Duration — چیست، محاسبه مدت زمان در Android

نویسنده: IT Sectr منتشر شده: 2026-07-13 زمان مطالعه: 9 دقیقه

Duration — کلاس تغییرناپذیر از بسته java.time که مدت زمان بین دو لحظه را بر حسب ثانیه و نانوثانیه نشان می‌دهد. Duration مقدار زمان مبتنی بر زمان — ساعت‌ها، دقیقه‌ها، ثانیه‌ها، میلی‌ثانیه‌ها و نانوثانیه‌ها را اندازه‌گیری می‌کند. طبق مشخصات Oracle Java 17 (2024)، برخلاف Period (که سال-ماه-روز را اندازه‌گیری می‌کند)، Duration با واحدهای زمانی دقیق کار می‌کند و به تقویم وابسته نیست.

نکات اصلی

  • Duration — کلاس تغییرناپذیر برای اندازه‌گیری مدت زمان بر حسب ثانیه و نانوثانیه.
  • برخلاف Period، Duration با واحدهای مبتنی بر زمان (ساعت، دقیقه، ثانیه) کار می‌کند، نه مبتنی بر تاریخ (روز، ماه، سال).
  • از طریق Duration.between(start, end)، Duration.ofMinutes()، Duration.ofHours() و سایر کارخانه‌های ایستا ایجاد می‌شود.
  • عملیات حسابی را پشتیبانی می‌کند: plus()، minus()، multipliedBy()، dividedBy()، negated().
  • برای توسعه Android، Duration برای محاسبه مهلت‌های زمانی، فواصل همگام‌سازی و مدت زمان عملیات مفید است.

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 در مقابل Period: تفاوت چیست؟

تفاوت اصلی — 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

رایج‌ترین روش — 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) شروع می‌شود.

kotlin
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

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() — تبدیل به واحدهای مربوطه.

kotlin
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

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.

kotlin
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 در وظایف واقعی Android

مثال اول — تنظیم همگام‌سازی دوره‌ای با سرور. Duration برای محاسبه فاصله بین همگام‌سازی‌ها و بررسی اینکه آیا محدودیت زمان بدون به‌روزرسانی فراتر رفته است استفاده می‌شود.

kotlin
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)
}

مثال دوم — اندازه‌گیری زمان اجرای عملیات برای ثبت عملکرد.

kotlin
fun measureExecution(
    tag: String,
    block: () -> Unit
) {
    val start = Instant.now()
    block()
    val duration = Duration.between(start, Instant.now())
    Log.d(tag, "اجرا شده در ${duration.toMillis()} میلی‌ثانیه")
}

مثال سوم — محاسبه زمان باقیمانده تایمر (مثلاً برای شمارش معکوس تا پایان یک تبلیغ).

kotlin
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
}

تبدیل Duration به رشته

متد 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 قابلیت‌های اضافی فرمت‌دهی را فراهم می‌کند.

kotlin
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 می‌تواند منفی باشد. Duration.between(start, end) start - end را برمی‌گرداند. اگر start بعد از end باشد، Duration منفی خواهد بود. برای دریافت مقدار مطلق از abs() یا برای بررسی از isNegative() استفاده کنید.

چگونه دو Duration را جمع کنیم؟

از متد plus(Duration) یا عملگر + در Kotlin استفاده کنید: duration1 + duration2. نتیجه — یک Duration جدید. متد minus(Duration) یک مدت را از دیگری کم می‌کند. همه عملیات تغییرناپذیر هستند و یک شیء جدید برمی‌گردانند.

تفاوت Duration.ofDays(1) با Period.ofDays(1) چیست؟

Duration.ofDays(1) همیشه 24 ساعت (86400 ثانیه) است. Period.ofDays(1) یک روز تقویمی است که در DST ممکن است 23 یا 25 ساعت باشد. برای محاسبات با زمان دقیق از Duration، برای محاسبات تقویمی از Period استفاده کنید.

چگونه Duration را به میلی‌ثانیه تبدیل کنیم؟

از متد toMillis() استفاده کنید. این تعداد میلی‌ثانیه‌ها را به صورت long برمی‌گرداند. برای نانوثانیه از toNanos() استفاده کنید. توجه: toNanos() ممکن است در مقادیر > 292 سال سرریز شود. برای Duration بزرگ از toSeconds() یا toMinutes() استفاده کنید.

چگونه Duration بین دو LocalTime را محاسبه کنیم؟

از Duration.between(startTime, endTime) استفاده کنید. اگر endTime کوچکتر از startTime باشد (شیفت شب)، Duration منفی خواهد بود. 24 ساعت اضافه کنید: duration.plusHours(24)، اگر فرض می‌کنید endTime روز بعد است.

خلاصه

  • Duration — کلاس تغییرناپذیر برای مدت زمان مبتنی بر زمان با دقت نانوثانیه، ایده‌آل برای اندازه‌گیری فواصل.
  • تفاوت اصلی با Period — Duration ثانیه‌ها (زمان فیزیکی) را اندازه‌گیری می‌کند، Period — واحدهای تقویمی.
  • از طریق Duration.between() برای تفاوت بین لحظات یا از طریق کارخانه‌های ایستا ofMinutes، ofHours، ofDays ایجاد می‌شود.
  • حساب را پشتیبانی می‌کند: plus، minus، multipliedBy، dividedBy، همچنین مقایسه از طریق Comparable و abs.
  • در Android، Duration برای محاسبه مهلت‌های زمانی، فواصل همگام‌سازی، تایمرها و اندازه‌گیری عملکرد استفاده می‌شود.
  • هنگام نمایش به کاربر، Duration را دستی فرمت کنید — toString() ISO-8601 را برمی‌گرداند که برای انسان قابل خواندن نیست.
  • توجه داشته باشید که Duration می‌تواند منفی باشد — isNegative() را بررسی کنید و برای محاسبات صحیح از abs() استفاده کنید.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید