DateComponents – vad är det, kalenderkomponenter och NSCalendar

Författare: IT Sectr Publicerad: 2026-07-12 Lästid: 7 min

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 – struktur för lagring av datumkomponenter (år, månad, dag) som valfria heltalsfält.
  • Calendar.dateComponents – metod som extraherar angivna komponenter från Date med hänsyn till tidszon.
  • Calendar.date(from:) – omvänd konvertering av DateComponents till Date med automatisk ifyllning av saknade fält.
  • Valfria fält – varje fält i DateComponents kan vara nil, vilket möjliggör angivelse av ofullständiga datum.
  • Range och komponenter – DateComponents används i Calendar för att beräkna skillnaden mellan datum och hitta datum inom ett intervall.

Vad är DateComponents?

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.

Fältens valfrihet

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.

Datumkomponenter: år, månad, dag

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.

KategoriFältIntervall
Kalenderyear, month, day1..∞, 1..12, 1..31
Tidhour, minute, second, nanosecond0..23, 0..59, 0..59, 0..999999999
Veckovisweekday, weekOfMonth, weekOfYear1..7, 1..5, 1..53
Speciellaquarter, yearForWeekOfYear1..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.

Skapa DateComponents

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.

swift
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.

Konvertera DateComponents till Date

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.

swift
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 och DateComponents

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.

swift
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.

DateComponents exempel

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.

Påminnelse för första dagen varje månad

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.

swift
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.

UppgiftCalendar-metodDateComponents roll
Första dagen i månadennextDate(after:matching:)day: 1
Beräkna ålderdateComponents(from:to:)[.year] från skillnad
Gruppera datumdateComponents(_:from:)year + month nyckel
Söka efter veckodagnextDate(after:matching:)weekday: N

Vanliga frågor

Varför returnerar Calendar.date(from:) nil för DateComponents?

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.

Kan DateComponents jämföras med varandra?

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.

Vad är skillnaden mellan DateComponents och Date?

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.

Hur anger man endast år och månad i DateComponents?

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.

Hur hanterar DateComponents tidszoner?

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

  • DateComponents – Foundation-struktur för lagring av kalenderkomponenter (år, månad, dag, timme) som valfria Int?-fält.
  • Calendar.dateComponents extraherar komponenter från Date med hänsyn till tidszon och kalendersystem.
  • Calendar.date(from:) sätter ihop Date från DateComponents med standardvärden för saknade fält.
  • Fältens valfrihet möjliggör angivelse av ofullständiga datum – Calendar fyller i saknade värden.
  • Calendar.nextDate söker efter nästa datum som matchar DateComponents – för påminnelser och återkommande händelser.
  • Beräkning av ålder via Calendar.dateComponents([.year], from:to:) – det enda korrekta sättet som tar hänsyn till skottår.
  • MatchingPolicy styr Calendar's beteende när alla komponenter inte matchar – viktig parameter för sökning av datum.

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.

Diskutera projektet

Läs också