Calendar — egy Foundation osztály, amely meghatározza a naptárrendszert és módszereket biztosít a naptári számításokhoz: dátumösszetevők kinyerése, dátumok közötti különbség kiszámítása, időszakhatárok keresése és dátumok eltolása. A naptár az abszolút időt (Date) ember által olvasható összetevőkhöz kapcsolja, és figyelembe veszi a regionális jellemzőket: a hét kezdetét, az időzónát és a nyári időszámítást. Az Apple Developer Documentation (2025) szerint a Foundation 17 naptárrendszert támogat — a Gergelytől a Buddhán és a Japánon át —, ami a Calendar-t univerzális eszközzé teszi a nemzetközivé tett alkalmazások számára.
Fő pontok
Calendar — egy Foundation osztály, amely az ICU (International Components for Unicode) alapján valósítja meg a naptári számításokat. A naptár meghatározza, hogy az abszolút idő (Date) hogyan képeződik le naptári összetevőkre: év, hónap, nap, óra, perc, másodperc. Calendar nélkül nem lehet megtudni, hogy milyen év, hónap és nap van ma — a Date önmagában nem tartalmazza ezt az információt.
A naptár három paramétercsoportot vesz figyelembe: naptárrendszert (Gergely, Buddha, Japán), időzónát és lokált. A Calendar.current mindhármat a felhasználó rendszerbeállításaiból kombinálja. A Calendar.autoupdatingCurrent — egy speciális verzió, amely automatikusan frissül a beállítások megváltozásakor az alkalmazás újraindítása nélkül a NotificationCenteren keresztül.
A naptár egy értéktípus (value type) a Foundation-ben. A Calendar(identifier:) egy új példányt hoz létre rögzített paraméterekkel. A naptár másolható, összehasonlítható == segítségével, és használható kulcsként egy szótárban. Ez lehetővé teszi naptárak létrehozását konkrét timeZone és locale beállításokkal a teszteléshez.
Calendar — az Objective-C NSCalendar Swift-verziója, az as Calendar / as NSCalendar híddal. A modern Swift-ben mindenhol a Calendar-t használják. Az NSCalendar a visszafelé kompatibilitás érdekében maradt meg az Objective-C API-val. A Calendar rendelkezik a módszerek teljes készletével NS előtag nélkül, type-safe argumentumokkal és Swift opcionalitással.
Thread Safety — a Calendar olvasásra thread-safe. A létrehozott példány több szálból is biztonságosan olvasható. A tulajdonságok módosítása (timeZone, locale) nem thread-safe — különböző konfigurációkhoz hozzon létre külön Calendar példányokat.
A Foundation 17 naptárrendszert támogat a Calendar.Identifier felsoroláson keresztül. Minden rendszernek megvannak a saját szabályai a szökőévekre, a hónapok számára és az éra kezdetére. A naptár kiválasztása minden számítást befolyásol: dateComponents, dateInterval, nextDate.
Fő naptárrendszerek:
Calendar(identifier: .gregorian) — a leggyakrabban használt. Megfelel a nemzetközi ISO 8601 szabványnak, és a legtöbb országban ez az alapértelmezett naptár. Nemzetközi közönségű alkalmazásokhoz használja a Calendar.current-et — automatikusan megfelel a felhasználó rendszernaptárának.
| Azonosító | Típus | Használati régió |
|---|---|---|
| .gregorian | Nap | Nemzetközi |
| .buddhist | Nap | Thaiföld, Kambodzsa |
| .japanese | Nap | Japán |
| .hebrew | Hold-Nap | Izrael |
| .islamic | Hold | Iszlám országok |
| .chinese | Hold-Nap | Kína |
DateComponents és Calendar — elválaszthatatlan pár. A Calendar.dateComponents(_:from:) kinyeri az összetevőket a Date-ből a naptár időzónájának figyelembevételével. A Calendar.date(from:) Date-et épít a DateComponents-ből, a hiányzó mezőket alapértékekkel kitöltve: nap = 1, óra = 0, perc = 0, másodperc = 0.
A Calendar.component metódus egy összetevőt nyer ki, ami kényelmes a gyors ellenőrzéshez. A Calendar.dateComponents egy összetevőkészletet nyer ki egy hívásban — ez hatékonyabb, mert a Calendar egyszer végzi el a naptári számításokat, nem minden összetevőre külön-külön. 3+ összetevőből álló lista esetén mindig a dateComponents-t használja.
Calendar.compare két Date-et hasonlít össze meghatározott pontossággal. A toGranularity paraméter határozza meg, hogy melyik összetevőig történjen az összehasonlítás: .year csak az évet hasonlítja össze, .month — évet és hónapot, .day — évet, hónapot, napot. Ez kényelmes annak ellenőrzésére, hogy két dátum ugyanarra a napra esik-e, az idő figyelembevétele nélkül.
let calendar = Calendar.current
let now = Date()
// Egy összetevő kinyerése
let year = calendar.component(.year, from: now)
// Összetevőkészlet kinyerése
let comps = calendar.dateComponents(
[.year, .month, .day], from: now
)
// Összehasonlítás nap pontossággal
let isSameDay = calendar.compare(date1, to: date2,
toGranularity: .day) == .orderedSame
// Ellenőrizze, hogy a dátum ma van-e
let isToday = calendar.isDateInToday(someDate)
Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday — relatív ellenőrzések metódusai. A Calendar.isDate(_:inSameDayAs:) ellenőrzi, hogy két dátum ugyanarra a naptári napra esik-e a naptár időzónájának figyelembevételével. Ezek a metódusok a Calendar.compare-t használják belsőleg, és gyakori hívásokra vannak optimalizálva.
Calendar.dateInterval — az egyik leghasznosabb metódus analitikához és UI-hoz. Visszaadja a DateInterval-et a megadott összetevőhöz: a nap, hét, hónap, év kezdetét és végét. A DateInterval tartalmazza a start (Date) és end (Date) értékeket — az időszak határait. Például a dateInterval(of: .weekOfYear, for: Date()) visszaadja az aktuális hét hétfő kezdetét és vasárnap végét.
Calendar.date byAdding-gal — metódus a dátum eltolásához. A Calendar.date(byAdding: .day, value: 7, to: Date()) visszaadja a dátumot egy hét múlva. A Calendar.date(byAdding: DateComponents) — rugalmasabb verzió, amely lehetővé teszi több összetevő egyidejű eltolását: +1 hónap +3 nap. A Calendar automatikusan figyelembe veszi a hónapok eltérő hosszát és a szökőéveket.
Calendar.nextDate megkeresi a következő dátumot, amely megfelel a megadott DateComponents-nek. A matchingPolicy paraméter határozza meg a viselkedést, ha nincs egyezés: .nextTime — következő egyezés időben, .nextTimePreservingSmallerComponents — megtartja a perceket és másodperceket az eredeti dátumból, .strict — pontos egyezést követel meg.
let calendar = Calendar.current
let today = Date()
// A hét kezdete és vége
let weekInterval = calendar.dateInterval(
of: .weekOfYear, for: today
)!
// Eltolás 1 hónappal
let nextMonth = calendar.date(
byAdding: .month, value: 1, to: today
)!
// Eltolás DateComponents segítségével
var delta = DateComponents()
delta.month = 1
delta.day = 3
let shifted = calendar.date(byAdding: delta, to: today)!
// Következő péntek 13.
let friday13Components = DateComponents(
weekday: 6, day: 13
)
let nextFriday13 = calendar.nextDate(
after: today, matching: friday13Components,
matchingPolicy: .nextTime
)
EnumerateDates — egy hatékony metódus a dátumok mintázat szerinti iterálásához. A Calendar.enumerateDates(startingAfter:matching:matchingPolicy:using:) egy blokkot hív meg minden egyezéshez, amíg a blokk vissza nem adja a stop = true értéket. Ismétlődő események generálására használják naptárakban és ütemezésekben. A metódus hatékonyabb, mint a manuális ciklus nextDate-tel, mert az ICU optimalizálja.
TimeZone — a Calendar elválaszthatatlan része. Az időzóna határozza meg, hogy az abszolút Date melyik naptári időnek felel meg. Ugyanaz a Date UTC-ben és Moszkvában különböző összetevőket ad: a Date() UTC-ben 10:00-t mutathat, MSK-ban pedig 13:00-t. A Calendar.timeZone alapértelmezés szerint egyenlő a TimeZone.current-tel.
Locale befolyásolja a hét első napját, az év első hetének minimális napszámát (minDaysInFirstWeek), valamint a hónapok/hét napjainak neveit (a DateFormatteren keresztüli konverziónál). A Calendar.locale alapértelmezés szerint egyenlő a Locale.current-tel. Magyar lokálban a hét hétfőn kezdődik, az amerikaiban — vasárnap.
Calendar.availableIdentifiers visszaadja az összes támogatott naptári azonosító listáját. static property Calendar.availableCalendarIdentifiers — sztringek tömbje ugyanezekkel az azonosítókkal. Használják naptárválasztó UI felépítéséhez és egy adott naptárrendszer elérhetőségének ellenőrzéséhez az eszközön.
// Naptár meghatározott időzónával
var utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!
// Naptár orosz lokállal
var russianCalendar = Calendar(identifier: .gregorian)
russianCalendar.locale = Locale(identifier: "ru_RU")
// A hét első napja a lokáltól függ
let firstWeekday = russianCalendar.firstWeekday
// 2 = hétfő (hu_HU-ban)
// Elérhető naptárak listája
for identifier in Calendar.availableIdentifiers {
print(identifier)
}
firstWeekday — a Calendar tulajdonsága, amely meghatározza, hogy a hét melyik napja számít elsőnek. Magyar lokálban Sunday = 2 (hétfő az első). Amerikai lokálban Sunday = 1. Ez befolyásolja a weekOfMonth és weekOfYear működését: ugyanaz a dátum különböző lokálokban különböző hét számokhoz rendelődhet. Dátumokkal dolgozó alkalmazásokhoz használja a Calendar.current-et, vagy állítsa be explicit módon a firstWeekday-t.
Tekintsük át a Calendar képességeit bemutató gyakorlati forgatókönyveket. Minden példa egy konkrét iOS-fejlesztési feladatot old meg, és megmutatja a naptári számítások helyes használatát.
Calendar.dateInterval(of: .month, for:) visszaadja az aktuális hónap határait. Annak ellenőrzése, hogy a Date ebbe az intervallumba esik-e — a leggyorsabb módja annak meghatározására, hogy a dátum az aktuális hónapba tartozik-e. Alternatív mód — Calendar.compare .month granularity-val: ha az eredmény .orderedSame, akkor a hónap egyezik.
func isInCurrentMonth(_ date: Date) -> Bool {
let calendar = Calendar.current
let monthInterval = calendar.dateInterval(
of: .month, for: Date()
)!
return monthInterval.contains(date)
}
// Napok száma egy hónapban
func daysInMonth(for date: Date) -> Int {
let calendar = Calendar.current
return calendar.range(
of: .day, in: .month, for: date
)?.count ?? 0
}
// Hónapok hozzáadása helyes befejezéssel
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:) visszaadja a megengedett értékek tartományát a megadott összetevőhöz egy másik összetevő kontextusában. Például a range(of: .day, in: .month, for: date) 1..<32-t ad vissza a 31 napos hónapokra vagy 1..<29-t a nem szökőév februárjára. Ez a helyes módja a hónap napjai számának megtudására, nem a hardcode-olt értékek használata.
Hónapok hozzáadása a Calendar.date(byAdding:value:to:) segítségével helyesen kezeli a határdátumokat. Ha január 31-hez hozzáadunk 1 hónapot, a Calendar február 28-át ad vissza (vagy 29-ét szökőévben), nem március 3-át, mint ahogy a 30 nap TimeInterval-on keresztüli egyszerű hozzáadásával történne. Ez egy újabb ok arra, hogy ne használjunk TimeInterval-t naptári számításokhoz.
| Calendar metódus | Cél | Példa |
|---|---|---|
| dateInterval | Időszak határai | Hónap kezdete és vége |
| range(of:in:for:) | Összetevő tartománya | Napok az aktuális hónapban |
| date(byAdding:) | Dátum eltolása | +1 hónap mától |
| isDateInToday | Ellenőrzés, hogy ma van-e | A dátum ma van? |
| compare(toGranularity:) | Összehasonlítás pontossággal | Ugyanaz a nap idő nélkül |
Gyakran Ismételt Kérdések
Calendar.current a felhasználó rendszerbeállításaiból adja vissza a naptárt — lehet, hogy nem Gergely-naptár (például Buddha-naptár Thaiföldön). Calendar(identifier: .gregorian) mindig Gergely-naptárt hoz létre a beállításoktól függetlenül. Dátumok megjelenítéséhez használja a Calendar.current-et, üzleti logikához — az expliciten kiválasztott azonosítót.
Ez a hónapok eltérő hosszával kapcsolatos. Ha az aktuális dátum január 31., 1 hónap hozzáadása február 28-át ad, mert februárban nincs 31 nap. A Calendar automatikusan kiegészíti a dátumot a hónap utolsó megengedett napjáig. Pontos vezérléshez használja a DateComponents-t day: 1 paraméterrel a hónap első napjára lépéshez.
DateFormatter a Calendar.current-et használja — a felhasználó rendszernaptárát. Ha az alkalmazásnak a beállításoktól függetlenül mindig a Gergely-naptárban kell megjelenítenie a dátumokat, állítsa be a formatter.calendar = Calendar(identifier: .gregorian) értéket. Ez egységes megjelenítést garantál minden felhasználó számára.
Calendar.range(of: .day, in: .year, for: date) 365 vagy 366 napot ad vissza. Egyszerűbben: Calendar.date(from: DateComponents(year: év, month: 2, day: 29)) != nil — ha február 29. létezik, az év szökőév. A Calendar maga veszi figyelembe az adott naptárrendszer szabályait.
Igen, a firstWeekday tulajdonság írható. A változtatás befolyásolja a weekOfMonth-ot, a weekOfYear-t és minden, a hét számokkal kapcsolatos számítást. A locale = Locale(identifier: "hu_HU") beállításakor a firstWeekday automatikusan 2 lesz (hétfő). A kézi beállítás felülírja a locale-ból származó értéket.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is