Duration — java.time 패키지의 불변 클래스로, 초와 나노초 단위의 둘 사이의 기간을 나타냅니다. Duration은 시간 기반 시간 양—시간, 분, 초, 밀리초, 나노초를 측정합니다. Oracle Java 17 (2024)의 사양에 따르면, Period(년-월-일 측정)와 달리 Duration은 정확한 시간 단위로 작동하며 캘린더에 의존하지 않습니다.
요점
Duration은 초와 나노초로 시간 양을 모델링하는 클래스입니다. 캘린더에 역어지지 않은 물리적인 초 수의 시간 기반 기간을 나타냅니다. Duration은 “125분” 또는 “2시간 5분”으로 생각할 수 있지만, Period는 “2개월”이라고 할 것입니다.
Duration의 내부 표현은 long seconds(초) 및 int nanos(나노초, 0에서 999999999)의 두 필드로 구성됩니다. 값은 음수가 될 수 있으며, 이는 시간이 “뒤로” 가는 기간을 의미합니다. 최대값은 ±31557014167219200 초입니다.
Baeldung (2024)에 따르면, Duration은 작업 기간 계산, 타임아웃 설정 및 성능 측정에 중요한 클래스입니다. Duration은 불변이며 쓰레드 안전하여 동기화 없이 다중 쓰레드 환경에서 사용할 수 있습니다.
클래스는 Comparable, TemporalAmount 및 TemporalUnit 인터페이스를 구현합니다. TemporalAmount를 통해 LocalTime, LocalDateTime, Instant 및 ZonedDateTime 클래스의 plus/minus 메소드에서 Duration을 사용할 수 있습니다.
주요 차이점은 Duration이 정확한 초 수(시간 기반)를 측정하는 반면, Period는 캘린더 단위(날짜 기반)인 년, 월, 일을 측정한다는 것입니다. Duration은 “86400초가 경과했습니다”라고 하고, Period는 “1일이 경과했습니다”라고 합니다. 일광 절약 시간(DST) 변경 시 차이가 나타납니다. Period에서 1일은 험상 1 캘린더일이지만, Duration에서 86400초는 DST 중 23이나 25시간에 해당할 수 있습니다.
Duration은 물리적 시간 측정(접속 타임아웃, 케리 실행 시간, 두 Instant 간 간격)에 사용되고, Period는 캘린더 계산(개인의 나이, 계약 기간)에 사용됩니다.
Duration은 초와 나노초를 다루므로 부분(시간, 분)으로 나눠 수 있습니다. Period는 년, 월, 일을 다루며 분할할 수 없는 캘린더 단위입니다. Oracle Java Tutorial (2024)에 따르면 Duration과 Period 사이의 선택은 작업 유형에 따라 달라집니다. 정확한 시간 대 캘린더 날짜입니다.
가장 일반적인 방법은 Duration.between(Temporal start, Temporal end)입니다. Temporal은 Instant, LocalTime, LocalDateTime, ZonedDateTime 등 Temporal을 구현하는 임의 타입입니다. 메소드는 start - end 차이를 나타내는 Duration을 반환합니다(음수 가능).
정적 팩토리 메소드: Duration.ofSeconds(long), ofMinutes(long), ofHours(long), ofDays(long), ofMillis(long), ofNanos(long). 임의 단위를 위한 of(long amount, TemporalUnit unit)도 있습니다 — ChronoUnit.HOURS, ChronoUnit.MINUTES 등.
parse(CharSequence) 메소드는 ISO-8601 형식의 문자열을 수락합니다: “PT1H30M”(1시간 30분), “PT45S”(45초), “P2DT3H”(2일 3시간). 문자열은 험상 “PT”(Period of Time)로 시작합니다.
val betweenMoments = Duration.between(
Instant.parse("2026-07-21T10:00:00Z"),
Instant.parse("2026-07-21T14:30:00Z")
)
val fromMinutes = Duration.ofMinutes(90)
val fromHours = Duration.ofHours(2)
val parsed = Duration.parse("PT1H30M")
Duration은 완전한 산술 연산 세트를 지원합니다. plus(Duration) 및 minus(Duration) 메소드는 다른 기간을 더하거나 빼고, plusDays(), plusHours(), plusMinutes(), plusSeconds(), plusMillis(), plusNanos() 메소드는 특정 단위를 추가합니다.
곱셈과 나눗셈에는 multipliedBy(long) 및 dividedBy(long)을 사용합니다. Duration.multipliedBy(2)는 기간을 두 배로 달고, Duration.dividedBy(3)는 버림하여 세 부분으로 나№니다. negated() 메소드는 부호를 반전합니다 — 양수가 음수가 되고 그 반대도 마찬가지입니다.
abs() 메소드는 절대값(양수)을 가진 Duration을 반환합니다. isNegative() 및 isZero()는 확인 용입니다. toDays(), toHours(), toMinutes(), toSeconds(), toMillis(), toNanos()는 해당 단위로 변환합니다.
val oneHour = Duration.ofHours(1)
val twoHours = oneHour.plus(Duration.ofMinutes(60))
val halfHour = oneHour.dividedBy(2)
val minutes = twoHours.toMinutes()
val absDuration = (Duration.ofHours(-1)).abs()
Duration은 Comparable 인터페이스를 구현하여 기간을 자연스럽게 비교할 수 있습니다. compareTo() 메소드는 음수, 0 또는 양수를 반환합니다. isNegative()와 isZero()는 빠른 확인용입니다. 명시적인 비교는 equals()를 사용합니다 — 두 Duration은 초와 나노초가 일치하면 같습니다.
Duration은 음수가 될 수 있기 때문에 “크기” 또는 “작기” 비교는 부호를 고려하여 작동합니다. -5분은 2분보다 작습니다. abs() 메소드는 방향과 무관하게 “절대적” 길이를 비교하는 데 유용합니다.
Kotlin에서 Duration은 연산자 오버로딩을 통해 비교 연산자를 지원합니다: a < b, a > b, a <= b. 또한 plus와 minus는 연산자로 사용할 수 있습니다: a + b, a - b.
val short = Duration.ofMinutes(5)
val long = Duration.ofMinutes(10)
if (short < long) {
Log.d("Duration", "5분은 10보다 작습니다")
}
val negative = Duration.ofMinutes(-3)
Log.d("Duration", "음수: ${negative.isNegative()}")
첫 번째 예제는 서버와의 정기 동기화 설정입니다. Duration은 동기화 간격을 계산하고 업데이트 없이 시간 제한이 초과되었는지 확인하는 데 사용됩니다.
data class SyncConfig(
val interval: Duration = Duration.ofMinutes(15),
val retryDelay: Duration = Duration.ofSeconds(30)
)
fun calculateNextSync(
lastSync: Instant,
config: SyncConfig
): Duration {
val elapsed = Duration.between(lastSync, Instant.now())
return config.interval.minus(elapsed)
.coerceAtLeast(Duration.ZERO)
}
둘 번째 예제는 성능 로깅을 위한 작업 실행 시간 측정입니다.
fun measureExecution(
tag: String,
block: () -> Unit
) {
val start = Instant.now()
block()
val duration = Duration.between(start, Instant.now())
Log.d(tag, "${duration.toMillis()} ms로 실행됨")
}
셈 번째 예제는 타이머의 남은 시간 계산입니다(예: 프로모션 종료까지 카운트다운).
class CountdownTimer(
private val expiresAt: Instant
) {
fun getRemainingTime(): Duration {
val remaining = Duration.between(
Instant.now(), expiresAt
)
return remaining.coerceAtLeast(Duration.ZERO)
}
fun isExpired(): Boolean = getRemainingTime() == Duration.ZERO
}
toString() 메소드는 Duration을 ISO-8601 형식으로 반환합니다: “PT1H30M”(1시간 30분), “PT45.5S”(45.5초). 이 형식은 기계 간 교환에는 편리하지만 사용자 표시에는 적합하지 않습니다.
읽기 쉽고 알기 쉬운 형식을 위해서는 toDays(), toHours(), toMinutes(), toSeconds()를 사용한 후 직접 문자열을 작성합니다. 예: “${days} 일 ${hours} 시 ${minutes} 분”. toHours()는 하루 내의 시간이 아닌 총 시간을 반환한다는 것에 유의하세요.
Duration을 구성 요소로 분해하려면 공식을 사용합니다: val hours = duration.toHours(); val minutes = duration.toMinutes() % 60; val seconds = duration.seconds % 60. Apache Commons Lang (2024)에 따르면 DurationFormatUtils 라이브러리가 추가 형식 기능을 제공합니다.
fun formatDuration(duration: Duration): String {
val hours = duration.toHours()
val minutes = duration.toMinutes() % 60
val seconds = duration.seconds % 60
return buildString {
if (hours > 0) append("${hours} h ")
if (minutes > 0) append("${minutes} min ")
append("${seconds} sec")
}
}
처음 실수는 날짜를 다룰 때 Duration과 Period를 혼동하는 것입니다. Duration은 초를 기준으로 하므로 Duration.ofDays(1)은 일광 절약과 무관하게 험상 24시간(86400초)입니다. 캘린더일이 필요한 경우 Period.ofDays(1)을 사용하세요.
두 번째 실수는 변환 시 나노초을 잃는 것입니다. Duration은 나노초을 저장할 수 있지만 toMillis()와 toSeconds()는 그것들을 버립니다. 정확한 계산을 위해서는 toNanos()를 사용하거나 원시 타입으로 변환하지 않고 Duration을 직접 사용하세요.
셸 번째 실수는 음수 Duration을 무시하는 것입니다. Duration.between(start, end)는 start - end를 반환하고 start가 end 다음에 있는 경우 Duration은 음수가 됩니다. abs()는 절대값을, isNegative()는 인수 순서를 확인합니다.
너번째 실수는 UI에 대한 잘못된 Duration 형식화입니다. Duration.toString()은 ISO-8601을 반환하여 읽기 어렵습니다. 사용자에게 표시할 때는 toHours(), toMinutes() 및 toSeconds()를 사용하여 Duration을 직접 형식화하고, 올바른 나눘셈의 나머지를 사용하세요.
자주 묻는 질문
네, Duration은 음수가 될 수 있습니다. Duration.between(start, end)는 start - end를 반환하고, start가 end 다음에 있으면 Duration은 음수가 됩니다. 절대값을 얻려면 abs()를, 확인하려면 isNegative()를 사용하세요.
plus(Duration) 메소드나 Kotlin에서 + 연산자를 사용하세요: duration1 + duration2. 결과는 새로운 Duration입니다. minus(Duration) 메소드는 한 기간에서 다른 기간을 뻽니다. 모든 작업은 불변이며 새 객체를 반환합니다.
Duration.ofDays(1)은 험상 24시간(86400초)입니다. Period.ofDays(1)은 1 캘린더일로, DST 중에는 23이나 25시간이 될 수 있습니다. 정확한 시간 계산에는 Duration을, 캘린더 계산에는 Period를 사용하세요.
toMillis() 메소드를 사용하세요. long을 반환하며 Duration의 밀리초 수를 나타냅니다. 나노초에는 toNanos()를 사용하세요. 주의: toNanos()는 > 292년에서 long 오버플로우가 발생할 수 있습니다. 큰 Duration에는 toSeconds() 또는 toMinutes()를 사용하세요.
Duration.between(startTime, endTime)을 사용하세요. endTime이 startTime보다 작은 경우(야근), Duration은 음수가 됩니다. endTime이 다음 날이라고 가정하는 경우 24시간을 추가하세요: duration.plusHours(24).
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.