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 تغییرناپذیر و thread-safe است که امکان استفاده از آن را در محیط چندنخی بدون همگامسازی فراهم میکند.
این کلاس رابطهای Comparable، TemporalAmount و TemporalUnit را پیادهسازی میکند. TemporalAmount امکان استفاده از Duration را در متدهای plus/minus کلاسهای LocalTime، LocalDateTime، Instant و ZonedDateTime فراهم میکند.
تفاوت اصلی — Duration تعداد دقیق ثانیهها (time-based) را اندازهگیری میکند، در حالی که Period واحدهای تقویمی (date-based): سال، ماه، روز را اندازهگیری میکند. Duration میگوید: «86400 ثانیه گذشته است». Period میگوید: «1 روز گذشته است». تفاوت در تغییر ساعت تابستانی نمایان میشود — 1 روز در Period همیشه برابر با 1 روز در تقویم است، در حالی که 86400 ثانیه در Duration ممکن است در DST معادل 23 یا 25 ساعت باشد.
Duration برای اندازهگیری زمان فیزیکی استفاده میشود: مهلتهای اتصال، زمان اجرای درخواست، فاصله بین دو Instant. Period برای محاسبات تقویمی استفاده میشود: سن فرد (Period.between(تاریختولد, امروز))، مدت اعتبار قرارداد.
Duration با ثانیه و نانوثانیه کار میکند، بنابراین میتوان آن را به بخشها (ساعت، دقیقه) تقسیم کرد. Period با سال، ماه و روز — واحدهای تقویمی غیرقابل تقسیم — کار میکند. به گفته Oracle Java Tutorial (2024)، انتخاب بین Duration و Period به نوع وظیفه بستگی دارد: زمان دقیق در مقابل تاریخهای تقویمی.
رایجترین روش — Duration.between(Temporal start, Temporal end). Temporal میتواند Instant، LocalTime، LocalDateTime، ZonedDateTime — هر نوعی که Temporal را پیادهسازی کند. متد Duration نشاندهنده تفاوت start - end را برمیگرداند (میتواند منفی باشد).
متدهای کارخانهای ایستا: 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() عدد منفی، صفر یا مثبت برمیگرداند. متدهای 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()} میلیثانیه")
}
مثال سوم — محاسبه زمان باقیمانده تایمر (مثلاً برای شمارش معکوس تا پایان یک تبلیغ).
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() — ترتیب آرگومانها را بررسی کند.
اشتباه چهارم — فرمتدهی نادرست Duration برای UI. Duration.toString() ISO-8601 را برمیگرداند که غیرقابل خواندن است. همیشه Duration را برای نمایش به کاربر دستی فرمت کنید، با استفاده از toHours()، toMinutes() و toSeconds() با باقیمانده تقسیم صحیح.
سوالات متداول
بله، 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) یک روز تقویمی است که در DST ممکن است 23 یا 25 ساعت باشد. برای محاسبات با زمان دقیق از Duration، برای محاسبات تقویمی از Period استفاده کنید.
از متد toMillis() استفاده کنید. این تعداد میلیثانیهها را به صورت long برمیگرداند. برای نانوثانیه از toNanos() استفاده کنید. توجه: toNanos() ممکن است در مقادیر > 292 سال سرریز شود. برای Duration بزرگ از toSeconds() یا toMinutes() استفاده کنید.
از Duration.between(startTime, endTime) استفاده کنید. اگر endTime کوچکتر از startTime باشد (شیفت شب)، Duration منفی خواهد بود. 24 ساعت اضافه کنید: duration.plusHours(24)، اگر فرض میکنید endTime روز بعد است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید