Data și ora în dezvoltarea mobilă: ce este, ce formate și cum se lucrează

Autor: IT Sectr Publicat: 2026-07-22 Timp de citire: 11 min

Data și ora în dezvoltarea mobilă — unul dintre subiectele cheie în ingineria mobilă. iOS folosește DateFormatter și ISO8601DateFormatter, Android folosește DateTimeFormatter și LocalDate din java.time. Conform Android Developer Docs, alegerea corectă a API-ului mobil pentru formatarea datei și orei afectează direct performanța și corectitudinea afișării în diferite fusuri orare.

Puncte principale

  • DateFormatter pe iOS — puternic, dar lent la crearea frecventă. Stocați în cache instanțele sau utilizați ISO8601DateFormatter pentru formatul ISO 8601.
  • DateTimeFormatter pe Android — formator thread-safe din java.time. A înlocuit SimpleDateFormat învechit începând cu API 26.
  • ThreeTenABP — backport al java.time pentru Android API sub 26. Adaugă LocalDate, ZonedDateTime și DateTimeFormatter pe dispozitivele vechi.
  • TimeZone — esențial pentru conversia UTC în ora locală. Stocați timpul în UTC, afișați în fusul orar al utilizatorului.
  • Unix Timestamp — format standard de stocare a timpului. Sincronizarea prin NTP garantează precizie la milisecundă.

Data și ora pe iOS: DateFormatter și ISO8601DateFormatter

Pe iOS, data și ora sunt formatate în mod tradițional prin DateFormatter din Foundation. Această clasă convertește Date în șir și invers folosind un model, o setare regională și un fus orar specificate. Problema principală a DateFormatter — nu este thread-safe și se creează lent, prin urmare, în codul mobil, instanțele trebuie stocate în cache. Data în dezvoltarea mobilă pe iOS necesită formatorul corect.

DateFormatter și performanța

Crearea unui DateFormatter durează aproximativ 1 milisecundă din cauza analizei modelului dateFormat, încărcării setării regionale și determinării fusului orar. La formatarea unei liste de sute de date, crearea repetată duce la întârzieri vizibile în UI. Soluția — creați formatorul o dată pentru întregul ecran și reutilizați-l. Pentru acces multi-thread, utilizați sincronizarea prin DispatchQueue.

swift
import Foundation

// DateFormatter stocat în cache — creat o dată
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 — alternativă ușoară
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"

Pentru formatul ISO 8601, utilizați ISO8601DateFormatter — nu necesită specificarea unui model și funcționează mai rapid decât DateFormatter. Pe iOS 10+, această clasă este preferată pentru lucrul cu datele serverului. Pentru formatele vechi, păstrați DateFormatter dar asigurați-vă că stocați în cache instanța ca proprietate statică sau singleton.

Data și ora pe Android: java.time și DateTimeFormatter

Pe Android, data și ora sunt procesate prin pachetul java.time, disponibil de la API 26. Clase principale: LocalDate (doar dată), LocalTime (doar oră), LocalDateTime (dată și oră fără fus orar) și ZonedDateTime (cu fus orar). DateTimeFormatter — un formator thread-safe pentru platforma mobilă Android. Data în aplicațiile mobile este formatată prin DateTimeFormatter și LocalDate fără pierdere de performanță.

LocalDate, ZonedDateTime și formatarea

LocalDate stochează data fără oră — ideal pentru zile de naștere. ZonedDateTime stochează informații complete cu fus orar. DateTimeFormatter suportă modele predefinite (ISO_LOCAL_DATE, ISO_DATE_TIME) și personalizate prin ofPattern. Toate clasele java.time sunt imutabile și thread-safe, ceea ce elimină condițiile de cursă la lucrul în mai multe fire de execuție.

kotlin
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.ZoneId

// Crearea și formatarea datei curente
val today = LocalDate.now()
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val formatted = today.format(formatter)

// Lucrul cu fusurile orare
val utcTime = ZonedDateTime.now(ZoneId.of("UTC"))
val moscowTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Moscow"))

