TimeZone — adalah kelas Foundation di iOS dan macOS yang mengabstraksi informasi tentang zona waktu untuk konversi waktu yang benar antar wilayah geografis. Menurut Apple Developer Documentation, 2024, TimeZone menyediakan metode untuk bekerja dengan identifier zona waktu (IANA Time Zone Database), offset relatif terhadap UTC, dan aturan peralihan ke waktu musim panas. Kelas ini terintegrasi dengan DateFormatter dan Calendar, memastikan penerapan otomatis zona waktu yang benar saat memformat tanggal. Berbeda dengan perhitungan offset manual, TimeZone secara otomatis memperbarui data saat zona waktu perangkat berubah.
Poin Penting
TimeZone — adalah tipe nilai di Swift yang menyediakan informasi tentang zona waktu geografis: offset relatif terhadap UTC, nama, singkatan, dan aturan peralihan waktu musim panas. Di Objective-C, kelas ini bernama NSTimeZone. Kedua kelas didasarkan pada IANA Time Zone Database (juga dikenal sebagai database Olson), yang berisi rivayat perubahan zona waktu sejak tahun 1970.
Setiap instance TimeZone menyimpan identifier zona waktu (misalnya, Europe/Moscow), offset saat ini dalam detik dari UTC, flag isDaylightSavingTime, dan tanggal peralihan berikutnya. Identifier adalah kunci utama: saat inisialisasi TimeZone(identifier:), sistem memuat catatan yang sesuai dari database zona waktu perangkat.
Menurut data IANA (2024), database berisi lebih dari 600 identifier zona waktu unik. Apple menyertakan sebagian dari database ini di setiap versi iOS dan macOS, menjamin keseragaman perhitungan di semua perangkat tanpa perlu permintaan jaringan.
Arsitektur TimeZone di Foundation dibangun di atas sistem dua tingkat: identifier zona waktu (nama yang dapat dibaca manusia) dan representasi numeriknya (offset dari UTC). Sistem secara otomatis memilih zona waktu saat ini dari pengaturan perangkat, tetapi pengembang dapat menimpanya untuk operasi pemformatan tertentu.
TimeZone terkait erat dengan Calendar dan DateFormatter. Saat memformat tanggal, DateFormatter menggunakan properti timeZone dari instance TimeZone untuk mengonversi momen waktu absolut (Date) menjadi representasi teks di zona waktu yang sesuai. Jika timeZone tidak diatur, zona waktu sistem default digunakan — TimeZone.current.
| Jenis | Inisialisasi | Karakteristik |
|---|---|---|
| Saat ini | TimeZone.current | Diperbarui otomatis saat wilayah diubah di pengaturan, melacak waktu musim panas |
| Tetap | TimeZone(identifier:) | Tidak tergantung pada wilayah perangkat. Menerapkan identifier yang dipilih secara permanen |
| UTC | TimeZone(secondsFromGMT: 0) | Zona waktu tanpa koreksi. Identifier: GMT |
| Dengan offset arbitrer | TimeZone(secondsFromGMT: 10800) | Offset tetap dalam detik. Tidak memperhitungkan waktu musim panas |
Nuansa penting: TimeZone(identifier:) mengembalikan nil untuk identifier yang tidak dikenal. Ini adalah penyebab umum kerusakan aplikasi — pengembang lupa menangani nilai opsional, mengirimkan identifier yang salah dari input pengguna. Untuk identifier IANA, huruf besar/kecil penting: Europe/Moscow — benar, europe/moscow — nil.
IANA Time Zone Database menggunakan format “Wilayah/Kota” (Continent/City), di mana wilayah adalah salah satu benua (Africa, America, Asia, Atlantic, Australia, Europe, Indian, Pacific) atau samudra, dan kota adalah pemukiman terbesar di zona waktu tersebut. Format ini menjamin keunikan dan keterbacaan identifier.
Selain format utama, TimeZone mendukung tiga metode identifikasi tambahan: singkatan (MSK, EST, PST), kode tiga huruf zona waktu (GMT, UTC), dan offset numerik (+0300, -0500). Namun, singkatan bersifat ambigu: EST dapat berarti Eastern Standard Time (GMT-5) maupun Eastern Summer Time (GMT+10) di Australia. Apple merekomendasikan penggunaan eksklusif identifier IANA.
import Foundation
// Dapatkan semua identifier zona waktu yang dikenal
let allIdentifiers: [String] = TimeZone.knownTimeZoneIdentifiers
print("Total zona waktu: \(allIdentifiers.count)")
// Filter berdasarkan wilayah
let europeZones = allIdentifiers.filter { $0.hasPrefix("Europe/") }
print("Zona waktu Eropa: \(europeZones)")
// Singkatan (tidak direkomendasikan untuk produksi)
if let moscowTimeZone = TimeZone(abbreviation: "MSK") {
print("Detik MSK dari GMT: \(moscowTimeZone.secondsFromGMT())")
}
// Temukan identifier berdasarkan offset
let utcPlus3 = TimeZone(secondsFromGMT: 10800)
print("Identifier: \(utcPlus3.identifier)")
Singkatan di TimeZone.abbreviationDictionary berisi singkatan untuk semua zona waktu yang dikenal, tetapi kamus ini tidak menjamin keunikan: kunci PST dapat sesuai dengan America/Los_Angeles maupun Pacific/Pago_Pago. Dalam kode produksi, selalu gunakan identifier IANA.
TimeZone secara otomatis memperhitungkan peralihan ke waktu musim panas dan musim dingin (DST — Daylight Saving Time) untuk semua wilayah yang menerapkannya. Sistem menggunakan data historis dari IANA Time Zone Database, yang mencakup tanggal peralihan yang tepat untuk setiap zona waktu. Properti isDaylightSavingTime mengembalikan true jika zona waktu saat ini berada dalam waktu musim panas.
Metode nextDaylightSavingTimeTransition memungkinkan Anda mengetahui tanggal peralihan berikutnya, yang berguna untuk merencanakan acara di masa depan. Fungsionalitas ini sangat penting untuk wilayah dengan perubahan aturan DST yang sering, seperti Brasil atau Maroko — hingga tahun 2024, Brasil setiap tahun mengubah tanggal peralihan, dan perhitungan manual menyebabkan kesalahan dalam aplikasi.
Menurut data Apple WWDC 2023, perpustakaan ICU (International Components for Unicode), yang mendasari Foundation, memperbarui data DST di setiap pembaruan iOS. Aplikasi tidak boleh menyimpan cache data waktu musim panas lebih dari satu hari setelah pembaruan sistem — database IANA dapat berubah bahkan tanpa pembaruan versi OS melalui penyesuaian zona waktu.
import Foundation
// Periksa DST untuk Europe/Moscow
let moscow = TimeZone(identifier: "Europe/Moscow")!
let now = Date()
let isMoscowDST = moscow.isDaylightSavingTime(for: now)
print("Moskow saat ini dalam DST: \(isMoscowDST)")
// Dapatkan tanggal transisi DST berikutnya
if let nextTransition = moscow.nextDaylightSavingTimeTransition(
after: now
) {
let dstOffset = moscow.daylightSavingTimeOffset(
for: nextTransition
)
print("Transisi berikutnya: \(nextTransition), offset DST: \(dstOffset)s")
}
// Konversi aman dengan kesadaran DST
let newYork = TimeZone(identifier: "America/New_York")!
let offsetNY = newYork.secondsFromGMT(for: now)
print("Offset NY saat ini: \(offsetNY / 3600)h")
Nuansa kritis: secondsFromGMT(for:) memperhitungkan DST untuk tanggal yang ditentukan, sedangkan secondsFromGMT() hanya untuk waktu saat ini. Saat memformat tanggal historis, selalu gunakan versi dengan parameter Date: secondsFromGMT(for: someHistoricalDate). Perbedaannya bisa mencapai 1–2 jam, yang sangat penting untuk log atau data historis.
Memformat tanggal dengan zona waktu tertentu — tugas paling umum saat bekerja dengan TimeZone. DateFormatter menggunakan properti timeZone untuk mengonversi Date menjadi teks. Jika timeZone tidak diatur secara eksplisit, pemformat menggunakan TimeZone.current — zona waktu yang diatur di perangkat pengguna, yang dapat menyebabkan hasil yang tidak terduga untuk data server.
import Foundation
// Format tanggal di zona waktu tertentu
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("Waktu Tokyo: \(tokyoTime)")
// Identifier yang tersedia untuk pilihan pengguna
let displayNames: [(String, String)] = TimeZone.knownTimeZoneIdentifiers
.prefix(20)
.map { ($0, TimeZone(identifier: $0)!.localizedName(
for: .generic, locale: .current
)) }
// Bandingkan dua zona waktu
let london = TimeZone(identifier: "Europe/London")!
let difference = tokyo.secondsFromGMT(for: Date())
- london.secondsFromGMT(for: Date())
print("Selisih Tokyo-London: \(difference / 3600)h")
// Bekerja dengan kamus singkatan
let knownAbbrevs = TimeZone.abbreviationDictionary
for (abbr, ident) in knownAbbrevs.sorted(by: { $0.key < $1.key }).prefix(5) {
print("\(abbr) -> \(ident)")
}
Nama yang dilokalkan zona waktu melalui localizedName(for:locale:) mengembalikan nama yang dapat dibaca manusia dalam bahasa yang ditentukan. Misalnya, untuk Europe/Moscow dengan locale Rusia, metode akan mengembalikan “Moskwa”, dan dengan locale Inggris — “Moscow Time”. Gaya yang tersedia: .standard (nama standar), .daylightSaving (waktu musim panas), dan .shortGeneric (pendek).
import Foundation
let paris = TimeZone(identifier: "Europe/Paris")!
let nameRU = paris.localizedName(
for: .standard,
locale: Locale(identifier: "ru_RU")
)
print("Nama Rusia: \(nameRU)")
// Periksa apakah wilayah berada di hari yang sama
let isSameDay = Calendar.current.isDate(
Date(),
equalTo: Date(),
toGranularity: .day
)
print("Hari yang sama di berbagai zona waktu: \(isSameDay)")
Serialisasi identifier zona waktu — praktik terbaik untuk menyimpan TimeZone di database atau UserDefaults. Simpan identifier (string tipe Europe/Moscow), bukan offset dalam detik atau singkatan. Offset dapat berubah saat perubahan DST, dan singkatan bersifat ambigu. Pemulihan: TimeZone(identifier: savedString).
Menggunakan offset tetap alih-alih identifier zona waktu — kesalahan paling umum. TimeZone(secondsFromGMT: 10800) tidak memperhitungkan DST, oleh karena itu untuk Europe/Moscow di musim panas, konstruksi ini memberikan offset yang salah sebesar 1 jam. Selalu gunakan identifier IANA untuk wilayah dengan waktu musim panas.
Penanganan nil yang terlupakan saat inisialisasi TimeZone(identifier:) — kesalahan paling umum kedua. Jika pengguna memasukkan identifier dengan kesalahan (misalnya, “moscow” alih-alih “Europe/Moscow”), konstruktor mengembalikan nil. Tanpa penanganan nilai opsional, aplikasi akan crash dengan runtime error. Gunakan guard let atau TimeZone(identifier:) dengan fallback yang dikenal.
Mengabaikan DST saat bekerja dengan tanggal mendatang. TimeZone.secondsFromGMT(for:) — satu-satunya cara yang benar untuk mendapatkan offset untuk tanggal tertentu. Penggunaan secondsFromGMT() tanpa parameter untuk tanggal historis atau mendatang memberikan offset untuk momen saat ini, yang mungkin tidak sesuai dengan offset sebenarnya pada tanggal tersebut, terutama untuk wilayah dengan penghapusan atau penerapan DST.
Menurut data Stack Overflow (2024), sekitar 15% pertanyaan tentang DateFormatter terkait dengan pengaturan timeZone yang salah. Skenario tipikal: server mengirim tanggal dalam UTC, pengembang memformatnya tanpa mengatur timeZone pemformat, dan tanggal ditampilkan di zona waktu perangkat, menyebabkan kebingungan di antara pengguna dari berbagai wilayah. Aturan: selalu atur timeZone pemformat secara eksplisit untuk data server.
Pertanyaan Umum
TimeZone — kelas Foundation untuk bekerja dengan zona waktu di iOS dan macOS. Menyediakan informasi tentang offset relatif terhadap UTC, aturan peralihan waktu musim panas, dan identifier zona waktu berdasarkan IANA Time Zone Database.
Tiga format: identifier IANA (Europe/Moscow), singkatan (MSK, EST), dan offset numerik (+0300). Apple merekomendasikan penggunaan identifier IANA sebagai satu-satunya format yang tidak ambigu untuk kode produksi.
Secara otomatis melalui metode secondsFromGMT(for:) dan isDaylightSavingTime(for:). TimeZone menggunakan data historis IANA yang diperbarui di setiap rilis iOS, menjamin peralihan DST yang benar untuk tanggal berapa pun.
TimeZone.current mengembalikan zona waktu yang dipilih pengguna di pengaturan (mungkin berbeda dari zona geografis). TimeZone.system mengembalikan zona waktu perangkat, yang secara otomatis ditentukan berdasarkan geolokasi dan tidak dapat ditimpa oleh pengguna.
TimeZone.current mengembalikan zona waktu saat ini dari perangkat. Untuk mendapatkan identifier, gunakan properti identifier: TimeZone.current.identifier. Untuk nama yang dilokalkan, panggil localizedName(for:locale:).
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga