TimeZone — је класа Foundation у iOS и macOS која апстрахира информације о временским зонама за коректну конверзију времена између географских регија. Према Apple Developer Documentation, 2024, TimeZone пружа методе за рад са идентификаторима временских зона (IANA Time Zone Database), померајима у односу на UTC и правилима преласка на летње време. Класа је интегрисана са DateFormatter и Calendar, обезбеђујући аутоматску примену правилне временске зоне при форматирању датума. За разлику од речног израчунавања помераја, TimeZone аутоматски ажурира податке при промени временске зоне уређаја.
Главно
TimeZone — је вриједносни тип у Swift-у који пружа информације о географској временској зони: померај у односу на UTC, назив, скраћеницу и правила преласка на летње време. У Objective-C-у класа се назива NSTimeZone. Обе класе се ослањају на IANA Time Zone Database (такође познату као Olson база података), која садржи историју промена временских зона од 1970. године.
Свака инстанца TimeZone чува идентификатор временске зоне (нпр. Europe/Moscow), тренутно померање у секундама од UTC, заставицу isDaylightSavingTime и датум следеће промене. Идентификатор је примарни кључ: при иницијализацији TimeZone(identifier:), систем учитава одговарајући унос из базе података временских зона уређаја.
Према подацима IANA (2024), база података садржи преко 600 јединствених идентификатора временских зона. Apple испоручује део ове базе у свакој верзији iOS и macOS, што гарантује једнообразност израчунавања на свим уређајима без потребе за мрежним захтевима.
Архитектура TimeZone-а у Foundation-у је изграђена на двоструком систему: идентификатор временске зоне (људски читљив назив) и његов бројчани приказ (померај од UTC). Систем аутоматски бира тренутну временску зону из поставки уређаја, али развојач може да је прегази за одређене операције форматирања.
TimeZone је чврсто повезан са Calendar и DateFormatter. При форматирању датума, DateFormatter користи својство timeZone инстанце TimeZone за претварање апсолутног тренутка времена (Date) у текстуални приказ у одговарајућој временској зони. Ако timeZone није постављен, користи се подразумевана системска временска зона — TimeZone.current.
| Тип | Иницијализација | Карактеристике |
|---|---|---|
| Тренутни | TimeZone.current | Аутоматски се ажурира при промени регија у поставкама, прати прелазак на летње време |
| Фиксни | TimeZone(identifier:) | Не зависи од регија уређаја. Стално примењује изабрани идентификатор |
| UTC | TimeZone(secondsFromGMT: 0) | Временска зона без корекције. Идентификатор: GMT |
| Са произвољним померањем | TimeZone(secondsFromGMT: 10800) | Фиксно померање у секундама. Не узима у обзир летње време |
Важан нијанс: TimeZone(identifier:) враћа nil за непознате идентификаторе. Ово је чест узрок пада апликације — развојачи заборављају да обраде опционалну вриједност, прослеђујући неисправан идентификатор из корисничког уноса. За IANA идентификаторе, величина слова је важна: Europe/Moscow — исправан, europe/moscow — nil.
IANA Time Zone Database користи формат „Регија/Град” (Continent/City), где је регија један од континената (Africa, America, Asia, Atlantic, Australia, Europe, Indian, Pacific) или океан, а град је највећи насељени пункт у зони дејства временске зоне. Овај формат гарантује јединственост и читљивост идентификатора.
Поред основног формата, TimeZone подржава три додатна начина идентификације: скраћенице (MSK, EST, PST), трословне кодове временских зона (GMT, UTC) и бројчана померања (+0300, -0500). Међутим, скраћенице су двосмислене: EST може да значи и Eastern Standard Time (GMT-5) и Eastern Summer Time (GMT+10) у Аустралији. Apple препоручује коришчење искључиво IANA идентификатора.
import Foundation
// Преузми све познате идентификаторе временских зона
let allIdentifiers: [String] = TimeZone.knownTimeZoneIdentifiers
print("Укупно временских зона: \(allIdentifiers.count)")
// Филтрирај по регији
let europeZones = allIdentifiers.filter { $0.hasPrefix("Europe/") }
print("Европске временске зоне: \(europeZones)")
// Скраћенице (нису препоручлјиве за производњу)
if let moscowTimeZone = TimeZone(abbreviation: "MSK") {
print("MSK секунди од GMT-а: \(moscowTimeZone.secondsFromGMT())")
}
// Пронађи идентификатор по померању
let utcPlus3 = TimeZone(secondsFromGMT: 10800)
print("Идентификатор: \(utcPlus3.identifier)")
Скраћенице у TimeZone.abbreviationDictionary садрже скраћенице за све познате временске зоне, али овај речник не гарантује јединственост: кључ PST може да одговара и America/Los_Angeles и Pacific/Pago_Pago. У производном коду увијек користите IANA идентификаторе.
TimeZone аутоматски узима у обзир прелазак на летње и зимско време (DST — Daylight Saving Time) за све регије где је то прихваћено. Систем користи историјске податке из IANA Time Zone Database, који укључују тачне датуме преласка за сваку временску зону. Својство isDaylightSavingTime враћа true ако се временска зона тренутно налази у летњем времену.
Метода nextDaylightSavingTimeTransition омогућава да сазнате датум следеће промене, што је корисно за планирање будућих догађаја. Ова функционалност је посебно важна за регије са честим промјенама правила DST, као што су Бразил или Мароко — до 2024. године, Бразил је годишње мењао датуме преласка, а речно израчунавање је доводило до грешака у апликацијама.
Према подацима Apple WWDC 2023, библиотека ICU (International Components for Unicode), која је основа Foundation-а, ажурира DST податке при сваком ажурирању iOS-а. Апликације не би требало да кеширају податке о летњем времену дуже од једног дана након ажурирања система — IANA база се може промијенити чак и без ажурирања верзије оперативног система кроз прилагођавање временских зона.
import Foundation
// Провери DST за Europe/Moscow
let moscow = TimeZone(identifier: "Europe/Moscow")!
let now = Date()
let isMoscowDST = moscow.isDaylightSavingTime(for: now)
print("Москва тренутно у DST-у: \(isMoscowDST)")
// Добиј следећи датум DST транзиције
if let nextTransition = moscow.nextDaylightSavingTimeTransition(
after: now
) {
let dstOffset = moscow.daylightSavingTimeOffset(
for: nextTransition
)
print("Следећа транзиција: \(nextTransition), DST померај: \(dstOffset)s")
}
// Сигурна конверзија са DST свесшчу
let newYork = TimeZone(identifier: "America/New_York")!
let offsetNY = newYork.secondsFromGMT(for: now)
print("Тренутни NY померај: \(offsetNY / 3600)h")
Критични нијанс: secondsFromGMT(for:) узима у обзир DST за наведени датум, док secondsFromGMT() само за тренутно време. При форматирању историјских датума увијек користите верзију са Date параметром: secondsFromGMT(for: someHistoricalDate). Разлика може да буде 1–2 сата, што је критично за евиденцију или историјске податке.
Форматирање датума са одређеном временском зоном — најчешчи задатак при раду са TimeZone. DateFormatter користи својство timeZone за претварање Date у текст. Ако timeZone није експлицитно постављен, форматер користи TimeZone.current — временску зону постављену на корисничком уређају, што може довести до неочекиваних резултата за податке са сервера.
import Foundation
// Форматирај датум у одређеној временској зони
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("Време у Токију: \(tokyoTime)")
// Доступни идентификатори за кориснички избор
let displayNames: [(String, String)] = TimeZone.knownTimeZoneIdentifiers
.prefix(20)
.map { ($0, TimeZone(identifier: $0)!.localizedName(
for: .generic, locale: .current
)) }
// Упореди две временске зоне
let london = TimeZone(identifier: "Europe/London")!
let difference = tokyo.secondsFromGMT(for: Date())
- london.secondsFromGMT(for: Date())
print("Разлика Токио-Лондон: \(difference / 3600)h")
// Ради са речником скраћеница
let knownAbbrevs = TimeZone.abbreviationDictionary
for (abbr, ident) in knownAbbrevs.sorted(by: { $0.key < $1.key }).prefix(5) {
print("\(abbr) -> \(ident)")
}
Локализовани назив временске зоне кроз localizedName(for:locale:) враћа људски читљив назив на наведеном језику. На пример, за Europe/Moscow са руском локализацијом, метода ће вратити „Москва”, а са енглеском — „Moscow Time”. Доступни стилови: .standard (стандардни назив), .daylightSaving (летње време) и .shortGeneric (кратки).
import Foundation
let paris = TimeZone(identifier: "Europe/Paris")!
let nameRU = paris.localizedName(
for: .standard,
locale: Locale(identifier: "ru_RU")
)
print("Руски назив: \(nameRU)")
// Провери да ли је регија у истом дану
let isSameDay = Calendar.current.isDate(
Date(),
equalTo: Date(),
toGranularity: .day
)
print("Исти дан у различитим временским зонама: \(isSameDay)")
Серијализација идентификатора временске зоне — најбоља пракса за чување TimeZone-а у базама података или UserDefaults-у. Сачувајте идентификатор (низ типа Europe/Moscow), а не померај у секундама или скраћеницу. Померај се може промијенити при промјени DST, а скраћеница је двосмислена. Обнова: TimeZone(identifier: savedString).
Коришчење фиксног помераја уместо идентификатора временске зоне — најчешча грешка. TimeZone(secondsFromGMT: 10800) не узима у обзир DST, па за Europe/Moscow лети ова конструкција даје погрешно померање од 1 сата. Увијек користите IANA идентификатор за регије са летњим временом.
Заборављена обрада nil-а при иницијализацији TimeZone(identifier:) — друга најчешча грешка. Ако корисник унесе идентификатор са грешком (нпр. „moscow” уместо „Europe/Moscow”), конструктор враћа nil. Без обраде опционалне вриједности, апликација пада са runtime error-ом. Користите guard let или TimeZone(identifier:) са познатим fallback-ом.
Игнорисање DST-а при раду са будућим датумима. TimeZone.secondsFromGMT(for:) — једини исправан начин да се добије померај за одређени датум. Коришчење secondsFromGMT() без параметра за историјске или будуће датуме даје померај за тренутни тренутак, што може да не одговара стварном померању у том датуму, посебно за регије са укидањем или увођењем DST-а.
Према подацима Stack Overflow (2024), око 15% питања везаних за DateFormatter односи се на неправилно постављен timeZone. Типичан сценарио: сервер шаље датум у UTC-у, развојач га форматира без постављања timeZone форматера, и датум се приказује у временској зони уређаја, стварајући збуну код корисника из различитих регија. Правило: увијек експлицитно поставите timeZone форматера за податке са сервера.
Често постављана питања
TimeZone — класа Foundation за рад са временским зонама у iOS и macOS. Пружа информације о померају у односу на UTC, правилима преласка на летње време и идентификаторима временских зона на основу IANA Time Zone Database.
Три формата: IANA идентификатори (Europe/Moscow), скраћенице (MSK, EST) и бројчана померања (+0300). Apple препоручује коришчење IANA идентификатора као јединог недвосмисленог формата за производни код.
Аутоматски кроз методе secondsFromGMT(for:) и isDaylightSavingTime(for:). TimeZone користи историјске IANA податке, које се ажурирају при сваком издању iOS-а, гарантујући коректне DST преласке за било који датум.
TimeZone.current враћа временску зону коју је корисник изабрао у поставкама (може се разликовати од географске). TimeZone.system враћа временску зону уређаја, која се аутоматски одређује на основу геопозиције и не може бити прегажена од стране корисника.
TimeZone.current враћа тренутну временску зону уређаја. Да бисте добили идентификатор, користите својство identifier: TimeZone.current.identifier. За локализовани назив, позовите localizedName(for:locale:).
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође