Instant: bu nədir, vaxt damğası və proqramlaşdırmada tətbiqi

Müəllif: IT Sectr Dərc olunub: 2026-07-13 Oxuma vaxtı: 9 dəq

Instant — java.time paketindən olan, UTC-də vaxt oxunda nöqtəni nanosaniyə dəqiqliyi ilə təmsil edən dəyişməz sinif. LocalDateTime-dan fərqli olaraq, Instant insan tərəfindən oxuna bilən formada tarix və vaxtı ehtiva etmir — bu anın maşın təmsilidir. Oracle Java 17 (2024) spesifikasiyasına görə, Instant maşın vaxt damğası mübadiləsi üçün nəzərdə tutulmuşdur və System.currentTimeMillis() analoqudur, lakin nanosaniyə dəqiqliyi ilə.

Əsas məqamlar

  • Instant — UTC-də nanosaniyə dəqiqliyi ilə vaxt anı, dəyişməz və thread-safe.
  • Vaxtı epoxadan (1970-01-01T00:00:00Z) saniyələrin sayı üstəgəl nanosaniyələr kimi saxlayır.
  • Instant.now() cihazın saat qurşağından asılı olmayaraq cari anı UTC-də qaytarır.
  • İnsan tərəfindən oxuna bilən formata çevirmək üçün atZone(ZoneId) istifadə olunur, ZonedDateTime qaytarır.
  • Instant — API və paylanmış sistemlərdə vaxt damğalarının ötürülməsi üçün üstünlük verilən tipdir.

Instant nədir?

Instant — vaxt oxunda tək nöqtəni modelləşdirən sinifdir. Onun daxili təmsili iki sahədən ibarətdir: long seconds (1970-01-01T00:00:00Z-dən saniyələrin sayı) və int nanos (cari saniyə daxilində nanosaniyələr, 0-dan 999999999-a qədər).

Instant dəyərlərinin diapazonu — epoxadan -31557014167219200-dən 31556889864403199 saniyəyə qədər, bu da hər iki istiqamətdə təxminən 292 milyon ili əhatə edir. Bu, astronomik hesablamalar da daxil olmaqla istənilən praktik tapşırıq üçün kifayətdir.

Baeldung (2024)-ə görə, Instant insan tərəfindən oxuna bilən tiplər (LocalDateTime, ZonedDateTime) ilə maşın formatları (millisaniyələrdə timestamp) arasında körpüdür. Instant logging, keşləmə, sinxronizasiya və vaxtın mütləq anının vacib olduğu bütün tapşırıqlar üçün istifadə olunur.

Sinif Comparable (anları müqayisə etmək üçün) və Temporal (java.time ümumi API-də istifadə üçün) interfeyslərini tətbiq edir. Instant dəyişməzdir — bütün metodlar yeni obyekt qaytarır.

Instant vs Date vs Long

Java 8-dən əvvəl vaxt anları ilə işləmək üçün java.util.Date və System.currentTimeMillis() istifadə olunurdu. Hər iki yanaşmanın çatışmazlıqları var. Date dəyişkəndir, thread-safe deyil, vaxtı epoxadan millisaniyələrlə saxlayır, lakin metod adları köhnəlmişdir (getYear() 2016 üçün 116 qaytarır).

Long (sadə timestamp) sürətli və yığcamdır, lakin nanosaniyələr üçün daxili dəstəyi yoxdur, oxuna bilən formada göstərilmir və debug zamanı əl ilə pars etmə tələb edir. Long yanaşması həmçinin məlumat növünü fərqləndirmir — proqramçı səhv dəyər ötürə bilər.

Instant bütün bu problemləri həll edir. O, dəyişməzdir, dəqiqlik haqqında aşkar məlumatı ehtiva edir (saniyələr + nanosaniyələr), ISO-8601 „2026-07-21T15:00:00Z“ formatına serializasiya olunur və çevrilmələr üçün zəngin API-ə malikdir. SonarSource (2024)-ə görə, Instant bütün yeni layihələrdə Date üçün tövsiyə olunan əvəzedicidir.

