Mobil inkişafda tarix və saat — mobil mühəndisliyin əsas mövzularından biridir. iOS DateFormatter və ISO8601DateFormatter istifadə edir, Android java.time-dan DateTimeFormatter və LocalDate istifadə edir. Android Developer Docs-a görə, tarix və saatın formatlanması üçün düzgün mobil API seçimi müxtəlif saat qurşaqlarında performansa və düzgün göstərilməyə birbaşa təsir edir.
Əsas məqamlar
iOS-da tarix və saat ənənəvi olaraq Foundation-dan DateFormatter vasitəsilə formatlanır. Bu sinif müəyyən edilmiş nümunə, lokal və saat qurşağından istifadə edərək Date-i sətirə və geri çevirir. DateFormatter-in əsas problemi — thread təhlükəsiz deyil və yavaş yaradılır, buna görə mobil kodda instansiyalar mütləq keşlənməlidir. iOS-da mobil inkişafda tarix düzgün formatlayıcı tələb edir.
DateFormatter yaratmaq təxminən 1 millisaniyə çəkir, çünki dateFormat nümunəsini təhlil etmək, lokalı yükləmək və saat qurşağını təyin etmək lazımdır. Yüzlərlə tarixin siyahısını formatlayarkən təkrar yaratmaq UI-də nəzərə çarpan gecikmələrə səbəb olur. Həll — formatlayıcını bütün ekran üçün bir dəfə yaradın və təkrar istifadə edin. Çox thread girişi üçün DispatchQueue vasitəsilə sinxronizasiyadan istifadə edin.
import Foundation
// Keşlənmiş DateFormatter — bir dəfə yaradılır
private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm"
formatter.locale = Locale(identifier: "ru_RU")
formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
return formatter
}()
// ISO8601DateFormatter — yüngül alternativ
private let isoFormatter: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter
}()
let now = Date()
let formattedDate = dateFormatter.string(from: now)
// "01.07.2026 14:30"
let isoDate = isoFormatter.string(from: now)
// "2026-07-01T14:30:00.000Z"
ISO 8601 formatı üçün ISO8601DateFormatter istifadə edin — nümunə tələb etmir və DateFormatter-dən daha sürətli işləyir. iOS 10+-da bu sinif server tarixləri ilə işləmək üçün üstünlük təşkil edir. Köhnə formatlar üçün DateFormatter saxlayın, lakin instansiyanı statik xüsusiyyət və ya singleton olaraq keşlədiyinizdən əmin olun.
Android-də tarix və saat API 26-dan etibarən mövcud olan java.time paketi vasitəsilə işlənir. Əsas siniflər: LocalDate (yalnız tarix), LocalTime (yalnız saat), LocalDateTime (saat qurşağı olmadan tarix və saat) və ZonedDateTime (saat qurşağı ilə). DateTimeFormatter — Android mobil platforması üçün thread təhlükəsiz formatlayıcı. Mobil tətbiqlərdə tarix performans itkisi olmadan DateTimeFormatter və LocalDate vasitəsilə formatlanır.
LocalDate vaxtsız tarixi saxlayır — ad günləri üçün idealdır. ZonedDateTime saat qurşağı ilə tam məlumatı saxlayır. DateTimeFormatter əvvəlcədən təyin edilmiş nümunələri (ISO_LOCAL_DATE, ISO_DATE_TIME) və ofPattern vasitəsilə fərdi nümunələri dəstəkləyir. Bütün java.time sinifləri dəyişməz və thread təhlükəsizdir, bu da çoxlu thread-lərdə işləyərkən yarış şərtlərini aradan qaldırır.
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.ZoneId
// Cari tarixin yaradılması və formatlanması
val today = LocalDate.now()
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val formatted = today.format(formatter)
// Saat qurşaqları ilə işləmək
val utcTime = ZonedDateTime.now(ZoneId.of("UTC"))
val moscowTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Moscow"))
DateTimeFormatter SimpleDateFormat-dən əhəmiyyətli dərəcədə daha səmərəlidir, çünki hər çağırışda nümunəni təhlil etmir. Formatlayıcı sabitlərini sinif və ya yoldaş obyekt səviyyəsində yaratmaq tövsiyə olunur. Unix Timestamp-ı çevirmək üçün Instant.ofEpochSecond istifadə edin, sonra saat qurşağı vasitəsilə LocalDateTime və ya ZonedDateTime-ə çevirin.
İstifadəçinin ekranında düzgün tarix və saat saat qurşaqlarının düzgün işlənməsindən asılıdır. Android üçün mobil inkişafda tarix və saat cihazın saat qurşağının nəzərə alınmasını tələb edir. Qızıl qayda: vaxtı UTC-də saxlayın, yalnız göstərmək üçün yerli saat qurşağına çevirin. iOS Foundation-dan TimeZone təqdim edir, Android java.time-dan ZoneId təqdim edir. Mobil platformalar üçün hər iki API cihazın cari saat qurşağını avtomatik aşkarlamanı dəstəkləyir. Mobil tətbiqdə tarix ZoneId və TimeZone-dan asılıdır.
Yay saatı qeyri-müəyyənlik yaradır: zamandakı bir an iki fərqli yerli saatla təmsil oluna bilər. java.time və Foundation DST-ni avtomatik idarə edir. IANA identifikatorlarından (Europe/Moscow, America/New_York) istifadə edin, abbreviaturalardan (MSK, EST) yox — abbreviaturalar qeyri-müəyyəndir və yay saatı keçidini nəzərə almır.
import Foundation
// UTC-nin iOS-da yerli vaxta çevrilməsi
func formatToLocalTime(utcDate: Date, timeZoneId: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm"
formatter.timeZone = TimeZone(identifier: timeZoneId)
return formatter.string(from: utcDate)
}
// Cihazın saat qurşağının müəyyən edilməsi
let localTimeZone = TimeZone.current
let isDST = localTimeZone.isDaylightSavingTime()
let secondsFromGMT = localTimeZone.secondsFromGMT()
Android-də cihazın saat qurşağını almaq üçün ZoneId.systemDefault() istifadə edin. UTC-ni yerli vaxta çevirərkən ZoneOffset.UTC ilə ZonedDateTime yaradın və withZoneSameInstant tətbiq edin. java.time olmayan köhnə API-lər üçün TimeZone.getDefault() və Calendar istifadə edin — lakin birbaşa ThreeTenABP əlavə etmək daha yaxşıdır.
import java.time.Instant
import java.time.ZonedDateTime
import java.time.ZoneId
// Unix Timestamp-ı yerli vaxta çevirin
fun toLocalDisplay(unixSeconds: Long): String {
val instant = Instant.ofEpochSecond(unixSeconds)
val local = instant.atZone(ZoneId.systemDefault())
return local.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"))
}
ThreeTenABP — java.time-ı Android API 26-dan aşağıya port edən adapter kitabxanasıdır. Eyni sinifləri təqdim edir: LocalDate, LocalTime, ZonedDateTime, DateTimeFormatter, Instant. Tətbiq Android 5 və ya 6-nı (API 21-25) dəstəkləyirsə, ThreeTenABP köhnəlmiş Calendar-a keçmədən müasir mobil API istifadə etməyin yeganə yoludur. Köhnə cihazlar üçün mobil inkişafda tarix və saat bu kitabxana vasitəsilə həyata keçirilir. Köhnə cihazlar üçün tarix və saat ThreeTenABP vasitəsilə həyata keçirilir.
Kitabxana Application.onCreate() metodunda AndroidThreeTen.init() çağıraraq başlatma tələb edir. Bu, assets-dən saat qurşağı məlumatlarını yükləyir. Başlatmadan sonra API tamamilə java.time ilə eynidir — API 26+ və API 21+ üçün kod eyni olacaq. Kitabxananın ölçüsü təxminən 400 KB-dır və əksər mobil tətbiqlər üçün məqbuldur.
import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter
// Application-da başlatma
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
// API java.time ilə eynidir
val today = LocalDate.now()
val formatted = today.format(DateTimeFormatter.ISO_LOCAL_DATE)
ThreeTenABP-nin performansı müasir cihazlarda orijinal java.time ilə müqayisə edilə bilər. Köhnə cihazlarda saat qurşağı məlumatlarının yüklənməsi səbəbindən ilk çağırışda gecikmə ola bilər. Mövcud kodu Calendar-dan ThreeTenABP-yə tədricən köçürün: yeni modullarda Date və Calendar-ı Instant və LocalDate ilə əvəz edin, köhnə kodu dəyişməz buraxın.
Unix Timestamp — 1 yanvar 1970 00:00 UTC-dən keçən saniyələrin sayıdır. Bu, server və müştəri arasında vaxtı saxlamaq və mübadilə etmək üçün universal formatdır. Lakin cihazdakı vaxt istifadəçi ayarları səbəbindən real vaxtdan fərqlənə bilər. Sinxronizasiya üçün NTP istifadə olunur — UDP üzərindən dəqiq vaxt protokolu. Unix Timestamp serverdə tarix və saatın saxlandığı formatdır.
iOS-da Date().timeIntervalSince1970 1970-ci ildən saniyələri qaytarır. Android-də System.currentTimeMillis() millisaniyələri qaytarır. Dəqiqlik üçün NTP istifadə edin: iOS üçün TrueTime kitabxanası və Android üçün AndroidNtp NTP serverinə sorğu göndərir və vaxt ofsetini hesablayır. NTP dəqiqliyi yerli şəbəkədə 1-10 ms və internet üzərindən 10-100 ms təşkil edir.
import Foundation
// iOS-da Unix Timestamp əldə etmə
let seconds = Date().timeIntervalSince1970
let milliseconds = Int64(seconds * 1000)
// TrueTime ilə NTP sinxronizasiyası
TrueTime.shared.start { result in
switch result {
case .success:
let ntpTime = TrueTime.shared.now()
print("Dəqiq vaxt: \(ntpTime)")
case .failure(let error):
print("NTP xətası: \(error)")
}
}
Mobil tətbiqdə sinxronizasiya olmadan səhvlər mümkündür: səhv hadisə vaxt damğaları, serverlə desinxronizasiya. Mobil inkişafda vaxt tətbiq başlayarkən bir dəfə NTP vasitəsilə sinxronlaşdırılır, bundan sonra hesablanmış ofset istifadə olunur. Dəqiqlik baxımından kritik mobil tətbiqlər (maliyyə, logistika) üçün serverə məlumat göndərməzdən əvvəl NTP protokolu məcburidir.
Tez-tez verilən suallar
DateFormatter hər dəfə instansiya yaradıldıqda formatlama nümunəsini təhlil edir, lokalı yükləyir və saat qurşağını təyin edir. Formatlayıcını statik sabit kimi keşləyin və ya ISO 8601 üçün ISO8601DateFormatter istifadə edin — daha yüngül və sürətlidir.
java.time paketindən DateTimeFormatter — thread təhlükəsiz və səmərəli. API 26-dan etibarən mövcuddur. Köhnə versiyalar üçün eyni API təmin edən ThreeTenABP istifadə edin.
ThreeTenABP əlavə edin — Android API 21+ üçün java-time backport-u. Application.onCreate()-də AndroidThreeTen.init() vasitəsilə başladın. API orijinal java.time ilə tamamilə eynidir.
Bəli, serverdə və yerli verilənlər bazasında vaxtı UTC-də saxlayın. Yalnız göstərmə mərhələsində istifadəçinin yerli saat qurşağına çevirin. Bu, saat qurşağını dəyişdirərkən və ya səyahət edərkən səhvləri aradan qaldırır.
Date().timeIntervalSince1970 1 yanvar 1970-ci ildən saniyələrin sayını qaytarır. Millisaniyələr üçün 1000-ə vurun və Int64-ə çevirin. Dəqiq sinxronizasiya üçün NTP serveri ilə TrueTime kitabxanasından istifadə edin.
Xülasə
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.