TimeZone, iOS ve macOS'te coğrafi bölgeler arasında doğru saat dönüşümü için saat dilimi bilgilerini soyutlayan bir Foundation sınıfıdır. Apple Developer Documentation, 2024'e göre, TimeZone saat dilimi tanımlayıcıları (IANA Time Zone Database), UTC'ye göre farklar ve yaz saati uygulaması kurallarıyla çalışmak için yöntemler sağlar. Sınıf, DateFormatter ve Calendar ile entegre edilmiştir ve tarihleri biçimlendirirken doğru saat diliminin otomatik olarak uygulanmasını sağlar. Manuel fark hesaplamasının aksine, TimeZone cihazın saat dilimi değiştiğinde verileri otomatik olarak günceller.
Önemli Noktalar
TimeZone, Swift'te coğrafi bir saat dilimi hakkında bilgi sağlayan bir değer türüdür: UTC farkı, ad, kısaltma ve yaz saati uygulaması kuralları. Objective-C'de sınıf NSTimeZone olarak adlandırılır. Her iki sınıf da 1970'ten bu yana saat dilimi değişikliklerinin geçmişini içeren IANA Time Zone Database'e (Olson veritabanı olarak da bilinir) dayanır.
Her TimeZone örneği bir saat dilimi tanımlayıcısı (orn. Europe/Moscow), UTC'den geçerli farkı saniye cinsinden, isDaylightSavingTime bayrağı ve sonraki geçiş tarihini depolar. Tanımlayıcı birincil anahtardır: TimeZone(identifier:) ile başlatırken, sistem cihazın saat dilimi veritabanından ilgili kaydı yükler.
IANA (2024)'e göre, veritabanı 600'den fazla benzersiz saat dilimi tanımlayıcısı içerir. Apple, her iOS ve macOS sürümüyle bu veritabanının bir anlık görüntüsünü sağlayarak ağ isteklerine gerek kalmadan tüm cihazlarda tutarlı hesaplamalar sağlar.
Mimari Foundation'daki TimeZone iki seviyeli bir sistem üzerine kurulmuştur: saat dilimi tanımlayıcısı (insan tarafından okunabilir ad) ve sayısal temsili (UTC farkı). Sistem, cihaz ayarlarından geçerli saat dilimini otomatik olarak seçer, ancak geliştirici belirli biçimlendirme işlemleri için bunu geçersiz kılabilir.
TimeZone, Calendar ve DateFormatter ile yakından ilişkilidir. Bir tarihi biçimlendirirken DateFormatter, mutlak bir zaman anını (Date) istenen saat diliminde bir dize temsiline dönüştürmek için bir TimeZone örneğinin timeZone özelliğini kullanır. timeZone ayarlanmazsa, varsayılan sistem saat dilimi — TimeZone.current kullanılır.
| Tür | Başlatma | Özellikler |
|---|---|---|
| Geçerli | TimeZone.current | Ayarlarda bölge değiştiğinde otomatik olarak güncellenir, yaz saatini izler |
| Sabit | TimeZone(identifier:) | Cihaz bölgesinden bağımsızdır. Seçilen tanımlayıcıyı tutarlı bir şekilde uygular |
| UTC | TimeZone(secondsFromGMT: 0) | Düzeltmesiz saat dilimi. Tanımlayıcı: GMT |
| Rastgele fark | TimeZone(secondsFromGMT: 10800) | Saniye cinsinden sabit fark. Yaz saatini dikkate almaz |
Önemli not: TimeZone(identifier:) bilinmeyen tanımlayıcılar için nil döndürür. Bu, uygulama çökmelerinin yaygın bir nedenidir — geliştiriciler, kullanıcı girdisinden geçersiz bir tanımlayıcı aktarırken isteğe bağlı değeri işlemeyi unuturlar. IANA tanımlayıcıları için büyük/küçük harf duyarlılığı önemlidir: Europe/Moscow geçerlidir, europe/moscow nil döndürür.
IANA Time Zone Database “Bölge/Şehir” (Kıta/Şehir) biçimini kullanır; burada bölge kıtalardan biridir (Africa, America, Asia, Atlantic, Australia, Europe, Indian, Pacific) veya bir okyanus ve şehir, saat diliminin kapsama alanındaki en büyük nüfuslu yerdir. Bu biçim, tanımlayıcının benzersizliğini ve okunabilirliğini garanti eder.
Ana biçime ek olarak, TimeZone üç ek tanımlama yöntemini destekler: kısaltmalar (MSK, EST, PST), üç harfli saat dilimi kodları (GMT, UTC) ve sayısal farklar (+0300, -0500). Ancak, kısaltmalar belirsizdir: EST, Eastern Standard Time (GMT-5) veya Avustralya'da Eastern Summer Time (GMT+10) anlamına gelebilir. Apple yalnızca IANA tanımlayıcılarının kullanılmasını önerir.
import Foundation
// Bilinen tüm saat dilimi tanımlayıcılarını al
let allIdentifiers: [String] = TimeZone.knownTimeZoneIdentifiers
print("Toplam saat dilimi: \(allIdentifiers.count)")
// Bölgeye göre filtrele
let europeZones = allIdentifiers.filter { $0.hasPrefix("Europe/") }
print("Avrupa saat dilimleri: \(europeZones)")
// Kısaltmalar (üretim için önerilmez)
if let moscowTimeZone = TimeZone(abbreviation: "MSK") {
print("GMT'den MSK saniyeleri: \(moscowTimeZone.secondsFromGMT())")
}
// Farka göre tanımlayıcı bul
let utcPlus3 = TimeZone(secondsFromGMT: 10800)
print("Tanımlayıcı: \(utcPlus3.identifier)")
Kısaltmalar TimeZone.abbreviationDictionary içinde bilinen tüm saat dilimleri için kısaltmalar içerir, ancak bu sözlük benzersizliği garanti etmez: PST anahtarı America/Los_Angeles veya Pacific/Pago_Pago'dan birine karşılık gelebilir. Üretim kodu için her zaman IANA tanımlayıcılarını kullanın.
TimeZone, yaz saati uygulamasının (DST) gözlemlendiği tüm bölgeler için otomatik olarak DST geçişlerini dikkate alır. Sistem, her saat dilimi için kesin geçiş tarihlerini içeren IANA Time Zone Database'den tarihsel verileri kullanır. isDaylightSavingTime özelliği, saat dilimi şu anda yaz saati uygulamasındaysa true döndürür.
nextDaylightSavingTimeTransition yöntemi, gelecekteki etkinlikleri planlamak için yararlı olan bir sonraki geçiş tarihini öğrenmeyi sağlar. Bu işlevsellik, Brezilya veya Fas gibi sık DST kuralı değişiklikleri olan bölgeler için özellikle önemlidir — 2024'e kadar Brezilya geçiş tarihlerini yıllık olarak değiştiriyordu ve manuel hesaplama uygulamalarda hatalara yol açıyordu.
Apple WWDC 2023'e göre, Foundation'ın temelini oluşturan ICU kütüphanesi (International Components for Unicode), her iOS güncellemesiyle DST verilerini günceller. Uygulamalar, bir sistem güncellemesinden sonra yaz saati verilerini bir günden fazla önbelleğe almamalıdır — IANA veritabanı, bir OS sürümü güncellemesi olmadan bile saat dilimi ayarlamaları yoluyla değişebilir.
import Foundation
// Europe/Moscow için DST'yi kontrol et
let moscow = TimeZone(identifier: "Europe/Moscow")!
let now = Date()
let isMoscowDST = moscow.isDaylightSavingTime(for: now)
print("Moskova şu anda DST'de: \(isMoscowDST)")
// Sonraki DST geçiş tarihini al
if let nextTransition = moscow.nextDaylightSavingTimeTransition(
after: now
) {
let dstOffset = moscow.daylightSavingTimeOffset(
for: nextTransition
)
print("Sonraki geçiş: \(nextTransition), DST farkı: \(dstOffset)s")
}
// DST farkındalığıyla güvenli dönüştürme
let newYork = TimeZone(identifier: "America/New_York")!
let offsetNY = newYork.secondsFromGMT(for: now)
print("NY geçerli farkı: \(offsetNY / 3600)h")
Önemli núns: secondsFromGMT(for:) belirtilen tarih için DST'yi dikkate alırken, secondsFromGMT() yalnızca geçerli saat için geçerlidir. Tarihsel tarihleri biçimlendirirken her zaman Date parametresiyle sürümü kullanın: secondsFromGMT(for: someHistoricalDate). Fark 1–2 saat olabilir, bu da günlükler veya tarihsel veriler için kritiktir.
Belirli bir saat dilimiyle tarih biçimlendirme, TimeZone ile çalışırken en yaygın görevdir. DateFormatter, bir Date'i dizeye dönüştürmek için timeZone özelliğini kullanır. timeZone açıkça ayarlanmazsa, biçimlendirici TimeZone.current — kullanıcının cihazında ayarlı saat dilimini kullanır ve bu da sunucu verileri için beklenmeyen sonuçlara yol açabilir.
import Foundation
// Belirli saat diliminde tarih biçimlendir
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("Tokyo saati: \(tokyoTime)")
// Kullanıcı seçimi için kullanılabilir tanımlayıcılar
let displayNames: [(String, String)] = TimeZone.knownTimeZoneIdentifiers
.prefix(20)
.map { ($0, TimeZone(identifier: $0)!.localizedName(
for: .generic, locale: .current
)) }
// İki saat dilimini karşılaştır
let london = TimeZone(identifier: "Europe/London")!
let difference = tokyo.secondsFromGMT(for: Date())
- london.secondsFromGMT(for: Date())
print("Tokyo-Londra farkı: \(difference / 3600)h")
// Kısaltma sözlüğüyle çalış
let knownAbbrevs = TimeZone.abbreviationDictionary
for (abbr, ident) in knownAbbrevs.sorted(by: { $0.key < $1.key }).prefix(5) {
print("\(abbr) -> \(ident)")
}
Saat diliminin yerelleştirilmiş adı localizedName(for:locale:) aracılığıyla belirtilen dilde insan tarafından okunabilir bir ad döndürür. Örneğin, Rus yerel ayarıyla Europe/Moscow için yöntem Rusça adı “Moskva” döndürür ve İngiliz yerel ayarıyla — “Moscow Time” döndürür. Kullanılabilir stiller: .standard (standart ad), .daylightSaving (yaz saati) ve .shortGeneric (kısa).
import Foundation
let paris = TimeZone(identifier: "Europe/Paris")!
let nameRU = paris.localizedName(
for: .standard,
locale: Locale(identifier: "ru_RU")
)
print("Rusça ad: \(nameRU)")
// Bölgenin aynı günde olup olmadığını kontrol et
let isSameDay = Calendar.current.isDate(
Date(),
equalTo: Date(),
toGranularity: .day
)
print("Saat dilimlerinde aynı gün: \(isSameDay)")
Saat dilimi tanımlayıcısının serileştirilmesi, TimeZone'u veritabanlarında veya UserDefaults'ta saklamak için en iyi uygulamadır. Tanımlayıcıyı (Europe/Moscow gibi bir dize) kaydedin, saniye cinsinden farkı veya bir kısaltmayı değil. DST değişiklikleriyle fark değişebilir ve kısaltmalar belirsizdir. Geri yükleme: TimeZone(identifier: savedString).
Saat dilimi tanımlayıcısı yerine sabit fark kullanma en yaygın hatadır. TimeZone(secondsFromGMT: 10800) DST'yi dikkate almaz, bu nedenle yaz aylarında Europe/Moscow için bu yapı 1 saat hatalı fark verir. Yaz saati uygulaması olan bölgeler için her zaman IANA tanımlayıcısını kullanın.
TimeZone(identifier:) başlatırken nil işlemesini unutma ikinci en yaygın hatadır. Kullanıcı hatalı bir tanımlayıcı girerse (örneğin “Europe/Moscow” yerine “moscow”), yapıcı nil döndürür. İsteğe bağlı değeri işlemeden uygulama çalışma zamanı hatasıyla çöker. guard let veya bilinen bir geri dönüşle TimeZone(identifier:) kullanın.
Gelecekteki tarihlerle çalışırken DST'yi görmezden gelme. TimeZone.secondsFromGMT(for:), belirli bir tarih için farkı almanın tek doğru yoludur. Tarihsel veya gelecekteki tarihler için parametresiz secondsFromGMT() kullanmak, geçerli an için farkı verir ve bu, belirtilen tarihteki gerçek farkla eşleşmeyebilir, özellikle DST'yi kaldırmış veya başlatmış bölgeler için.
Stack Overflow (2024)'e göre, DateFormatter ile ilgili soruların yaklaşık %15'i yanlış timeZone yapılandırmasıyla ilgilidir. Tipik bir senaryo: sunucu UTC'de bir tarih gönderir, geliştirici biçimlendiricinin timeZone'unu ayarlamadan biçimlendirir ve tarih cihazın saat diliminde görüntülenir ve farklı bölgelerden kullanıcılar arasında kafa karışıklığı yaratır. Kural: sunucu verileri için her zaman biçimlendiricinin timeZone'unu açıkça ayarlayın.
Sıkça Sorulan Sorular
TimeZone iOS ve macOS'te saat dilimleriyle çalışmak için bir Foundation sınıfıdır. UTC farkı, yaz saati uygulaması kuralları ve IANA Time Zone Database'e dayalı saat dilimi tanımlayıcıları hakkında bilgi sağlar.
Üç biçim: IANA tanımlayıcıları (Europe/Moscow), kısaltmalar (MSK, EST) ve sayısal farklar (+0300). Apple, üretim kodu için tek net biçim olarak IANA tanımlayıcılarının kullanılmasını önerir.
Otomatik olarak secondsFromGMT(for:) ve isDaylightSavingTime(for:) yöntemleri aracılığıyla. TimeZone, her iOS sürümüyle güncellenen tarihsel IANA verilerini kullanarak herhangi bir tarih için doğru DST geçişlerini garanti eder.
TimeZone.current kullanıcının ayarlarda seçtiği saat dilimini döndürür (coğrafi olandan farklı olabilir). TimeZone.system, coğrafi konuma göre otomatik olarak belirlenen ve kullanıcı tarafından geçersiz kılınamayan cihaz saat dilimini döndürür.
TimeZone.current geçerli cihaz saat dilimini döndürür. Tanımlayıcıyı almak için identifier özelliğini kullanın: TimeZone.current.identifier. Yerelleştirilmiş bir ad için localizedName(for:locale:) çağrısı yapın.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun