Duration — an immutable class from the java.time package representing the duration between two moments in time in seconds and nanoseconds. Duration measures time-based amounts of time — hours, minutes, seconds, milliseconds, and nanoseconds. According to the specification from Oracle Java 17 (2024), unlike Period (which measures years-months-days), Duration works with precise time units and does not depend on the calendar.
Key Takeaways
Duration is a class that models the amount of time in seconds and nanoseconds. It represents a time-based duration — that is, a physical number of seconds not tied to a calendar. Duration can be thought of as “125 minutes” or “2 hours 5 minutes” — unlike Period, which would say “2 months”.
The internal representation of Duration consists of two fields: long seconds and int nanos (0 to 999999999). The value can be negative — this means a duration “backward” in time. The maximum value is ±31557014167219200 seconds.
According to Baeldung (2024), Duration is a key class for calculating operation duration, setting timeouts, and measuring performance. Duration is immutable and thread-safe, allowing its use in multithreaded environments without synchronization.
The class implements the Comparable, TemporalAmount, and TemporalUnit interfaces. TemporalAmount allows Duration to be used in plus/minus methods of LocalTime, LocalDateTime, Instant, and ZonedDateTime classes.
The main difference is that Duration measures the exact number of seconds (time-based), while Period measures calendar units (date-based): years, months, days. Duration says: “86400 seconds have passed.” Period says: “1 day has passed.” The difference becomes apparent during daylight saving time transitions — 1 day in Period is always 1 calendar day, while 86400 seconds in Duration may correspond to 23 or 25 hours during DST.
Duration is used for measuring physical time: connection timeouts, query execution time, intervals between two Instants. Period is used for calendar calculations: a person’s age (Period.between(dateOfBirth, today)), contract duration.
Duration works with seconds and nanoseconds, so it can be divided into parts (hours, minutes). Period works with years, months, and days — indivisible calendar units. According to Oracle Java Tutorial (2024), the choice between Duration and Period depends on the type of task: precise time vs calendar dates.
The most common way is Duration.between(Temporal start, Temporal end). Temporal can be Instant, LocalTime, LocalDateTime, ZonedDateTime — any type implementing Temporal. The method returns a Duration representing the difference start - end (can be negative).
Static factory methods: Duration.ofSeconds(long), ofMinutes(long), ofHours(long), ofDays(long), ofMillis(long), ofNanos(long). There is also of(long amount, TemporalUnit unit) for arbitrary units — ChronoUnit.HOURS, ChronoUnit.MINUTES, and others.
The parse(CharSequence) method accepts a string in ISO-8601 format: “PT1H30M” (1 hour 30 minutes), “PT45S” (45 seconds), “P2DT3H” (2 days 3 hours). The string always starts with “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 supports a full set of arithmetic operations. Methods plus(Duration) and minus(Duration) add or subtract another duration. Methods plusDays(), plusHours(), plusMinutes(), plusSeconds(), plusMillis(), plusNanos() — for adding specific units.
For multiplication and division, use multipliedBy(long) and dividedBy(long). Duration.multipliedBy(2) doubles the duration. Duration.dividedBy(3) divides into three parts with rounding down. The negated() method inverts the sign — positive becomes negative and vice versa.
The abs() method returns a Duration with an absolute (positive) value. isNegative() and isZero() are checks. toDays(), toHours(), toMinutes(), toSeconds(), toMillis(), toNanos() convert to corresponding units.
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 implements the Comparable interface, allowing durations to be compared naturally. The compareTo() method returns a negative number, zero, or a positive number. isNegative() and isZero() are quick checks. For explicit comparison, use equals() — two Duration objects are equal if their seconds and nanoseconds match.
Since Duration can be negative, “greater than” or “less than” comparisons work with sign considered. -5 minutes is less than 2 minutes. The abs() method is useful when comparing “absolute” lengths regardless of direction.
In Kotlin, Duration supports comparison operators through operator overloading: a < b, a > b, a <= b. Plus and minus are also available as operators: a + b, a - b.
val short = Duration.ofMinutes(5)
val long = Duration.ofMinutes(10)
if (short < long) {
Log.d("Duration", "5 min is less than 10")
}
val negative = Duration.ofMinutes(-3)
Log.d("Duration", "Negative: ${negative.isNegative()}")
The first example is configuring periodic synchronization with the server. Duration is used to calculate the interval between synchronizations and check whether the time limit without updates has been exceeded.
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)
}
The second example is measuring operation execution time for performance logging.
fun measureExecution(
tag: String,
block: () -> Unit
) {
val start = Instant.now()
block()
val duration = Duration.between(start, Instant.now())
Log.d(tag, "Executed in ${duration.toMillis()} ms")
}
The third example is calculating the remaining time of a timer (for example, counting down to a promotion end).
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
}
The toString() method returns Duration in ISO-8601 format: “PT1H30M” (1 hour 30 minutes), “PT45.5S” (45.5 seconds). This format is convenient for machine exchange but not for user display.
For human-readable format, use toDays(), toHours(), toMinutes(), toSeconds() followed by manual string assembly. For example: “${days} d ${hours} h ${minutes} min”. Note that toHours() returns the total number of hours, not the hours within a day.
To break down Duration into components, use the formula: val hours = duration.toHours(); val minutes = duration.toMinutes() % 60; val seconds = duration.seconds % 60. According to Apache Commons Lang (2024), the DurationFormatUtils library provides additional formatting capabilities.
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")
}
}
The first mistake is confusing Duration and Period when working with dates. Duration measures seconds, so Duration.ofDays(1) is always 24 hours (86400 seconds), regardless of daylight saving time transitions. If you need a calendar day, use Period.ofDays(1).
The second mistake is losing nanoseconds during conversion. Duration can store nanoseconds, but toMillis() and toSeconds() discard them. For precise calculations, use toNanos() or work with Duration directly without converting to primitives.
The third mistake is ignoring negative Duration. Duration.between(start, end) returns start - end. If start is after end, Duration will be negative. The abs() method helps get the absolute value, and isNegative() checks the argument order.
The fourth mistake is incorrect Duration formatting for the UI. Duration.toString() returns ISO-8601, which is not human-readable. Always format Duration manually for user display using toHours(), toMinutes(), and toSeconds() with the correct remainder from division.
Frequently Asked Questions
Yes, Duration can be negative. Duration.between(start, end) returns start - end. If start is after end, Duration will be negative. Use abs() to get the absolute value or isNegative() to check.
Use the plus(Duration) method or the + operator in Kotlin: duration1 + duration2. The result is a new Duration. The minus(Duration) method subtracts one duration from another. All operations are immutable and return a new object.
Duration.ofDays(1) is always 24 hours (86400 seconds). Period.ofDays(1) is 1 calendar day, which during DST may be 23 or 25 hours. For precise time calculations, use Duration; for calendar calculations, use Period.
Use the toMillis() method. It returns a long — the number of milliseconds in the Duration. For nanoseconds, use toNanos(). Note: toNanos() may overflow long at values > 292 years. For large Durations, use toSeconds() or toMinutes().
Use Duration.between(startTime, endTime). If endTime is less than startTime (night shift), Duration will be negative. Add 24 hours: duration.plusHours(24), if endTime is assumed to be the next day.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also