Instant-ın yaradılması və oxunması

Cari an Instant.now() vasitəsilə əldə edilir. LocalDateTime.now()-dan fərqli olaraq, Instant.now() həmişə vaxtı UTC-də qaytarır, cihazın saat qurşağını nəzərə almır. Bu onu server vaxt damğaları üçün ideal edir.

Mövcud dəyərlərdən: Instant.ofEpochSecond(long epochSecond) — epoxadan saniyələrlə, Instant.ofEpochMilli(long epochMilli) — millisaniyələrlə, Instant.parse(CharSequence) — ISO-8601 sətirindən („2026-07-21T15:00:00Z“).

Oxumaq üçün getEpochSecond() — epoxadan saniyələrin sayı, toEpochMilli() — millisaniyələrin sayı, getNano() — nanosaniyələr istifadə olunur. toString() metodu ISO-8601 formatında sətir qaytarır.

kotlin
val now = Instant.now()

val fromSeconds = Instant.ofEpochSecond(1784700000)
val fromMillis = Instant.ofEpochMilli(1784700000000)
val parsed = Instant.parse("2026-07-21T15:00:00Z")

val epochSecond = now.getEpochSecond()
val epochMilli = now.toEpochMilli()
val nanos = now.getNano()

Instant-ın digər formatlara çevrilməsi

Instant ZonedDateTime-yə atZone(ZoneId) vasitəsilə çevrilir. Məsələn, Instant.now().atZone(ZoneId.of("Europe/Moscow")) Moskva üçün ZonedDateTime qaytaracaq. Qurşaq olmadan çevirmə mümkün deyil — Instant təqvim məlumatını ehtiva etmir.

LocalDateTime-ə Instant atZone(ZoneId).toLocalDateTime() vasitəsilə çevrilir. Bu üsul aşkardır və məlumat itkisinə yol vermir. Əks çevirmə — LocalDateTime.atZone(ZoneId).toInstant().

java.util.Date ilə uyğunluq üçün: Date.from(instant) və date.toInstant(). Bu, millisaniyəyə qədər dəqiqliyi qoruyan ikitərəfli çevirmədir (Date nanosaniyələri dəstəkləmir). java.sql.Timestamp ilə işləmək üçün nanosaniyə dəstəyi ilə Timestamp.from(instant) istifadə olunur.

kotlin
val instant = Instant.now()

val zoned = instant.atZone(ZoneId.of("Europe/Moscow"))
val localDateTime = instant
    .atZone(ZoneId.systemDefault())
    .toLocalDateTime()

val oldDate = Date.from(instant)
val backToInstant = oldDate.toInstant()

Instant və saat qurşaqları

Instant-ın əsas xüsusiyyəti — o, saat qurşaqlarından tamamilə müstəqildir. Instant.now() dünyanın istənilən nöqtəsində istənilən cihazda eyni nəticəni qaytarır. Bu, vaxtın UTC-də təsbit edilməsi ilə əldə olunur.

Saat qurşağı yalnız Instant-ı insana göstərmək üçün lazımdır. Bunun üçün atZone(ZoneId) istifadə olunur. ZoneId.systemDefault() əməliyyat sistemində quraşdırılmış cihazın saat qurşağını qaytarır. ZoneOffset.UTC — UTC üçün sabit.

Paylanmış sistemlərdə bütün vaxt damğalarını Instant (və ya ZoneOffset.UTC ilə OffsetDateTime) şəklində saxlamaq və ötürmək tövsiyə olunur. Yerli vaxta çevirmə yalnız müştəri tərəfdə istifadəçiyə göstərməzdən əvvəl aparılır. Bu, saat qurşaqları ilə bağlı qarışıqlığın qarşısını alır.

Instant vasitəsilə vaxt sinxronizasiyası

Paylanmış Android tətbiqlərində vaxt sinxronizasiyası keşləmə, bildirişlər və birgə redaktə üçün vacibdir. Instant UTC-yə bağlı olduğuna görə bu tapşırıq üçün təbii seçimdir.

Müxtəlif cihazlardan vaxt damğalarını müqayisə edərkən sistem saatlarının üst-üstə düşməyə biləcəyini nəzərə almaq lazımdır. İstinad kimi server vaxtından istifadə etmək tövsiyə olunur. Server Instant-ı UTC-də qaytarır, müştəri yalnız nisbi hesablamalar üçün lokal Instant ilə müqayisə edir.

İki an arasındakı fərqi hesablamaq üçün Duration.between(Instant start, Instant end) istifadə olunur. Bu metod müddəti qaytarır — saatlara, dəqiqələrə, saniyələrə çevrilə bilən Duration. isAfter() və isBefore() metodları anları müqayisə etməyə imkan verir.

kotlin
fun isCacheExpired(
    cachedAt: Instant,
    ttlMinutes: Long
): Boolean {
    val elapsed = Duration.between(cachedAt, Instant.now())
    return elapsed.toMinutes() >= ttlMinutes
}

Android-də praktik nümunələr

Birinci nümunə — vaxt damğası ilə hadisələrin jurnallaşdırılması. Instant Room verilənlər bazasında saxlanılır və serverə ötürülür. Vaxt damğası birmənalı şərh üçün UTC-də jurnallaşdırılır.

kotlin
data class EventLog(
    val id: Long = 0,
    val eventName: String,
    val timestamp: Instant
)

class Converters {
    @TypeConverter
    fun fromInstant(value: Instant?): Long? {
        return value?.toEpochMilli()
    }

    @TypeConverter
    fun toInstant(value: Long?): Instant? {
        return value?.let { Instant.ofEpochMilli(it) }
    }
}

İkinci nümunə — hadisədən keçən vaxtın təyin edilməsi. Duration.between istifadə edərək „5 dəqiqə əvvəl“, „2 saat əvvəl“ — messencerlərdə və sosial şəbəkələrdə geniş yayılmış formatı göstəririk.

kotlin
fun timeAgo(instant: Instant): String {
    val duration = Duration.between(instant, Instant.now())
    return when {
        duration.toMinutes() < 1 -> "just now"
        duration.toHours() < 1 -> "${duration.toMinutes()} min ago"
        duration.toDays() < 1 -> "${duration.toHours()} h ago"
        else -> "${duration.toDays()} d ago"
    }
}

Üçüncü nümunə — server və müştəri arasında verilənlərin sinxronizasiyası. Son yeniləmə vaxtını izləmək üçün Instant istifadə edirik.

kotlin
class SyncManager {
    private var lastSyncAt: Instant? = null

    fun sync() {
        val syncStart = Instant.now()
        // lastSyncAt ilə server sorğusu
        lastSyncAt = syncStart
    }

    fun shouldSync(intervalMinutes: Long): Boolean {
        val last = lastSyncAt ?: return true
        return Duration.between(last, Instant.now())
            .toMinutes() >= intervalMinutes
    }
}

Tipik səhvlər

Birinci səhv — istifadəçiyə göstərmək üçün Instant.now().toString() istifadə etmək. Instant UTC formatında „2026-07-21T15:00:00Z“ çıxışı verir, bu insan üçün oxunmazdır. Həmişə Instant-ı göstərməzdən əvvəl atZone() vasitəsilə lokal saat qurşağına çevirin.

İkinci səhv — java.util.Date-ə çevirərkən nanosaniyələrin itirilməsi. Date yalnız millisaniyələri dəstəkləyir. Instant-ın nanosaniyələri varsa, onlar Date.from(instant) zamanı itiriləcək. Dəqiqliyi açıq şəkildə göstərmək üçün Instant.truncatedTo(ChronoUnit.MILLIS) istifadə edin.

Üçüncü səhv — toEpochMilli() və getEpochSecond()-in qarışdırılması. toEpochMilli() epoxadan millisaniyələrin sayını (long) qaytarır, getEpochSecond() isə saniyələrin sayını (long). Bu metodları qarışdırmaq 1000 dəfə səhvə səbəb ola bilər.

Dördüncü səhv — Instant.now()-un bütün cihazlarda sinxronlaşdırıldığını güman etmək. Sistem saatları dəqiqələrlə, hətta saatlarla fərqlənə bilər. Vaxta həssas əməliyyatlar (autentifikasiya, ödənişlər) üçün həqiqət mənbəyi kimi server Instant-ından istifadə edin.

Tez-tez verilən suallar

Instant System.currentTimeMillis()-dan nə ilə fərqlənir?

System.currentTimeMillis() long qaytarır — saat qurşağına bağlı olmadan epoxadan millisaniyələrin sayı. Instant eyni funksionallığı təmin edir, lakin nanosaniyə dəqiqliyi və çevrilmələr, müqayisələr və java.time ilə uyğunluq üçün zəngin API ilə.

Instant-ı Room verilənlər bazasında necə saxlamaq olar?

Room Instant-ı birbaşa dəstəkləmir. Instant-ı Long-a (toEpochMilli) və geri (Instant.ofEpochMilli) çevirən TypeConverter istifadə edin. Nanosaniyə dəqiqliyi üçün iki sahə saxlayın: epoxa-saniyələr və nanosaniyələr.

Instant-ı HashMap-də açar kimi istifadə etmək olar?

Bəli, Instant dəyişməzdir və equals() və hashCode()-u düzgün tətbiq edir. Eyni dəyərə malik iki Instant bərabər olacaq. Bu, onu dəyişkən java.util.Date-dən fərqli olaraq HashMap və digər kolleksiyalar üçün etibarlı açar edir.

İki Instant arasındakı fərqi necə əldə etmək olar?

Duration.between(start, end) istifadə edərək Duration əldə edin və ya saniyələrlə fərq üçün (long) ChronoUnit.SECONDS.between(start, end). Duration toMinutes(), toHours(), toDays() və toNanos() metodlarını təqdim edir.

Niyə Instant.parse() Z suffiksi və ya yerdəyişmə tələb edir?

Instant vaxt oxunda mütləq nöqtə kimi dizayn edilmişdir. Saat qurşağı və ya UTC göstərilmədən pars etmək mümkün deyil, çünki Instant təqvim məlumatını ehtiva etmir. „Z“ suffiksi sıfır yerdəyişməni (UTC) bildirir və ISO-8601 formatı üçün məcburidir.

Nəticə

  • Instant — UTC-də mütləq vaxt anı üçün nanosaniyə dəqiqliyi ilə dəyişməz sinif, paylanmış sistemlərdə vaxt damğaları üçün üstünlük verilir.
  • java.util.Date-dən fərqli olaraq, Instant dəyişməz, thread-safe və nanosaniyə dəqiqliyinə malikdir. Long-dan fərqli olaraq — açıq şəkildə tipləşdirilmişdir və digər ədədi dəyərlərlə qarışıqlığa yol vermir.
  • İstifadəçiyə göstərmək üçün Instant atZone(ZoneId) vasitəsilə ZonedDateTime-ə çevrilir, əks halda vaxt UTC-də göstəriləcək.
  • API-ə ötürmək üçün Instant.toString() (ISO-8601) və ya köhnə formatlarla uyğunluq üçün toEpochMilli() istifadə edin.
  • Room ilə işləyərkən Instant-ı TypeConverter vasitəsilə toEpochMilli() metodu ilə Long kimi saxlayın.
  • Keçən vaxtı hesablamaq üçün nanosaniyələri düzgün idarə edən Duration.between() istifadə edin.
  • Cihaz saatlarının sinxronizasiyasına etibar etməyin — kritik əməliyyatlar üçün həqiqət mənbəyi kimi server Instant-ından istifadə edin.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun