DateComponents är en Foundation-struktur som lagrar komponenterna i ett kalenderdatum som separata fält: år, månad, dag, timme, minut, sekund och andra. Till skillnad från Date, som representerar ett absolut ögonblick i tiden, innehåller DateComponents mänskligt läsbara värden som är beroende av kalender och tidszon. Enligt Apple Developer Documentation (2025) används DateComponents som en mellanlänk mellan Date och Calendar – genom den extraheras och konstrueras kalenderdatum, beräkningar och förskjutningar av datum utförs utan manuell aritmetik.
Huvudpunkter
DateComponents är en värdetyp i Foundation avsedd för lagring av kalenderkomponenter för tid. Varje komponent representeras som ett valfritt Int-fält: year, month, day, hour, minute, second, nanosecond, weekday, weekOfMonth, weekOfYear, quarter, yearForWeekOfYear och andra.
Den huvudsakliga skillnaden från Date är kopplingen till kalendern. Date lagrar absolut tid (antal sekunder från referensdatumet), medan DateComponents är en mänskligt läsbar representation som endast har mening i kontexten av en specifik Calendar. Samma Date kan representeras av olika DateComponents i olika kalendrar och tidszoner.
DateComponents är ingen självständig tidstyp, utan en databehållare. För tolkning av DateComponents som datum krävs en Calendar som förstår hur komponenterna förhåller sig till kalendersystemet. Calendar.dateComponents(from: Date) utför extraktion av komponenter, Calendar.date(from: DateComponents) – omvänd sammansättning.
Varje fält i DateComponents är valfritt (Int?), vilket är fundamentalt för arbete med ofullständiga datum. Om du endast anger år och månad kommer Calendar att fylla i de saknade fälten med standardvärden: dag = 1, timme = 0, minut = 0. Detta är praktiskt för att skapa startdatum för en period – du behöver bara ange relevanta komponenter.
Vid jämförelse av DateComponents med operatorn == jämförs endast angivna (icke-nil) fält. Två DateComponents-strukturer med år 2026 men olika månader anses vara olika. isEqual från NSObjectProtocol tillämpas inte för DateComponents – DateComponents ärver inte NSObject.
Grundfält i DateComponents inkluderar year, month, day, hour, minute, second, nanosecond. Varje fält lagrar ett numeriskt värde i motsvarande enhet: år – 2026, månad – 1..12, dag – 1..31, timme – 0..23, minut – 0..59, sekund – 0..59. Nanosekunder kan anta värden 0..999999999.
Veckofält – weekday (1..7, där 1 = söndag i den gregorianska kalendern), weekOfMonth, weekOfYear. Dessa fält är beroende av Calendar och har ingen mening utanför dess kontext. weekday beror på kalenderns firstWeekday-inställning: i svensk locale börjar veckan på måndag (weekday = 2 i det gregorianska systemet), och i amerikansk locale – på söndag (weekday = 1).
Specialiserade fält – quarter (1..4), yearForWeekOfYear (året som veckan tillhör), isLeapMonth (logisk flagga för skottmånader i hebreiska eller kinesiska kalendern). Fälten calendar och timeZone lagrar referenser till motsvarande objekt som strukturen skapades med.
| Kategori | Fält | Intervall |
|---|---|---|
| Kalender | year, month, day | 1..∞, 1..12, 1..31 |
| Tid | hour, minute, second, nanosecond | 0..23, 0..59, 0..59, 0..999999999 |
| Veckovis | weekday, weekOfMonth, weekOfYear | 1..7, 1..5, 1..53 |
| Speciella | quarter, yearForWeekOfYear | 1..4, beroende |
Vid extraktion av komponenter via Calendar.dateComponents är det viktigt att endast begära nödvändiga fält för prestanda. Calendar extraherar alla begärda fält i en enda genomgång – detta är betydligt snabbare än att anropa Calendar.component för varje fält separat.
Initiering av DateComponents – det enklaste sättet: du skapar en tom struktur och fyller i nödvändiga fält. Alla ej angivna fält får automatiskt nil. Ett datum skapat från partiella komponenter valideras inte i initieringsfasen – fel kan endast uppstå vid konvertering till Date via Calendar.
Initieraren DateComponents(calendar:timeZone:era:year:month:day:hour:minute:second:nanosecond:weekday:…) gör det möjligt att ställa in alla fält i ett anrop. Denna initierare är praktisk för att skapa ett fullständigt datum från färdiga värden, men används sällan med mer än 5-6 argument på grund av läsbarhet.
Calendar.dateComponents(_:from:) – det primära sättet att få DateComponents från en befintlig Date. Det andra argumentet är uppsättningen komponenter som ska extraheras. Calendar utför kalenderberäkningar med hänsyn till tidszon och returnerar en struktur endast med de begärda fälten, de övriga fälten förblir nil.
import Foundation
// Skapa via fältinitierare
var components = DateComponents()
components.year = 2026
components.month = 7
components.day = 21
// Extrahera från Date
let now = Date()
let extracted = Calendar.current.dateComponents(
[.year, .month, .day],
from: now
)
print("Today: \(extracted.day!).\(extracted.month!).\(extracted.year!)")
// Skapa via utökad initierare
let birthday = DateComponents(
calendar: Calendar.current,
year: 1990, month: 5, day: 15
)
Vid skapande av DateComponents genom manuella fält, kontrollera alltid Calendar före konvertering till Date. Calendar kan vid konvertering date(from:) returnera nil om komponenterna utgör ett obefintligt datum – till exempel 31 februari eller 30 februari under ett icke-skottår. Validering av datum är Calendar's ansvar, inte DateComponents.
Calendar.date(from:) – den primära metoden för konvertering av DateComponents till Date. Calendar tolkar komponenterna enligt sin kalender och tidszon. Om vissa fält inte är inställda (nil) använder Calendar standardvärden: dag = 1, timme = 0, minut = 0, sekund = 0.
Metoden returnerar en valfri Date – nil uppstår när komponenterna motsäger varandra eller utgör ett ogiltigt datum. Typiska orsaker till nil: obefintligt datum (32 januari, 29 februari 2023), motstridiga fält (weekday=1, day=5 i samma uppsättning), omöjligt år för given kalender (år 0 i den gregorianska kalendern).
DateComponents med timeZone – om DateComponents innehåller timeZone använder Calendar det vid konvertering. Om timeZone inte anges använder Calendar sin egen aktuella timeZone. Om Calendar.timeZone inte överensstämmer med datumets förväntade tidszon kan resultatet skilja sig med flera timmar – se till att timeZone är explicit inställd i ett av objekten.
let calendar = Calendar(identifier: .gregorian)
// Skapa Date från DateComponents
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)")
}
// Skapa med angivelse av timeZone
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 för datumskillnad – ett annat scenario för användning av DateComponents. Calendar.dateComponents([.year, .month, .day], from: Date(), to: futureDate) returnerar skillnaden i år, månader och dagar mellan två datum. Detta är det korrekta sättet att beräkna ålder istället för att dividera TimeInterval med antalet sekunder på ett år, eftersom Calendar tar hänsyn till skottår.
Calendar – den centrala klassen som arbetar med DateComponents. Alla operationer för extraktion, sammansättning och jämförelse av datum går genom Calendar. Utan Calendar är DateComponents bara en samling siffror utan tidsmässig betydelse. Calendar ger komponenterna tolkning: den bestämmer att månad 2 är februari och weekday 2 är måndag.
Calendar.nextDate och Calendar.enumerateDates – två metoder baserade på DateComponents. nextDate(after: Date(), matching: DateComponents) hittar nästa datum som motsvarar de angivna komponenterna – till exempel nästa måndag efter idag. enumerateDates(startingAfter:matching:matchingPolicy:using:) itererar över alla datum som matchar mönstret upp till en angiven gräns.
Calendar.dateInterval – en metod som returnerar DateInterval för den angivna komponenten. dateInterval(of: .month, for: Date()) returnerar början och slutet av den aktuella månaden. Internt använder denna metod DateComponents för att hitta periodens gränser: den skapar DateComponents med första och sista dagen i månaden, konverterar dem till Date via Calendar.
let calendar = Calendar.current
// Nästa måndag
let nextMonday = calendar.nextDate(
after: Date(),
matching: DateComponents(weekday: 2),
matchingPolicy: .nextTime
)!
// Skillnad mellan datum i dagar
let diff = calendar.dateComponents(
[.day], from: Date(), to: nextMonday
)
// Månadens intervall
let monthInterval = calendar.dateInterval(
of: .month, for: Date()
)!
let startOfMonth = monthInterval.start
let endOfMonth = monthInterval.end
MatchingPolicy – en viktig parameter för Calendar-metoder vid arbete med DateComponents. strictPolicy kräver exakt matchning av alla komponenter, nextTimePolicy väljer nästa matchning i tid, nextTimePreservingSmallerComponents bevarar mindre komponenter (minuter, sekunder) från det ursprungliga datumet. Valet av policy påverkar resultatet av sökning efter datum, särskilt vid förskjutning genom övergång till sommar/vintertid.
Vi undersöker praktiska scenarier för användning av DateComponents i en applikation. Varje exempel visar en typisk uppgift som en iOS-utvecklare stöter på vid arbete med kalenderdatum.
Calendar.nextDate med DateComponents(day: 1) hittar första dagen i nästa månad. Calendar bestämmer automatiskt antalet dagar i den aktuella månaden och går vidare till nästa månad. För återkommande aviseringar, använd enumerateDates eller Combine.Timer med Calendar-nyckel.
func firstDayOfNextMonth(from date: Date) -> Date {
let calendar = Calendar.current
let comps = DateComponents(day: 1)
return calendar.nextDate(
after: date,
matching: comps,
matchingPolicy: .nextTime
)!
}
// Beräkna ålder i år
func ageInYears(from birthDate: Date) -> Int {
let calendar = Calendar.current
let ageComponents = calendar.dateComponents(
[.year], from: birthDate, to: Date()
)
return ageComponents.year ?? 0
}
// Gruppera händelser efter år och månad
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!)"
}
}
Beräkning av ålder via Calendar.dateComponents([.year], from:to:) – det enda korrekta sättet som tar hänsyn till skottår. TimeInterval-baserad beräkning (sekunder / 31536000) ger fel för personer födda den 29 februari. Calendar avgör korrekt om födelsedagen var under det aktuella året och returnerar exakt ålder.
Gruppering efter år och månad – en vanlig uppgift för skärmar med historik eller kalender. DateComponents fungerar som grupperingsnyckel: du extraherar år och månad från händelsedatumet, skapar en strängnyckel och grupperar via Dictionary(grouping:). För visning, använd DateFormatter med mallen ”LLLL yyyy” för lokaliserat månadsnamn.
| Uppgift | Calendar-metod | DateComponents roll |
|---|---|---|
| Första dagen i månaden | nextDate(after:matching:) | day: 1 |
| Beräkna ålder | dateComponents(from:to:) | [.year] från skillnad |
| Gruppera datum | dateComponents(_:from:) | year + month nyckel |
| Söka efter veckodag | nextDate(after:matching:) | weekday: N |
Vanliga frågor
Orsaker: obefintligt datum (31 april), motstridiga fält (weekday=1 med day=5), ogiltig fältkombination för vald kalender. Calendar försöker tolka komponenterna i sitt system – om kombinationen är omöjlig är resultatet nil. Använd alltid guard let eller if let vid konvertering.
Ja, via operatorn ==. DateComponents implementerar Equatable och jämför alla fält. Två strukturer är lika om alla deras fält är lika (nil == nil anses sant). För att jämföra endast en del av fälten – extrahera samma uppsättning via Calendar.dateComponents.
Date – ett absolut ögonblick i tiden utan koppling till kalender. DateComponents – en uppsättning mänskligt läsbara tal (år, månad, dag) som endast har mening i kontexten av Calendar. Date kan jämföras, subtraheras, serialiseras till ISO 8601. DateComponents – en mellanliggande representation för interaktion med kalendern.
Ställ endast in fälten year och month, låt resten vara nil. Vid konvertering till Date via Calendar.date(from:) kommer Calendar automatiskt att ställa in dag = 1, timme = 0, minut = 0. Resultatet – en Date som motsvarar första dagen i den angivna månaden vid midnatt.
DateComponents lagrar inte information om tidszon i fälten – fältens värden (år, månad, dag) är själva beroende av i vilken timeZone de extraherades. Komponenterna ”21 juli 2026 14:00 MSK” och ”21 juli 2026 10:00 UTC” representerar samma Date, men DateComponents-fälten är olika.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också