TimeZone — este o clasă Foundation în iOS și macOS care abstractizează informațiile despre fusurile orare pentru conversia corectă a timpului între regiuni geografice. Conform Apple Developer Documentation, 2024, TimeZone oferă metode pentru lucrul cu identificatori de fus orar (IANA Time Zone Database), decalaje față de UTC și reguli de trecere la ora de vară. Clasa este integrată cu DateFormatter și Calendar, asigurând aplicarea automată a fusului orar corect la formatarea datelor. Spre deosebire de calculul manual al decalajului, TimeZone actualizează automat datele la schimbarea fusului orar al dispozitivului.
Principalele puncte
TimeZone — este un tip-valoare în Swift care oferă informații despre fusul orar geografic: decalajul față de UTC, denumirea, abrevierea și regulile de schimbare a orei de vară. În Objective-C, clasa se numește NSTimeZone. Ambele clase se bazează pe IANA Time Zone Database (cunoscută și ca baza de date Olson), care conține istoricul schimbărilor fusurilor orare începând cu anul 1970.
Fiecare instanță TimeZone stochează un identificator de fus orar (de exemplu, Europe/Moscow), decalajul curent în secunde față de UTC, indicatorul isDaylightSavingTime și data următoarei schimbări. Identificatorul este cheia primară: la inițializarea TimeZone(identifier:), sistemul încarcă înregistrarea corespunzătoare din baza de date a fusurilor orare a dispozitivului.
Conform datelor IANA (2024), baza de date conține peste 600 de identificatori unici de fus orar. Apple livrează o parte din această bază în fiecare versiune de iOS și macOS, garantând uniformitatea calculelor pe toate dispozitivele fără necesitatea cererilor de rețeaua.
Arhitectura TimeZone în Foundation este construită pe un sistem pe două niveluri: identificatorul fusului orar (un nume lizibil pentru om) și reprezentarea sa numerică (decalajul față de UTC). Sistemul selectează automat fusul orar curent din setările dispozitivului, dar dezvoltatorul poate să-l suprascrie pentru operații specifice de formatare.
TimeZone este strâns legat de Calendar și DateFormatter. La formatarea unei date, DateFormatter folosește proprietatea timeZone a unei instanțe TimeZone pentru a converti momentul absolut de timp (Date) într-o reprezentare text în fusul orar corespunzător. Dacă timeZone nu este setat, se utilizează fusul orar implicit al sistemului — TimeZone.current.
| Tip | Inițializare | Caracteristici |
|---|---|---|
| Curent | TimeZone.current | Se actualizează automat la schimbarea regiunii în setări, urmărește ora de vară |
| Fix | TimeZone(identifier:) | Nu depinde de regiunea dispozitivului. Aplică permanent identificatorul selectat |
| UTC | TimeZone(secondsFromGMT: 0) | Fus orar fără corecție. Identificator: GMT |
| Cu decalaj arbitrar | TimeZone(secondsFromGMT: 10800) | Decalaj fix în secunde. Nu ia în calcul ora de vară |
Nuanță importantă: TimeZone(identifier:) returnează nil pentru identificatori necunoscuți. Aceasta este o cauză frecventă de crash al aplicației — dezvoltatorii uită să gestioneze valoarea opțională, transmițând un identificator incorect din introducerea utilizatorului. Pentru identificatorii IANA, literele mari și mici contează: Europe/Moscow — corect, europe/moscow — nil.
IANA Time Zone Database utilizează formatul „Region/Oraș” (Continent/City), unde regiunea este unul dintre continente (Africa, America, Asia, Atlantic, Australia, Europe, Indian, Pacific) sau un ocean, iar orașul este cea mai mare localitate din zona de acțiune a fusului orar. Acest format garantează unicitatea și lizibilitatea identificatorului.
Pe lângă formatul principal, TimeZone suportă trei metode suplimentare de identificare: abrevieri (MSK, EST, PST), coduri de trei litere ale fusurilor orare (GMT, UTC) și decalaje numerice (+0300, -0500). Cu toate acestea, abrevierile sunt ambigue: EST poate însemna atât Eastern Standard Time (GMT-5), cât și Eastern Summer Time (GMT+10) în Australia. Apple recomandă utilizarea exclusivă a identificatorilor IANA.
import Foundation
// Obține toți identificatorii de fus orar cunoscuți
let allIdentifiers: [String] = TimeZone.knownTimeZoneIdentifiers
print("Total fusuri orare: \(allIdentifiers.count)")
// Filtrează după regiune
let europeZones = allIdentifiers.filter { $0.hasPrefix("Europe/") }
print("Fusuri orare europene: \(europeZones)")
// Abrevieri (nerecomandate pentru producție)
if let moscowTimeZone = TimeZone(abbreviation: "MSK") {
print("Secunde MSK de la GMT: \(moscowTimeZone.secondsFromGMT())")
}
// Găsește identificatorul după decalaj
let utcPlus3 = TimeZone(secondsFromGMT: 10800)
print("Identificator: \(utcPlus3.identifier)")
Abrevierile în TimeZone.abbreviationDictionary conțin prescurtări pentru toate fusurile orare cunoscute, dar acest dicționar nu garantează unicitatea: cheia PST poate corespunde atât America/Los_Angeles, cât și Pacific/Pago_Pago. În codul de producție, utilizați întotdeauna identificatori IANA.
TimeZone ia automat în calcul trecerea la ora de vară și de iarnă (DST — Daylight Saving Time) pentru toate regiunile unde aceasta este practicată. Sistemul utilizează date istorice din IANA Time Zone Database, care includ datele exacte ale schimbărilor pentru fiecare fus orar. Proprietatea isDaylightSavingTime returnează true dacă fusul orar se află în prezent în ora de vară.
Metoda nextDaylightSavingTimeTransition permite aflarea datei următoarei schimbări, ceea ce este util pentru planificarea evenimentelor viitoare. Această funcționalitate este deosebit de importantă pentru regiunile cu schimbări frecvente ale regulilor DST, precum Brazilia sau Maroc — până în 2024, Brazilia modifica anual datele de tranziție, iar calculul manual ducea la erori în aplicații.
Conform datelor Apple WWDC 2023, biblioteca ICU (International Components for Unicode), care stă la baza Foundation, actualizează datele DST la fiecare actualizare iOS. Aplicațiile nu ar trebui să stocheze în cache datele despre ora de vară mai mult de o zi după actualizarea sistemului — baza IANA se poate modifica chiar și fără actualizarea versiunii sistemului de operare prin ajustări ale fusurilor orare.
import Foundation
// Verifică DST pentru Europe/Moscow
let moscow = TimeZone(identifier: "Europe/Moscow")!
let now = Date()
let isMoscowDST = moscow.isDaylightSavingTime(for: now)
print("Moscova în prezent în DST: \(isMoscowDST)")
// Obține următoarea dată de tranziție DST
if let nextTransition = moscow.nextDaylightSavingTimeTransition(
after: now
) {
let dstOffset = moscow.daylightSavingTimeOffset(
for: nextTransition
)
print("Următoarea tranziție: \(nextTransition), decalaj DST: \(dstOffset)s")
}
// Conversie sigură cu conștientizare DST
let newYork = TimeZone(identifier: "America/New_York")!
let offsetNY = newYork.secondsFromGMT(for: now)
print("Decalajul curent NY: \(offsetNY / 3600)h")
Nuanță critică: secondsFromGMT(for:) ia în calcul DST pentru data specificată, în timp ce secondsFromGMT() — doar pentru timpul curent. La formatarea datelor istorice, utilizați întotdeauna versiunea cu parametrul Date: secondsFromGMT(for: someHistoricalDate). Diferența poate ajunge la 1–2 ore, ceea ce este critic pentru jurnale sau date istorice.
Formatarea datei cu un fus orar specific — cea mai frecventă sarcină la lucrul cu TimeZone. DateFormatter folosește proprietatea timeZone pentru a converti Date în text. Dacă timeZone nu este setat explicit, formatterul utilizează TimeZone.current — fusul orar setat pe dispozitivul utilizatorului, ceea ce poate duce la rezultate neașteptate pentru datele de pe server.
import Foundation
// Formatează data în fusul orar specific
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let tokyo = TimeZone(identifier: "Asia/Tokyo")!
formatter.timeZone = tokyo
let tokyoTime = formatter.string(from: Date())
print("Ora Tokio: \(tokyoTime)")
// Identificatori disponibili pentru selecția utilizatorului
let displayNames: [(String, String)] = TimeZone.knownTimeZoneIdentifiers
.prefix(20)
.map { ($0, TimeZone(identifier: $0)!.localizedName(
for: .generic, locale: .current
)) }
// Compară două fusuri orare
let london = TimeZone(identifier: "Europe/London")!
let difference = tokyo.secondsFromGMT(for: Date())
- london.secondsFromGMT(for: Date())
print("Diferența Tokio-Londra: \(difference / 3600)h")
// Lucrează cu dicționarul de abrevieri
let knownAbbrevs = TimeZone.abbreviationDictionary
for (abbr, ident) in knownAbbrevs.sorted(by: { $0.key < $1.key }).prefix(5) {
print("\(abbr) -> \(ident)")
}
Denumirea localizată a fusului orar prin localizedName(for:locale:) returnează un nume lizibil în limba specificată. De exemplu, pentru Europe/Moscow cu localizare rusă, metoda va returna „Moscova”, iar cu localizare engleză — „Moscow Time”. Stilurile disponibile sunt: .standard (denumire standard), .daylightSaving (ora de vară) și .shortGeneric (scurtă).
import Foundation
let paris = TimeZone(identifier: "Europe/Paris")!
let nameRU = paris.localizedName(
for: .standard,
locale: Locale(identifier: "ru_RU")
)
print("Denumirea rusă: \(nameRU)")
// Verifică dacă regiunea este în aceeași zi
let isSameDay = Calendar.current.isDate(
Date(),
equalTo: Date(),
toGranularity: .day
)
print("Aceeași zi în fusuri orare diferite: \(isSameDay)")
Serializarea identificatorului fusului orar — cea mai bună practică pentru stocarea TimeZone în baze de date sau UserDefaults. Salvați identificatorul (șir de tip Europe/Moscow), nu decalajul în secunde sau abrevierea. Decalajul se poate modifica la schimbarea DST, iar abrevierea este ambiguă. Restaurare: TimeZone(identifier: savedString).
Utilizarea unui decalaj fix în locul identificatorului de fus orar — cea mai răspândită eroare. TimeZone(secondsFromGMT: 10800) nu ia în calcul DST, prin urmare pentru Europe/Moscow vara această construcție oferă un decalaj incorect de 1 oră. Utilizați întotdeauna identificatorul IANA pentru regiunile cu ora de vară.
Gestionarea uitată a nil la inițializarea TimeZone(identifier:) — a doua cea mai frecventă eroare. Dacă utilizatorul introduce un identificator cu eroare (de exemplu, „moscow” în loc de „Europe/Moscow”), constructorul returnează nil. Fără gestionarea valorii opționale, aplicația se prăbușește cu o eroare de execuție. Folosiți guard let sau TimeZone(identifier:) cu un fallback cunoscut.
Ignorarea DST la lucrul cu date viitoare. TimeZone.secondsFromGMT(for:) — singura modalitate corectă de a obține decalajul pentru o dată specifică. Utilizarea secondsFromGMT() fără parametru pentru date istorice sau viitoare oferă decalajul pentru momentul curent, ceea ce poate să nu corespundă decalajului real la data respectivă, în special pentru regiunile cu abolirea sau introducerea DST.
Conform datelor Stack Overflow (2024), aproximativ 15% din întrebările legate de DateFormatter se referă la setarea incorectă a timeZone. Scenariu tipic: serverul trimite data în UTC, dezvoltatorul o formatează fără a seta timeZone-ul formatterului, iar data se afișează în fusul orar al dispozitivului, creând confuzie între utilizatorii din diferite regiuni. Regulă: setați întotdeauna explicit timeZone-ul formatterului pentru datele de pe server.
Întrebări frecvente
TimeZone — clasa Foundation pentru lucrul cu fusurile orare în iOS și macOS. Oferă informații despre decalajul față de UTC, regulile de trecere la ora de vară și identificatorii fusurilor orare pe baza IANA Time Zone Database.
Trei formate: identificatori IANA (Europe/Moscow), abrevieri (MSK, EST) și decalaje numerice (+0300). Apple recomandă utilizarea identificatorilor IANA ca singurul format lipsit de ambiguitate pentru codul de producție.
Automat prin metodele secondsFromGMT(for:) și isDaylightSavingTime(for:). TimeZone folosește date istorice IANA, actualizate la fiecare lansare iOS, garantând tranziții corecte DST pentru orice dată.
TimeZone.current returnează fusul orar selectat de utilizator în setări (poate diferi de cel geografic). TimeZone.system returnează fusul orar al dispozitivului, determinat automat pe baza geopoziției și care nu poate fi suprascris de utilizator.
TimeZone.current returnează fusul orar curent al dispozitivului. Pentru a obține identificatorul, utilizați proprietatea identifier: TimeZone.current.identifier. Pentru o denumire localizată, apelați localizedName(for:locale:).
Concluzii
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.
Citiți și