Calendar, bir takvim sistemi tanımlayan ve takvim hesaplamaları için yöntemler sağlayan bir Foundation sınıfıdır: tarih bileşenlerini çıkarma, tarihler arasındaki farkları hesaplama, dönem sınırlarını bulma ve tarihleri kaydırma. Takvim, mutlak zamanı (Date) insan tarafından okunabilir bileşenlere bağlar ve bölgesel özellikleri dikkate alır: haftanın başlangıcı, saat dilimi ve yaz saati uygulaması. Apple Developer Documentation'a (2025) göre Foundation, Gregoryen'den Budist ve Japon'a kadar 17 takvim sistemini destekleyerek Calendar'ı uluslararası uygulamalar için evrensel bir araç haline getirir.
Ana Noktalar
Calendar, ICU (International Components for Unicode) tabanlı takvim hesaplamalarını uygulayan bir Foundation sınıfıdır. Takvim, mutlak zamanın (Date) takvim bileşenlerine nasıl eşlendiğini tanımlar: yıl, ay, gün, saat, dakika, saniye. Calendar olmadan hangi yıl, ay ve günde olduğunu bilmek imkansızdır — Date'in kendisi bu bilgiyi içermez.
Takvim üç grup parametreyi dikkate alır: takvim sistemi (Gregoryen, Budist, Japon), saat dilimi ve bölgesel ayarlar. Calendar.current, kullanıcının sistem ayarlarından üçünü de birleştirir. Calendar.autoupdatingCurrent, NotificationCenter aracılığıyla uygulamayı yeniden başlatmadan ayarlar değiştiğinde otomatik olarak güncellenen özel bir sürümdür.
Calendar, Foundation'da bir değer tipidir (value type). Calendar(identifier:) sabit parametrelerle yeni bir örnek oluşturur. Calendar kopyalanabilir, == ile karşılaştırılabilir ve sözlükte anahtar olarak kullanılabilir. Bu, test için belirli timeZone ve locale ayarlarına sahip takvimler oluşturmaya olanak tanır.
Calendar, Objective-C NSCalendar'ın Swift sürümüdür ve as Calendar / as NSCalendar aracılığıyla köprülenir. Modern Swift'te Calendar her yerde kullanılır. NSCalendar, Objective-C API'leriyle geriye dönük uyumluluk için kalır. Calendar, NS öneki olmadan, type-safe argümanlar ve Swift optional'ları ile eksiksiz bir yöntem setine sahiptir.
Thread Güvenliği — Calendar okuma için thread-safe'dir. Oluşturulan bir örnek birden çok thread'den güvenle okunabilir. Özelliklerin (timeZone, locale) değiştirilmesi thread-safe değildir — farklı yapılandırmalar için ayrı Calendar örnekleri oluşturun.
Foundation, Calendar.Identifier numaralandırması aracılığıyla 17 takvim sistemini destekler. Her sistemin artık yıllar, ay sayısı ve dönem başlangıcı için kendi kuralları vardır. Takvim seçimi tüm hesaplamaları etkiler: dateComponents, dateInterval, nextDate.
Başlıca takvim sistemleri:
Calendar(identifier: .gregorian) — en çok kullanılanıdır. Uluslararası standart ISO 8601'e uygundur ve çoğu ülkede varsayılan takvimdir. Uluslararası kitleye sahip uygulamalar için Calendar.current kullanın — kullanıcının sistem takvimiyle otomatik olarak eşleşir.
| Tanımlayıcı | Tür | Kullanım Bölgesi |
|---|---|---|
| .gregorian | Güneş takvimi | Uluslararası |
| .buddhist | Güneş takvimi | Tayland, Kamboçya |
| .japanese | Güneş takvimi | Japonya |
| .hebrew | Ay-güneş takvimi | İsrail |
| .islamic | Ay takvimi | İslam ülkeleri |
| .chinese | Ay-güneş takvimi | Çin |
DateComponents ve Calendar ayrılmaz bir çifttir. Calendar.dateComponents(_:from:), takvimin saat dilimini dikkate alarak Date'ten bileşenleri çıkarır. Calendar.date(from:), DateComponents'ten Date oluşturur ve eksik alanları varsayılan değerlerle doldurur: gün = 1, saat = 0, dakika = 0, saniye = 0.
Calendar.component yöntemi tek bir bileşeni çıkarır, hızlı kontroller için uygundur. Calendar.dateComponents tek bir çağrıda birden çok bileşeni çıkarır — bu daha verimlidir çünkü Calendar her bileşen için ayrı ayrı yerine bir kez takvim hesaplaması yapar. 3+ bileşenli bir liste için her zaman dateComponents kullanın.
Calendar.compare, belirtilen hassasiyette iki Date'i karşılaştırır. toGranularity parametresi bileşen hassasiyetini belirler: .year yalnızca yılı, .month — yıl ve ayı, .day — yıl, ay, günü karşılaştırır. Bu, saati göz ardı ederek iki tarihin aynı güne denk gelip gelmediğini kontrol etmek için kullanışlıdır.
let calendar = Calendar.current
let now = Date()
// Tek bir bileşeni çıkarma
let year = calendar.component(.year, from: now)
// Bir dizi bileşeni çıkarma
let comps = calendar.dateComponents(
[.year, .month, .day], from: now
)
// Gün hassasiyetiyle karşılaştırma
let isSameDay = calendar.compare(date1, to: date2,
toGranularity: .day) == .orderedSame
// Tarihin bugün olup olmadığını kontrol et
let isToday = calendar.isDateInToday(someDate)
Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday — göreceli kontroller için yöntemler. Calendar.isDate(_:inSameDayAs:), takvimin saat dilimini dikkate alarak iki tarihin aynı takvim gününe denk gelip gelmediğini kontrol eder. Bu yöntemler dahili olarak Calendar.compare kullanır ve sık çağrılar için optimize edilmiştir.
Calendar.dateInterval, analitik ve kullanıcı arayüzü için en kullanışlı yöntemlerden biridir. Belirtilen bileşen için bir DateInterval döndürür: bir gün, hafta, ay, yılın başlangıcı ve bitişi. DateInterval, start (Date) ve end (Date) — dönem sınırlarını içerir. Örneğin, dateInterval(of: .weekOfYear, for: Date()) geçerli haftanın Pazartesi başlangıcını ve Pazar bitişini döndürür.
Calendar.date byAdding ile — tarihleri kaydırmak için bir yöntem. Calendar.date(byAdding: .day, value: 7, to: Date()) bir hafta sonraki tarihi döndürür. Calendar.date(byAdding: DateComponents) daha esnek bir sürümdür ve aynı anda birden çok bileşeni kaydırmaya olanak tanır: +1 ay +3 gün. Calendar otomatik olarak farklı ay uzunluklarını ve artık yılları dikkate alır.
Calendar.nextDate, belirtilen DateComponents ile eşleşen bir sonraki tarihi arar. matchingPolicy parametresi, uyuşmazlık durumunda davranışı tanımlar: .nextTime — zamandaki bir sonraki eşleşme, .nextTimePreservingSmallerComponents — orijinal tarihten dakika ve saniyeleri korur, .strict — tam eşleşme gerektirir.
let calendar = Calendar.current
let today = Date()
// Haftanın başı ve sonu
let weekInterval = calendar.dateInterval(
of: .weekOfYear, for: today
)!
// 1 ay kaydırma
let nextMonth = calendar.date(
byAdding: .month, value: 1, to: today
)!
// DateComponents aracılığıyla kaydırma
var delta = DateComponents()
delta.month = 1
delta.day = 3
let shifted = calendar.date(byAdding: delta, to: today)!
// Bir sonraki 13'üncü Cuma
let friday13Components = DateComponents(
weekday: 6, day: 13
)
let nextFriday13 = calendar.nextDate(
after: today, matching: friday13Components,
matchingPolicy: .nextTime
)
EnumerateDates — bir desene göre tarihler üzerinde yineleme yapmak için güçlü bir yöntem. Calendar.enumerateDates(startingAfter:matching:matchingPolicy:using:), blok stop = true döndürene kadar her eşleşme için bir blok çağırır. Takvimlerde ve programlarda yinelenen olaylar oluşturmak için kullanılır. Bu yöntem, ICU tarafından optimize edildiğinden, nextDate ile manuel döngüden daha verimlidir.
TimeZone, Calendar'ın ayrılmaz bir parçasıdır. Saat dilimi, mutlak bir Date'in hangi takvim saatine karşılık geldiğini belirler. UTC'de ve Moskova'da aynı Date farklı bileşenler üretir: UTC'de Date() 10:00 gösterebilirken, MSK'da — 13:00. Calendar.timeZone varsayılan olarak TimeZone.current'tir.
Locale, haftanın ilk gününü, yılın ilk haftasındaki minimum gün sayısını (minDaysInFirstWeek) ve ay/hafta günü adlarını (DateFormatter aracılığıyla dönüştürme sırasında) etkiler. Calendar.locale varsayılan olarak Locale.current'tir. Rus bölgesel ayarlarında hafta Pazartesi günü başlar, Amerikan ayarlarında — Pazar günü.
Calendar.availableIdentifiers, desteklenen tüm takvim tanımlayıcılarının bir listesini döndürür. Statik özellik Calendar.availableCalendarIdentifiers, aynı tanımlayıcılara sahip bir dize dizisidir. Takvim seçim arayüzü oluşturmak ve cihazda belirli bir takvim sisteminin kullanılabilirliğini kontrol etmek için kullanılır.
// Belirli saat dilimiyle Calendar
var utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!
// Rus bölgesel ayarlarıyla Calendar
var russianCalendar = Calendar(identifier: .gregorian)
russianCalendar.locale = Locale(identifier: "ru_RU")
// İlk iş günü bölgesel ayarlara bağlıdır
let firstWeekday = russianCalendar.firstWeekday
// 2 = Pazartesi (ru_RU'da)
// Mevcut takvimlerin listesi
for identifier in Calendar.availableIdentifiers {
print(identifier)
}
firstWeekday — haftanın hangi gününün ilk olarak kabul edildiğini belirleyen bir Calendar özelliğidir. Rus bölgesel ayarlarında Sunday = 2 (Pazartesi ilktir). Amerikan bölgesel ayarlarında Sunday = 1. Bu, weekOfMonth ve weekOfYear'ı etkiler: aynı tarih farklı bölgesel ayarlarda farklı hafta numaralarına ait olabilir. Tarihlerle çalışan uygulamalar için Calendar.current kullanın veya firstWeekday'i açıkça ayarlayın.
Calendar'in yeteneklerini gösteren pratik senaryoları inceleyelim. Her örnek belirli bir iOS geliştirme görevini çözer ve takvim hesaplamalarının doğru kullanımını gösterir.
Calendar.dateInterval(of: .month, for:) geçerli ayın sınırlarını döndürür. Bir Date'in bu aralık içinde olup olmadığını kontrol etmek, bir tarihin geçerli aya ait olup olmadığını belirlemenin en hızlı yoludur. Bir alternatif, .month hassasiyetiyle Calendar.compare kullanmaktır: sonuç .orderedSame ise, ay eşleşir.
func isInCurrentMonth(_ date: Date) -> Bool {
let calendar = Calendar.current
let monthInterval = calendar.dateInterval(
of: .month, for: Date()
)!
return monthInterval.contains(date)
}
// Bir aydaki gün sayısı
func daysInMonth(for date: Date) -> Int {
let calendar = Calendar.current
return calendar.range(
of: .day, in: .month, for: date
)?.count ?? 0
}
// Doğru sarmalamayla ay ekleme
func addMonths(_ months: Int, to date: Date) -> Date {
let calendar = Calendar.current
return calendar.date(
byAdding: .month, value: months, to: date
)!
}
Calendar.range(of:in:for:), başka bir bileşenin bağlamında belirtilen bir bileşen için geçerli değerlerin aralığını döndürür. Örneğin, range(of: .day, in: .month, for: date) 31 günlük aylar için 1..<32 veya artık yıl olmayan bir yılda Şubat için 1..<29 döndürür. Sabit kodlanmış değerler kullanmak yerine bir aydaki gün sayısını öğrenmenin doğru yoludur.
Ay ekleme, Calendar.date(byAdding:value:to:) aracılığıyla sınır tarihlerini doğru şekilde işler. 31 Ocak'a 1 ay eklenirse, Calendar 28 Şubat'ı (veya artık yılda 29) döndürür, TimeInterval aracılığıyla sadece 30 gün eklenmesiyle elde edilecek 3 Mart yerine. Bu, takvim hesaplamaları için TimeInterval kullanmamanın bir başka nedenidir.
| Calendar Yöntemi | Amaç | Örnek |
|---|---|---|
| dateInterval | Dönem sınırları | Bir ayın başlangıcı ve bitişi |
| range(of:in:for:) | Bileşen aralığı | Geçerli aydaki günler |
| date(byAdding:) | Tarih kaydırma | Bugünden +1 ay |
| isDateInToday | Bugün kontrolü | Tarih bugüne ait mi? |
| compare(toGranularity:) | Hassasiyetle karşılaştırma | Saat göz ardı edilerek aynı gün |
Sıkça Sorulan Sorular
Calendar.current, kullanıcının sistem ayarlarından takvimi döndürür — Gregoryen olmayabilir (örneğin Tayland'da Budist). Calendar(identifier: .gregorian) ayarlardan bağımsız olarak her zaman bir Gregoryen takvimi oluşturur. Tarihleri görüntülemek için Calendar.current kullanın ve iş mantığı için açıkça seçilmiş bir tanımlayıcı kullanın.
Bu, ayların farklı uzunluklarından kaynaklanır. Geçerli tarih 31 Ocak ise, 1 ay eklemek 28 Şubat'ı verir çünkü Şubat'ta 31 gün yoktur. Calendar, tarihi otomatik olarak ayın son geçerli gününe ayarlar. Hassas kontrol için, ayın ilk gününe geçmek için day: 1 ile DateComponents kullanın.
DateFormatter, Calendar.current — kullanıcının sistem takvimini kullanır. Bir uygulama ayarlardan bağımsız olarak tarihleri her zaman Gregoryen takviminde göstermeliyse, formatter.calendar = Calendar(identifier: .gregorian) olarak ayarlayın. Bu, tüm kullanıcılar için tek tip görüntüleme sağlar.
Calendar.range(of: .day, in: .year, for: date) 365 veya 366 gün döndürür. Daha basit: Calendar.date(from: DateComponents(year: year, month: 2, day: 29)) != nil — 29 Şubat mevcutsa, yıl artık yıldır. Calendar, belirli takvim sisteminin kurallarını otomatik olarak işler.
Evet, firstWeekday özelliği yazılabilir. Değişiklik weekOfMonth, weekOfYear ve hafta numaralarıyla ilgili tüm hesaplamaları etkiler. locale = Locale(identifier: “ru_RU”) olarak ayarlandığında, firstWeekday otomatik olarak 2 (Pazartesi) olur. Manuel ayar, locale'den gelen değeri geçersiz kılar.
Ö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