DateComponents egy Foundation struktúra, amely a naptári dátum komponenseit külön mezőkként tárolja: év, hónap, nap, óra, perc, másodperc és mások. Ellentétben a Date-tel, amely egy abszolút időpillanatot képvisel, a DateComponents ember által olvasható értékeket tartalmaz, amelyek a naptártól és időzónától függenek. Az Apple Developer Documentation (2025) szerint a DateComponents közvetítő kapocsként szolgál a Date és a Calendar között – rajta keresztül történik a naptári dátumok kinyerése és létrehozása, számítások és dátumeltolások végrehajtása kézi aritmetika nélkül.
Főbb pontok
DateComponents egy Foundation értéktípus, amely az idő naptári komponenseinek tárolására szolgál. Minden komponens egy opcionális Int mezőként van ábrázolva: year, month, day, hour, minute, second, nanosecond, weekday, weekOfMonth, weekOfYear, quarter, yearForWeekOfYear és mások.
A fő különbség a Date-hez képest a naptárhoz való kötődés. A Date abszolút időt tárol (másodpercek száma a referencia dátumtól), míg a DateComponents egy ember által olvasható reprezentáció, amelynek csak egy adott Calendar kontextusában van értelme. Ugyanaz a Date különböző DateComponents-ként jelenhet meg különböző naptárakban és időzónákban.
A DateComponents nem önálló időtípus, hanem adattároló. A DateComponents dátumként való értelmezéséhez Calendar szükséges, amely megérti, hogy a komponensek hogyan viszonyulnak a naptári rendszerhez. A Calendar.dateComponents(from: Date) végzi a komponensek kinyerését, a Calendar.date(from: DateComponents) – a fordított összeállítást.
A DateComponents minden mezője opcionális (Int?), ami alapvető fontosságú a hiányos dátumokkal való munkához. Ha csak az évet és a hónapot adja meg, a Calendar a hiányzó mezőket alapértelmezett értékekkel egészíti ki: nap = 1, óra = 0, perc = 0. Ez kényelmes az időszak kezdetének dátumának létrehozásához – csak a releváns komponenseket kell megadni.
A DateComponents == operátorral történő összehasonlításakor csak a megadott (nem nil) mezők kerülnek összehasonlításra. Két DateComponents struktúra 2026-os évvel, de különböző hónapokkal, különbözőnek minősül. Az NSObjectProtocol-ből származó isEqual nem alkalmazható a DateComponents-re – a DateComponents nem örökli az NSObject-et.
Alapmezők a DateComponents-ben: year, month, day, hour, minute, second, nanosecond. Minden mező numerikus értéket tárol a megfelelő egységben: év – 2026, hónap – 1..12, nap – 1..31, óra – 0..23, perc – 0..59, másodperc – 0..59. A nanomásodpercek 0..999999999 értékeket vehetnek fel.
Hét mezői – weekday (1..7, ahol 1 = vasárnap a Gergely-naptárban), weekOfMonth, weekOfYear. Ezek a mezők a Calendar-tól függenek, és azon kívül nincs értelmük. A weekday a naptár firstWeekday beállításától függ: a magyar lokalizációban a hét hétfőn kezdődik (weekday = 2 a Gergely-rendszerben), az amerikában pedig – vasárnap (weekday = 1).
Speciális mezők – quarter (1..4), yearForWeekOfYear (az év, amelyhez a hét tartozik), isLeapMonth (logikai jelző a szökőhónapokhoz a héber vagy kínai naptárban). A calendar és timeZone mezők a megfelelő objektumokra mutató hivatkozásokat tárolják, amelyekkel a struktúra létrejött.
| Kategória | Mezők | Tartomány |
|---|---|---|
| Naptári | year, month, day | 1..∞, 1..12, 1..31 |
| Időbeli | hour, minute, second, nanosecond | 0..23, 0..59, 0..59, 0..999999999 |
| Heti | weekday, weekOfMonth, weekOfYear | 1..7, 1..5, 1..53 |
| Speciális | quarter, yearForWeekOfYear | 1..4, függő |
A komponensek Calendar.dateComponents segítségével történő kinyerésekor fontos, hogy a teljesítmény érdekében csak a szükséges mezőket kérje le. A Calendar az összes kért mezőt egyetlen menetben nyeri ki – ez jelentősen gyorsabb, mint a Calendar.component külön-külön történő meghívása minden mezőre.
A DateComponents inicializálása – a legegyszerűbb mód: létrehoz egy üres struktúrát és kitölti a szükséges mezőket. Az összes meg nem adott mező automatikusan nil értéket kap. A részleges komponensekből létrehozott dátum nem kerül érvényesítésre az inicializálás szakaszában – hiba csak a Calendar-on keresztüli Date-té konvertáláskor merülhet fel.
A DateComponents(calendar:timeZone:era:year:month:day:hour:minute:second:nanosecond:weekday:…) inicializátor lehetővé teszi az összes mező egyetlen hívásban történő beállítását. Ez az inicializátor kényelmes a teljes dátum létrehozásához kész értékekből, de az olvashatóság miatt ritkán használják 5-6 argumentumnál többel.
Calendar.dateComponents(_:from:) – a DateComponents megszerzésének elsődleges módja egy meglévő Date-ből. A második argumentum a kinyerendő komponensek halmaza. A Calendar naptári számításokat végez az időzóna figyelembevételével, és csak a kért mezőkkel rendelkező struktúrát ad vissza, a többi mező nil marad.
import Foundation
// Létrehozás mezőinicializátoron keresztül
var components = DateComponents()
components.year = 2026
components.month = 7
components.day = 21
// Kinyerés Date-ből
let now = Date()
let extracted = Calendar.current.dateComponents(
[.year, .month, .day],
from: now
)
print("Today: \(extracted.day!).\(extracted.month!).\(extracted.year!)")
// Létrehozás kiterjesztett inicializátoron keresztül
let birthday = DateComponents(
calendar: Calendar.current,
year: 1990, month: 5, day: 15
)
A DateComponents kézi mezőkön keresztüli létrehozásakor mindig ellenőrizze a Calendar-t a Date-té konvertálás előtt. A Calendar a date(from:) konvertáláskor nil-t adhat vissza, ha a komponensek egy nem létező dátumot alkotnak – például február 31-ét vagy február 30-át nem szökőévben. A dátum érvényesítése a Calendar felelőssége, nem a DateComponents-é.
Calendar.date(from:) – a DateComponents Date-té konvertálásának elsődleges metódusa. A Calendar a komponenseket a saját naptárának és időzónájának megfelelően értelmezi. Ha egyes mezők nincsenek beállítva (nil), a Calendar alapértelmezett értékeket használ: nap = 1, óra = 0, perc = 0, másodperc = 0.
A metódus egy opcionális Date-et ad vissza – nil akkor fordul elő, ha a komponensek ellentmondanak egymásnak vagy érvénytelen dátumot alkotnak. A nil tipikus okai: nem létező dátum (január 32., 2023. február 29.), ellentmondásos mezők (weekday=1, day=5 ugyanabban a halmazban), lehetetlen év az adott naptárhoz (0. év a Gergely-naptárban).
DateComponents timeZone-nal – ha a DateComponents tartalmazza a timeZone-t, a Calendar azt használja a konvertáláskor. Ha a timeZone nincs megadva, a Calendar a saját aktuális timeZone-ját használja. Ha a Calendar.timeZone nem egyezik meg a dátum várt időzónájával, az eredmény több órával is eltérhet – győződjön meg arról, hogy a timeZone explicit módon be van állítva az egyik objektumban.
let calendar = Calendar(identifier: .gregorian)
// Date létrehozása DateComponents-ből
var comps = DateComponents()
comps.year = 2026
comps.month = 12
comps.day = 25
comps.hour = 10
if let date = calendar.date(from: comps) {
print("Christmas: \(date)")
}
// Létrehozás timeZone megadásával
calendar.timeZone = TimeZone(identifier: "UTC")!
let utcComps = DateComponents(
calendar: calendar, year: 2026, month: 7, day: 21,
hour: 12
)
let utcDate = calendar.date(from: utcComps)!
Calendar.dateComponents dátumkülönbséghez – a DateComponents használatának egy másik forgatókönyve. A Calendar.dateComponents([.year, .month, .day], from: Date(), to: futureDate) a két dátum közötti különbséget években, hónapokban és napokban adja vissza. Ez a helyes módja az életkor kiszámításának a TimeInterval elosztása helyett az év másodperceinek számával, mivel a Calendar figyelembe veszi a szökőéveket.
Calendar – a központi osztály, amely a DateComponents-szel dolgozik. A dátumok kinyerésének, összeállításának és összehasonlításának minden művelete a Calendar-on keresztül történik. Calendar nélkül a DateComponents csak számok halmaza időbeli jelentés nélkül. A Calendar értelmezi a komponenseket: meghatározza, hogy a 2. hónap február, a weekday 2 pedig hétfő.
Calendar.nextDate és Calendar.enumerateDates – két DateComponents-en alapuló metódus. A nextDate(after: Date(), matching: DateComponents) megkeresi a megadott komponenseknek megfelelő következő dátumot – például a mai nap utáni következő hétfőt. Az enumerateDates(startingAfter:matching:matchingPolicy:using:) végigiterál az összes, a mintának megfelelő dátumon a megadott határig.
Calendar.dateInterval – egy metódus, amely DateInterval-et ad vissza a megadott komponenshez. A dateInterval(of: .month, for: Date()) visszaadja az aktuális hónap kezdetét és végét. Belsőleg ez a metódus DateComponents-t használ az időszak határainak megtalálásához: létrehozza a DateComponents-t a hónap első és utolsó napjával, majd Calendar-on keresztül Date-té konvertálja azokat.
let calendar = Calendar.current
// Következő hétfő
let nextMonday = calendar.nextDate(
after: Date(),
matching: DateComponents(weekday: 2),
matchingPolicy: .nextTime
)!
// Dátumok közötti különbség napokban
let diff = calendar.dateComponents(
[.day], from: Date(), to: nextMonday
)
// Hónap tartománya
let monthInterval = calendar.dateInterval(
of: .month, for: Date()
)!
let startOfMonth = monthInterval.start
let endOfMonth = monthInterval.end
MatchingPolicy – a Calendar metódusainak fontos paramétere a DateComponents-szel való munka során. A strictPolicy az összes komponens pontos egyezését követeli meg, a nextTimePolicy a következő időbeli egyezést választja, a nextTimePreservingSmallerComponents megtartja a kisebb komponenseket (perceket, másodperceket) az eredeti dátumból. A szabályzat megválasztása befolyásolja a dátumkeresés eredményét, különösen a nyári/téli időszámításra való átálláskor.
Megvizsgáljuk a DateComponents gyakorlati használati forgatókönyveit egy alkalmazásban. Minden példa egy tipikus feladatot mutat be, amellyel egy iOS-fejlesztő találkozik a naptári dátumokkal való munka során.
A Calendar.nextDate a DateComponents(day: 1) paraméterrel megkeresi a következő hónap első napját. A Calendar automatikusan meghatározza az aktuális hónap napjainak számát, és továbblép a következő hónapra. Ismétlődő értesítésekhez használja az enumerateDates vagy a Combine.Timer metódust Calendar kulccsal.
func firstDayOfNextMonth(from date: Date) -> Date {
let calendar = Calendar.current
let comps = DateComponents(day: 1)
return calendar.nextDate(
after: date,
matching: comps,
matchingPolicy: .nextTime
)!
}
// Életkor kiszámítása években
func ageInYears(from birthDate: Date) -> Int {
let calendar = Calendar.current
let ageComponents = calendar.dateComponents(
[.year], from: birthDate, to: Date()
)
return ageComponents.year ?? 0
}
// Események csoportosítása év és hónap szerint
func groupEventsByMonth(_ events: [Event]) -> [String: [Event]] {
let calendar = Calendar.current
return Dictionary(grouping: events) { event in
let comps = calendar.dateComponents(
[.year, .month], from: event.date
)
return "\(comps.year!)-\(comps.month!)"
}
}
Életkor kiszámítása a Calendar.dateComponents([.year], from:to:) segítségével – az egyetlen helyes mód, amely figyelembe veszi a szökőéveket. A TimeInterval-alapú számítás (másodpercek / 31536000) hibát ad a február 29-én született személyek esetében. A Calendar helyesen határozza meg, hogy a születésnap az aktuális évben volt-e, és pontos életkort ad vissza.
Csoportosítás év és hónap szerint – gyakori feladat az előzményeket vagy naptárt megjelenítő képernyőkön. A DateComponents csoportosítási kulcsként szolgál: kinyeri az év és a hónap értékét az esemény dátumából, létrehoz egy string kulcsot, és a Dictionary(grouping:) segítségével csoportosít. A megjelenítéshez használja a DateFormatter-t a „LLLL yyyy” sablonnal a lokalizált hónapnévhez.
| Feladat | Calendar metódus | DateComponents szerepe |
|---|---|---|
| Hónap első napja | nextDate(after:matching:) | day: 1 |
| Életkor kiszámítása | dateComponents(from:to:) | [.year] a különbségből |
| Dátumok csoportosítása | dateComponents(_:from:) | year + month kulcs |
| Hét napjának keresése | nextDate(after:matching:) | weekday: N |
Gyakran ismételt kérdések
Okok: nem létező dátum (április 31.), ellentmondásos mezők (weekday=1 a day=5-tel), érvénytelen mezőkombináció a kiválasztott naptárhoz. A Calendar megpróbálja értelmezni a komponenseket a saját rendszerében – ha a kombináció lehetetlen, az eredmény nil. Mindig használjon guard let vagy if let utasítást a konvertáláskor.
Igen, a == operátoron keresztül. A DateComponents megvalósítja az Equatable protokollt, összehasonlítva az összes mezőt. Két struktúra egyenlő, ha minden mezőjük egyenlő (a nil == nil igaznak minősül). Csak a mezők egy részének összehasonlításához – nyerje ki ugyanazt a halmazt a Calendar.dateComponents segítségével.
Date – egy abszolút időpillanat a naptártól függetlenül. DateComponents – ember által olvasható számok halmaza (év, hónap, nap), amelyeknek csak a Calendar kontextusában van értelme. A Date összehasonlítható, kivonható, ISO 8601 formátumba szerializálható. A DateComponents – egy köztes reprezentáció a naptárral való interakcióhoz.
Csak a year és month mezőket állítsa be, a többit hagyja nil-ként. A Calendar.date(from:) segítségével történő Date-té konvertáláskor a Calendar automatikusan beállítja a nap = 1, óra = 0, perc = 0 értékeket. Az eredmény – egy Date, amely a megadott hónap első napjának éjfélnek felel meg.
A DateComponents nem tárol információt az időzónáról a mezőkben – a mezők értékei (év, hónap, nap) maguk függenek attól a timeZone-tól, amelyben kinyerésre kerültek. A „2026. július 21. 14:00 MSK” és „2026. július 21. 10:00 UTC” komponensek ugyanazt a Date-et képviselik, de a DateComponents mezői különböznek.
Ö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