ISO8601DateFormatter, iOS ve macOS'ta uluslararası standart ISO 8601'e göre tarihleri biçimlendirmek ve ayrıştırmak için tasarlanmış bir Foundation sınıfıdır. Apple Developer Documentation, 2024'e göre, ISO8601DateFormatter DateFormat'i manuel olarak ayarlamaya gerek kalmadan milisaniyeleri, zaman dilimlerini ve saniye kesirlerini otomatik olarak işler. DateFormatter'ın aksine, bu sınıf Locale ve TimeZone'a bağlı değildir — ISO 8601 spesifikasyonuna göre sıkı bir şekilde çalışır ve bu da onu sunucu ve istemci arasında tarih alışverişi için ideal kılar. Sınıf, iOS 10 ve macOS 10.12'den itibaren kullanılabilir.
Ana Noktalar
ISO8601DateFormatter, Foundation'da Formatter'ın özelleştirilmiş bir alt sınıfıdır ve Date ile ISO 8601 biçimli dizeler arasında çift yönlü dönüşüm uygular. ISO 8601 standardı (International Standard for the Representation of Dates and Times), tarih ve saat alışverişi için uluslararası bir biçim tanımlar: 2024-07-21T14:30:00+00:00. DateFormatter'ın aksine, bu sınıf dateFormat belirtilmesini gerektirmez ve verilen seçeneklere göre dize yapısını otomatik olarak belirler.
ISO8601DateFormatter'ın DateFormatter'a göre ana avantajları: yerel ayara bağımlılık yok (ayrıştırma herhangi bir cihazda aynı şekilde çalışır), saniye kesirleri için yerleşik destek (herhangi bir sayıda ondalık basamakla) ve iletilen seçeneklere dayalı otomatik biçim algılama. Sınıf ayrıca Z sonekini (UTC tanımı), +HH:mm biçimindeki zaman dilimlerini ve azaltılmış hassasiyeti (saatsiz sadece tarih) doğru şekilde işler.
ISO Spesifikasyonuna (ISO 8601-1:2019) göre, standart dört hassasiyet seviyesini destekler: yıl (2024), yıl-ay (2024-07), tam tarih (2024-07-21) ve zaman dilimli tarih-saat (2024-07-21T14:30:00+00:00). ISO8601DateFormatter, biçim seçeneklerinin bir kombinasyonu aracılığıyla tüm bu seviyeleri kapsar ve geliştiriciyi manuel olarak dateFormat dizeleri oluşturmaktan kurtarır.
Çalışma prensibi ISO8601DateFormatter, her biri çıktıya belirli bir tarih veya saat bileşeni ekleyen bit seçeneklerinin (formatOptions) bir kombinasyonuna dayanır. Örneğin, .withFullDate seçeneği yıl, ay ve günü içerir; .withTime saat, dakika ve saniyeyi içerir. Seçenekleri birleştirerek, geliştirici bir dateFormat dizesi yazmadan istenen hassasiyet seviyesini elde eder.
Dahili olarak, ISO8601DateFormatter ayrıştırma için ICU kütüphanesini kullanır, ancak sabit ISO 8601 kurallarıyla. Bu, cihazdaki Locale ve TimeZone ayarlarını yok saydığı anlamına gelir — sonuç her zaman tahmin edilebilirdir. Zaman dilimini ayarlamak için varsayılanı UTC olan timeZone özelliği kullanılır. timeZone nil olarak ayarlanırsa, cihazın yerel saati kullanılır.
| Seçenek | Açıklama | Çıktı örneği |
|---|---|---|
| .withFullDate | Yıl, ay, gün | 2024-07-21 |
| .withTime | Saat, dakika, saniye | 14:30:00 |
| .withMilliseconds | Saniye kesirleri (3 basamağa kadar) | .123 |
| .withFractionalSeconds | Saniye kesirleri (herhangi bir hassasiyet) | .123456 |
| .withTimeZone | Zaman dilimi | +03:00 |
| .withColonSeparatorInTimeZone | Zaman diliminde iki nokta ayırıcı | +03:00 (+0300'a karşı) |
| .withInternetDateTime | Tam biçim (tarih + saat + dilim) | 2024-07-21T14:30:00+00:00 |
Seçeneklerin birleştirilmesi: .withInternetDateTime, .withFullDate, .withTime ve .withTimeZone'un birleştirilmesine eşdeğerdir. Milisaniyeli dizeleri ayrıştırmak için .withFractionalSeconds ekleyin. .withMilliseconds'in saniye kesirlerini üç basamakla sınırladığını, .withFractionalSeconds'ın ise ondalık noktadan sonra birden dokuza kadar herhangi bir hassasiyeti desteklediğini unutmamak önemlidir.
Biçim seçenekleri ISO8601DateFormatter'ın seçenekleri üç gruba ayrılır: tarih bileşenleri (withFullDate, withYear, withMonth, withDay, withWeekOfYear), saat bileşenleri (withTime, withHours, withMinutes, withSeconds) ve ek ayarlar (withMilliseconds, withFractionalSeconds, withTimeZone, withColonSeparatorInTimeZone, withDashSeparatorInDate, withFullTime). Bunları birleştirerek neredeyse herhangi bir ISO 8601 alt biçimini elde edebilirsiniz.
Önemli nüans: .withFractionalSeconds ve .withMilliseconds birbirini dışlar — her ikisi de ayarlanırsa, .withFractionalSeconds uygulanır. Sunucu verilerinden milisaniyeleri ayrıştırmak için .withFractionalSeconds önerilir, çünkü birçok sunucu üç, altı veya dokuz basamaklı saniye kesirleri gönderir ve .withFractionalSeconds herhangi bir uzunluğu işler.
import Foundation
// Configure ISO8601DateFormatter
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
// Different format option combinations
formatter.formatOptions = [.withFullDate]
let dateOnly = formatter.string(from: Date())
print("Date: \(dateOnly)")
formatter.formatOptions = [.withFullDate, .withTime]
let dateTime = formatter.string(from: Date())
print("DateTime: \(dateTime)")
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let full = formatter.string(from: Date())
print("Full: \(full)")
// Parse string with milliseconds
let serverString = "2024-07-21T14:30:00.123456+03:00"
if let parsed = formatter.date(from: serverString) {
print("Parsed: \(parsed)")
}
Temel kullanım ISO8601DateFormatter'ın kullanımı, bir örnek oluşturma, timeZone (sunucu verileri için UTC önerilir) ve formatOptions ayarlama ile başlar, ardından biçimlendirme için string(from:) ve ayrıştırma için date(from:) çağrılabilir. DateFormatter'ın aksine, Locale hakkında endişelenmeye gerek yoktur — sınıf bölgesel ayarları yok sayar.
import Foundation
let formatter = ISO8601DateFormatter()
// Parse different ISO 8601 formats
let strings: [String] = [
"2024-07-21T14:30:00Z",
"2024-07-21T14:30:00+03:00",
"2024-07-21T14:30:00.123Z",
"2024-07-21"
]
for str in strings {
if let autoParsed = formatter.date(from: str) {
print("Parsed '\(str)': \(autoParsed)")
} else {
// Use withFullDate for date-only strings
formatter.formatOptions = [.withFullDate]
if let fallback = formatter.date(from: str) {
print("Fallback parsed '\(str)': \(fallback)")
}
formatter.formatOptions = [.withInternetDateTime]
}
}
// Serialize to RFC 3339 (GitHub API)
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let rfc3339 = formatter.string(from: Date())
print("RFC 3339: \(rfc3339)")
Değişken uzunlukta saniye kesirleri olan tarihleri ayrıştırma — birçok modern API'nin özelliğidir. Bir sunucu 2024-07-21T14:30:00.123Z (3 basamak) veya 2024-07-21T14:30:00.123456Z (6 basamak) gönderebilir. .withFractionalSeconds seçeneği ile ISO8601DateFormatter her iki değişkeni de doğru şekilde işlerken, dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" ile DateFormatter yalnızca üç basamaklı milisaniyeleri işler.
import Foundation
let variantFormatter = ISO8601DateFormatter()
variantFormatter.formatOptions = [
.withInternetDateTime,
.withFractionalSeconds
]
// Different fractional second precision
let variants: [String] = [
"2024-07-21T14:30:00.1Z",
"2024-07-21T14:30:00.12Z",
"2024-07-21T14:30:00.123Z",
"2024-07-21T14:30:00.123456Z",
"2024-07-21T14:30:00.123456789Z"
]
for variant in variants {
if let parsed = variantFormatter.date(from: variant) {
print("OK: \(variant) -> \(parsed)")
} else {
print("FAIL: \(variant)")
}
}
// Use withMilliseconds (3 digits only)
variantFormatter.formatOptions = [
.withInternetDateTime,
.withMilliseconds
]
let milliParsed = variantFormatter.string(from: Date())
print("With milliseconds: \(milliParsed)")
Tüm değişkenlerin ayrıştırma testi: gösterilen kod, .withFractionalSeconds ile ISO8601DateFormatter'ın 1 ila 9 basamak arasında herhangi bir uzunluktaki saniye kesirlerini başarıyla işlediğini gösterir. Bu, farklı sunucu platformlarıyla uyumluluk için önemlidir: .NET genellikle 7 basamak (100 nanosaniye tick) üretir, Python — 6, Java — sürüme bağlı olarak 3 veya 9.
DateFormatter da ISO 8601'i ayrıştırabilir, ancak dateFormat, locale ve timeZone'un manuel olarak yapılandırılmasını gerektirir. Ana sorun, DateFormatter'ın Locale'ye bağlı olması ve en_US_POSIX ayarlanmazsa, standart olmayan tarih biçimlerine sahip bölgelerdeki kullanıcılar için ayrıştırmanın başarısız olabilmesidir. ISO8601DateFormatter bu sorunu mimari düzeyde çözer: Locale kullanmaz.
| Parametre | ISO8601DateFormatter | DateFormatter |
|---|---|---|
| Locale Yapılandırması | Gerekli değil (yok sayar) | en_US_POSIX zorunlu |
| DateFormat | Otomatik (seçeneklerle) | Manuel biçim dizesi |
| Saniye kesirleri | Herhangi bir hassasiyet (.withFractionalSeconds) | Sabit SSS |
| Z soneki | Doğru şekilde işler | DateFormat aracılığıyla |
| Performans | Daha yüksek (özelleştirilmiş) | Daha düşük (genel) |
| Standart | Sadece ISO 8601 | Herhangi bir biçim |
| iOS Sürümü | iOS 10+ | iOS 2+ |
DateFormatter ne zaman kullanılır: bir tarihi ISO 8601 olmayan bir biçimde biçimlendirmeniz gerekiyorsa (örneğin, kullanıcı arayüzü için "21 Temmuz 2024") veya iOS 9 ve öncesini desteklemeniz gerekiyorsa. Tüm sunucu-istemci tarih alışverişi görevleri için ISO8601DateFormatter kullanın — daha güvenli, daha verimli ve daha az kod gerektirir. ISO 8601 için DateFormatter, yerel ayar ve bölgesel ayarlarla ilgili potansiyel hataların kaynağıdır.
DateFormatter'dan ISO8601DateFormatter'a geçiş: DateFormatter + dateFormat + locale + timeZone oluşturmayı, ISO8601DateFormatter + formatOptions + timeZone ile değiştirin. date(from:) aracılığıyla dize ayrıştırma değişmeden kalır. Geriye dönük uyumluluk için, DateFormatter'a geri dönüşle birlikte #available(iOS 10, *) kullanabilirsiniz.
Unutulan formatOptions yapılandırması biçimlendiricinin varsayılan değeri — .withInternetDateTime — kullanmasına neden olur. Sunucu saatsiz bir tarih gönderirse (2024-07-21), ayrıştırma nil döndürür. formatOptions'ın sunucudan gelebilecek tüm olası biçimleri kapsadığını her zaman kontrol edin. Değişken biçimlere sahip API'ler için farklı seçenek kombinasyonlarıyla geri dönüş denemeleri kullanın.
withMilliseconds ve withFractionalSeconds arasındaki karışıklık — saniye kesirleri olan tarihleri ayrıştırırken yaygın bir hatadır. withMilliseconds, ondalık noktadan sonra tam olarak 3 basamak bekler. Sunucu 6 basamak (mikrosaniye) gönderirse, withMilliseconds ile ayrıştırma başarısız olur. Herhangi bir sayıda basamakla uyumluluk için .withFractionalSeconds kullanın. .withFractionalSeconds iOS 13'te kullanıma sunulmuştur; daha eski sürümler için dateFormat ile DateFormatter kullanın.
Zaman dilimini yok saymak — başka bir yaygın sorundur. Sunucu zaman dilimiyle (+03:00) bir tarih gönderir ve biçimlendirici UTC'ye ayarlanmışsa, ayrıştırma başarısız olmaz, ancak sonuç UTC olur. Geliştiriciler genellikle Date'in zaman dilimini korumasını bekler, ancak Date mutlak bir zaman noktasıdır — zaman dilimi bilgisini saklamaz. Doğru görüntüleme için zaman dilimini ayrı olarak kaydedin veya doğru timeZone ile ISO8601DateFormatter kullanın.
Apple Forumuna (2024) göre, ISO8601DateFormatter ile ilgili soruların yaklaşık %20'si saniyelerin isteğe bağlı olduğu biçimle ilgilidir. ISO 8601 standardı saniyesiz bir biçime izin verir: 2024-07-21T14:30+03:00. .withInternetDateTime ile ISO8601DateFormatter bu biçimi desteklemez — ayrıştırmak için dateFormat = "yyyy-MM-dd'T'HH:mmZ" ile DateFormatter gerekir. Kısaltılmış saat biçimini kullanan API'lerle çalışırken bu sınırlamayı dikkate almak önemlidir.
Sıkça Sorulan Sorular
ISO8601DateFormatter — ISO 8601 biçiminde tarihleri biçimlendirmek ve ayrıştırmak için özelleştirilmiş bir Foundation sınıfıdır, iOS 10'dan itibaren kullanılabilir. dateFormat'ı manuel olarak ayarlamadan standart biçimleri otomatik olarak işler.
ISO8601DateFormatter Locale'ye bağlı değildir, dateFormat yerine seçenekleri kullanır ve herhangi bir uzunluktaki saniye kesirlerini doğru şekilde işler. DateFormatter evrenseldir, ancak manuel yapılandırma gerektirir ve bölgesel ayarlarla ilgili hatalara yatkındır.
.withFractionalSeconds seçeneğini kullanın — ondalık noktadan sonra 1 ila 9 basamağı destekler. Hassasiyet değişebiliyorsa .withMilliseconds kullanmayın. .withFractionalSeconds iOS 13'ten itibaren kullanılabilir.
Varsayılan olarak UTC. Değiştirmek için timeZone özelliğini ayarlayın. timeZone = nil ise, cihazın yerel saati kullanılır. +HH:MM biçiminde açık zaman dilimi olan bir dize ayrıştırılırken, biçimlendirici bunu otomatik olarak dikkate alır.
Çünkü varsayılan formatOptions .withInternetDateTime'dır, tarih + saat + zaman dilimi bekler. Sadece tarihi ayrıştırmak için formatOptions = [.withFullDate] ayarlayın. Her iki biçimi desteklemek için farklı seçeneklerle geri dönüş kullanı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