DateTimeFormatter este semnificativ mai performant decât SimpleDateFormat deoarece nu analizează modelul la fiecare apel. Se recomandă crearea constantelor de formator la nivel de clasă sau obiect companion. Pentru conversia Unix Timestamp, utilizați Instant.ofEpochSecond, apoi convertiți în LocalDateTime sau ZonedDateTime prin fusul orar.

Fusuri orare: data și ora în aplicațiile mobile și TimeZone

Data și ora corecte pe ecranul utilizatorului depind de procesarea corespunzătoare a fusurilor orare. Data și ora în dezvoltarea mobilă pentru Android necesită luarea în considerare a fusului orar al dispozitivului. Regula de aur: stocați timpul în UTC, convertiți în fusul orar local doar pentru afișare. iOS oferă TimeZone din Foundation, Android oferă ZoneId din java.time. Ambele API-uri pentru platforme mobile suportă detectarea automată a fusului orar curent al dispozitivului. Data într-o aplicație mobilă depinde de ZoneId și TimeZone.

Ora de vară și identificatorii IANA

Ora de vară creează ambiguitate: un moment în timp poate fi reprezentat de două ore locale diferite. java.time și Foundation gestionează DST automat. Utilizați identificatori IANA (Europe/Moscow, America/New_York), nu abrevieri (MSK, EST) — abrevierile sunt ambigue și ignoră trecerea la ora de vară.

swift
import Foundation

// Conversia UTC în ora locală pe iOS
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)
}

// Determinarea fusului orar al dispozitivului
let localTimeZone = TimeZone.current
let isDST = localTimeZone.isDaylightSavingTime()
let secondsFromGMT = localTimeZone.secondsFromGMT()

Pe Android, utilizați ZoneId.systemDefault() pentru a obține fusul orar al dispozitivului. La conversia UTC în ora locală, creați un ZonedDateTime cu ZoneOffset.UTC și aplicați withZoneSameInstant. Pentru API-uri vechi fără java.time, utilizați TimeZone.getDefault() și Calendar — dar este mai bine să adăugați direct ThreeTenABP.

kotlin
import java.time.Instant
import java.time.ZonedDateTime
import java.time.ZoneId

// Convertiți Unix Timestamp în ora locală
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 — data și ora pentru versiunile vechi de Android

ThreeTenABP — o bibliotecă adaptor care portează java.time pe Android API sub 26. Oferă aceleași clase: LocalDate, LocalTime, ZonedDateTime, DateTimeFormatter, Instant. Dacă aplicația suportă Android 5 sau 6 (API 21-25), ThreeTenABP este singura modalitate de a utiliza un API mobil modern fără a trece la Calendar învechit. Data și ora în dezvoltarea mobilă pentru dispozitive vechi sunt implementate prin această bibliotecă. Pentru dispozitive vechi, data și ora sunt implementate prin ThreeTenABP.

Adăugarea și configurarea ThreeTenABP

Biblioteca necesită inițializare în metoda Application.onCreate() prin apelarea AndroidThreeTen.init(). Aceasta încarcă datele fusurilor orare din assets. După inițializare, API-ul este complet identic cu java.time — codul pentru API 26+ și pentru API 21+ va fi același. Dimensiunea bibliotecii este de aproximativ 400 KB, ceea ce este acceptabil pentru majoritatea aplicațiilor mobile.

kotlin
import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter

// Inițializare în Application
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}

// API este identic cu java.time
val today = LocalDate.now()
val formatted = today.format(DateTimeFormatter.ISO_LOCAL_DATE)

Performanța ThreeTenABP este comparabilă cu java.time original pe dispozitive moderne. Pe dispozitive vechi, poate apărea o întârziere la prima apelare din cauza încărcării datelor fusurilor orare. Migrați codul existent de la Calendar la ThreeTenABP treptat: înlocuiți Date și Calendar cu Instant și LocalDate în modulele noi, lăsând codul vechi neschimbat.

Unix Timestamp și sincronizarea timpului prin NTP

Unix Timestamp — numărul de secunde scurse de la 1 ianuarie 1970 00:00 UTC. Acesta este un format universal pentru stocarea și schimbul de timp între server și client. Cu toate acestea, ora pe dispozitiv poate diferi de ora reală din cauza setărilor utilizatorului. Pentru sincronizare se folosește NTP — un protocol de timp precis prin UDP. Unix Timestamp este formatul în care data și ora sunt stocate pe server.

Obținerea Unix Timestamp și sincronizarea NTP

Date().timeIntervalSince1970 pe iOS returnează secunde din 1970. Pe Android, System.currentTimeMillis() returnează milisecunde. Pentru precizie, utilizați NTP: biblioteca TrueTime pentru iOS și AndroidNtp pentru Android trimit o cerere către un server NTP și calculează decalajul de timp. Precizia NTP este de 1-10 ms în rețeaua locală și 10-100 ms prin internet.

swift
import Foundation

// Obținerea Unix Timestamp pe iOS
let seconds = Date().timeIntervalSince1970
let milliseconds = Int64(seconds * 1000)

// Sincronizare NTP cu TrueTime
TrueTime.shared.start { result in
    switch result {
    case .success:
        let ntpTime = TrueTime.shared.now()
        print("Ora exactă: \(ntpTime)")
    case .failure(let error):
        print("Eroare NTP: \(error)")
    }
}

Fără sincronizare într-o aplicație mobilă, sunt posibile erori: marcaje de timp incorecte ale evenimentelor, desincronizare cu serverul. Timpul în dezvoltarea mobilă este sincronizat prin NTP o singură dată la pornirea aplicației, după care se utilizează decalajul calculat. Pentru aplicațiile mobile critice în ceea ce privește precizia (finanțe, logistică), protocolul NTP este obligatoriu înainte de trimiterea datelor către server.

Întrebări frecvente

De ce este DateFormatter lent pe iOS?

DateFormatter analizează modelul de formatare, încarcă setarea regională și determină fusul orar de fiecare dată când este creată o instanță. Stocați în cache formatorul ca constantă statică sau utilizați ISO8601DateFormatter pentru ISO 8601 — este mai ușor și mai rapid.

Ce să folosiți în loc de SimpleDateFormat pe Android?

DateTimeFormatter din pachetul java.time — thread-safe și performant. Disponibil de la API 26. Pentru versiunile vechi, utilizați ThreeTenABP care oferă un API identic.

Cum să lucrați cu date anterioare Java 8 pe Android?

Adăugați ThreeTenABP — un backport al java.time pentru Android API 21+. Inițializare prin AndroidThreeTen.init() în Application.onCreate(). API-ul este complet identic cu java.time original.

Este necesar să stocați timpul în UTC?

Da, stocați timpul în UTC pe server și în baza de date locală. Convertiți în fusul orar local al utilizatorului doar în etapa de afișare. Aceasta elimină erorile la schimbarea fusului orar sau în călătorii.

Cum să obțineți Unix Timestamp pe iOS?

Date().timeIntervalSince1970 returnează numărul de secunde de la 1 ianuarie 1970. Pentru milisecunde, înmulțiți cu 1000 și convertiți în Int64. Pentru sincronizare precisă, utilizați biblioteca TrueTime cu un server NTP.

Rezumat

  • DateFormatter pe iOS — instrumentul principal pentru formatarea datei și orei, necesită stocarea obligatorie în cache a instanțelor. ISO8601DateFormatter este o alternativă mai ușoară pentru ISO 8601.
  • DateTimeFormatter pe Android — formator thread-safe din java.time pentru API 26+. LocalDate și ZonedDateTime sunt clasele principale pentru lucrul cu datele.
  • ThreeTenABP — un API unificat pentru toate versiunile de Android. Adăugați pentru compatibilitate retroactivă cu API 21-25. Codul nu diferă de java.time.
  • TimeZone și UTC — stocați timpul în UTC, convertiți în fusul orar local doar pentru afișare. Utilizați identificatori IANA.
  • Unix Timestamp — un format universal pentru schimbul de timp între server și client. Obțineți prin Date().timeIntervalSince1970 pe iOS.
  • Sincronizarea NTP — garantează precizia timpului până la milisecundă. TrueTime (iOS) și AndroidNtp (Android) sunt bibliotecile standard.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul