Calendar — vad är det, Date-kalender och beräkningar i Swift

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

Calendar — är en Foundation-klass som definierar kalendersystemet och tillhandahåller metoder för kalenderberäkningar: extrahering av datumkomponenter, beräkning av skillnad mellan datum, sökning efter periodsgränser och förskjutning av datum. Kalendern kopplar absolut tid (Date) till mänskligt läsbara komponenter och tar hänsyn till regionala särdrag: veckans början, tidszon och sommartid. Enligt Apple Developer Documentation (2025) stödjer Foundation 17 kalendersystem — från gregorianska till buddhistiska och japanska, vilket gör Calendar till ett universellt verktyg för internationaliserade applikationer.

Huvudpunkter

  • Calendar — Foundation-klass för kalenderberäkningar: extrahering av komponenter, jämförelse och förskjutning av datum.
  • Calendar.current — användarens systemkalender som automatiskt tar hänsyn till regionala inställningar.
  • 17 kalendersystem — Foundation stödjer gregorianska, buddhistiska, japanska, hebreiska, islamiska och andra.
  • Calendar.dateComponents extraherar komponenter (år, månad, dag) från Date med hänsyn till tidszon.
  • Calendar.dateInterval returnerar start- och slutdatum för en angiven period (dag, vecka, månad).

Vad är Calendar i Foundation?

Calendar — är en Foundation-klass som implementerar kalenderberäkningar baserade på ICU (International Components for Unicode). Kalendern bestämmer hur absolut tid (Date) mappas till kalenderkomponenter: år, månad, dag, timme, minut, sekund. Utan Calendar är det omöjligt att veta vilket år, månad och dag det är — Date i sig innehåller inte denna information.

Kalendern tar hänsyn till tre grupper av parametrar: kalendersystem (gregorianskt, buddhistiskt, japanskt), tidszon och locale. Calendar.current kombinerar alla tre från användarens systeminställningar. Calendar.autoupdatingCurrent — en speciell version som automatiskt uppdateras vid ändring av inställningar utan omstart av applikationen via NotificationCenter.

Kalendern är en värdetyp (value type) i Foundation. Calendar(identifier:) skapar en ny instans med fasta parametrar. Kalendern kan kopieras, jämföras med == och användas som nyckel i en ordbok. Detta gör det möjligt att skapa kalendrar med specifika timeZone- och locale-inställningar för testning.

Calendar och NSCalendar

Calendar — Swift-versionen av Objective-C NSCalendar, med bryggan as Calendar / as NSCalendar. I modern Swift används Calendar överallt. NSCalendar finns kvar för bakåtkompatibilitet med Objective-C API. Calendar har en fullständig uppsättning metoder utan NS-prefix, med type-safe argument och Swift-optionalitet.

Thread Safety — Calendar är trådsäker för läsning. En skapad instans kan säkert läsas från flera trådar. Ändring av egenskaper (timeZone, locale) är inte trådsäker — för olika konfigurationer, skapa separata Calendar-instanser.

Typer av kalendrar i Foundation

Foundation stödjer 17 kalendersystem genom uppräkningen Calendar.Identifier. Varje system har sina egna regler för skottår, antal månader och början av era. Valet av kalender påverkar alla beräkningar: dateComponents, dateInterval, nextDate.

Huvudsakliga kalendersystem:

  • .gregorian — internationell standard, 12 månader, 365/366 dagar, kristen era.
  • .buddhist — buddhistisk kalender, används i Thailand, Kambodja, Laos, eran är 543 år före den gregorianska.
  • .japanese — japansk kalender efter kejsarnas regeringsperioder, 12 månader som i gregorianska.
  • .hebrew — hebreisk kalender, 12/13 månader, skottmånad Adar II.
  • .islamic — islamisk kalender, 12 månmånader, 354/355 dagar.
  • .indian — indisk nationell kalender (Saka), 12 månader.

Calendar(identifier: .gregorian) — mest använd. Den överensstämmer med internationell standard ISO 8601 och är standardkalender i de flesta länder. För applikationer med internationell publik, använd Calendar.current — den matchar automatiskt användarens systemkalender.

IdentifierareTypAnvändningsregion
.gregorianSolInternationell
.buddhistSolThailand, Kambodja
.japaneseSolJapan
.hebrewMån-solIsrael
.islamicMånIslamiska länder
.chineseMån-solKina

Calendar och DateComponents

DateComponents och Calendar — ett oskiljaktigt par. Calendar.dateComponents(_:from:) extraherar komponenter från Date med hänsyn till kalenderns tidszon. Calendar.date(from:) bygger Date från DateComponents och fyller i saknade fält med standardvärden: dag = 1, timme = 0, minut = 0, sekund = 0.

Metoden Calendar.component extraherar en komponent, vilket är praktiskt för snabb kontroll. Calendar.dateComponents extraherar en uppsättning komponenter i ett anrop — detta är effektivare eftersom Calendar utför kalenderberäkningarna en gång, inte för varje komponent separat. För en lista med 3+ komponenter, använd alltid dateComponents.

Calendar.compare jämför två Date med angiven precision. Parametern toGranularity bestämmer till vilken komponent jämförelsen utförs: .year jämför endast året, .month — år och månad, .day — år, månad, dag. Detta är praktiskt för att kontrollera om två datum tillhör samma dag, utan hänsyn till tid.

swift
let calendar = Calendar.current
let now = Date()

// Extrahering av en komponent
let year = calendar.component(.year, from: now)

// Extrahering av en uppsättning komponenter
let comps = calendar.dateComponents(
    [.year, .month, .day], from: now
)

// Jämförelse med dagprecision
let isSameDay = calendar.compare(date1, to: date2,
                                  toGranularity: .day) == .orderedSame

// Kontrollera om datumet är idag
let isToday = calendar.isDateInToday(someDate)

Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday — metoder för relativa kontroller. Calendar.isDate(_:inSameDayAs:) kontrollerar om två datum infaller på samma kalenderdag med hänsyn till kalenderns tidszon. Dessa metoder använder Calendar.compare internt och är optimerade för frekventa anrop.

Calendar-beräkningar

Calendar.dateInterval — en av de mest användbara metoderna för analys och UI. Den returnerar DateInterval för den angivna komponenten: början och slut av dag, vecka, månad, år. DateInterval innehåller start (Date) och end (Date) — periodens gränser. Till exempel returnerar dateInterval(of: .weekOfYear, for: Date()) början av måndag och slutet av söndag för nuvarande vecka.

Calendar.date med byAdding — metod för att förskjuta datum. Calendar.date(byAdding: .day, value: 7, to: Date()) returnerar datum om en vecka. Calendar.date(byAdding: DateComponents) — en mer flexibel version som tillåter förskjutning av flera komponenter samtidigt: +1 månad +3 dagar. Calendar tar automatiskt hänsyn till olika månadslängder och skottår.

Calendar.nextDate söker efter nästa datum som matchar angivna DateComponents. Parametern matchingPolicy bestämmer beteende vid icke-matchning: .nextTime — nästa matchning i tid, .nextTimePreservingSmallerComponents — behåller minuter och sekunder från originaldatumet, .strict — kräver exakt matchning.

swift
let calendar = Calendar.current
let today = Date()

// Början och slut av vecka
let weekInterval = calendar.dateInterval(
    of: .weekOfYear, for: today
)!

// Förskjutning med 1 månad
let nextMonth = calendar.date(
    byAdding: .month, value: 1, to: today
)!

// Förskjutning via DateComponents
var delta = DateComponents()
delta.month = 1
delta.day = 3
let shifted = calendar.date(byAdding: delta, to: today)!

// Nästa fredag den 13:e
let friday13Components = DateComponents(
    weekday: 6, day: 13
)
let nextFriday13 = calendar.nextDate(
    after: today, matching: friday13Components,
    matchingPolicy: .nextTime
)

EnumerateDates — en kraftfull metod för att iterera datum efter mönster. Calendar.enumerateDates(startingAfter:matching:matchingPolicy:using:) anropar ett block för varje matchning tills blocket returnerar stop = true. Används för att generera återkommande händelser i kalendrar och scheman. Metoden är effektivare än en manuell loop med nextDate eftersom den är optimerad av ICU.

TimeZone och Locale

TimeZone — en oskiljaktig del av Calendar. Tidszonen bestämmer vilken kalendertid som motsvarar det absoluta Date. Samma Date i UTC och i Moskva ger olika komponenter: Date() i UTC kan visa 10:00, och i MSK — 13:00. Calendar.timeZone är som standard lika med TimeZone.current.

Locale påverkar veckans första dag, minsta antal dagar i årets första vecka (minDaysInFirstWeek) och namn på månader/veckodagar (vid konvertering via DateFormatter). Calendar.locale är som standard lika med Locale.current. I svensk locale börjar veckan på måndag, i amerikansk — på söndag.

Calendar.availableIdentifiers returnerar en lista över alla stödda kalenderidentifierare. static property Calendar.availableCalendarIdentifiers — en array av strängar med samma identifierare. Används för att bygga UI för kalenderval och för att kontrollera tillgängligheten av ett specifikt kalendersystem på enheten.

swift
// Kalender med specifik tidszon
var utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!

// Kalender med rysk locale
var russianCalendar = Calendar(identifier: .gregorian)
russianCalendar.locale = Locale(identifier: "ru_RU")

// Första veckodagen beror på locale
let firstWeekday = russianCalendar.firstWeekday
// 2 = måndag (i sv_SE)

// Lista över tillgängliga kalendrar
for identifier in Calendar.availableIdentifiers {
    print(identifier)
}

firstWeekday — Calendar-egenskapen som bestämmer vilken veckodag som anses vara första. I svensk locale är Sunday = 2 (måndag första). I amerikansk är Sunday = 1. Detta påverkar funktionen av weekOfMonth och weekOfYear: samma datum kan tilldelas olika veckonummer i olika locales. För applikationer med datum, använd Calendar.current eller ställ in firstWeekday explicit.

Exempel på arbete med Calendar

Låt oss titta på praktiska scenarier som demonstrerar Calendar:s möjligheter. Varje exempel löser en specifik iOS-utvecklingsuppgift och visar rätt sätt att använda kalenderberäkningar.

Kontroll: är datumet i denna månad?

Calendar.dateInterval(of: .month, for:) returnerar gränserna för nuvarande månad. Att kontrollera om Date faller inom detta intervall — det snabbaste sättet att avgöra om datumet tillhör den nuvarande månaden. Alternativt sätt — Calendar.compare med granularity .month: om resultatet är .orderedSame, stämmer månaden.

swift
func isInCurrentMonth(_ date: Date) -> Bool {
    let calendar = Calendar.current
    let monthInterval = calendar.dateInterval(
        of: .month, for: Date()
    )!
    return monthInterval.contains(date)
}

// Antal dagar i en månad
func daysInMonth(for date: Date) -> Int {
    let calendar = Calendar.current
    return calendar.range(
        of: .day, in: .month, for: date
    )?.count ?? 0
}

// Lägga till månader med korrekt slutförande
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:) returnerar intervallet av tillåtna värden för den angivna komponenten i kontexten av en annan komponent. Till exempel returnerar range(of: .day, in: .month, for: date) 1..<32 för månader med 31 dagar eller 1..<29 för februari i ett icke-skottår. Detta är rätt sätt att ta reda på antalet dagar i en månad, inte att använda hårdkodade värden.

Lägga till månader via Calendar.date(byAdding:value:to:) hanterar gränsdatum korrekt. Om 31 januari läggs 1 månad till, returnerar Calendar 28 februari (eller 29 under skottår), inte 3 mars, som skulle bli fallet vid enkel tilläggning av 30 dagar via TimeInterval. Detta är ytterligare en anledning att inte använda TimeInterval för kalenderberäkningar.

Calendar-metodSyfteExempel
dateIntervalPeriodgränserBörjan och slut av månad
range(of:in:for:)KomponentintervallDagar i nuvarande månad
date(byAdding:)Förskjutning av datum+1 månad från idag
isDateInTodayKontroll om idagÄr datumet idag?
compare(toGranularity:)Jämförelse med precisionSamma dag utan tid

Vanliga frågor

Vad är skillnaden mellan Calendar.current och Calendar(identifier: .gregorian)?

Calendar.current returnerar kalendern från användarens systeminställningar — den kan vara icke-gregoriansk (till exempel buddhistisk i Thailand). Calendar(identifier: .gregorian) skapar alltid en gregoriansk kalender oavsett inställningar. För visning av datum, använd Calendar.current, för affärslogik — den explicit valda identifieraren.

Varför returnerar Calendar.date(byAdding: .month, value: 1) ibland samma datum?

Detta beror på olika månadslängder. Om aktuellt datum är 31 januari, ger tillägg av 1 månad 28 februari, eftersom februari inte har 31 dagar. Calendar slutför automatiskt datumet till den sista tillåtna dagen i månaden. För exakt kontroll, använd DateComponents med day: 1 för att gå till första dagen i månaden.

Vilken kalender använder DateFormatter som standard?

DateFormatter använder Calendar.current — användarens systemkalender. Om applikationen alltid ska visa datum i den gregorianska kalendern oavsett inställningar, ställ in formatter.calendar = Calendar(identifier: .gregorian). Detta garanterar enhetlig visning för alla användare.

Hur kontrollerar jag via Calendar om ett år är skottår?

Calendar.range(of: .day, in: .year, for: date) returnerar 365 eller 366 dagar. Enklare: Calendar.date(from: DateComponents(year: år, month: 2, day: 29)) != nil — om 29 februari finns, är året skottår. Calendar tar själv hänsyn till reglerna för det specifika kalendersystemet.

Kan firstWeekday ändras efter skapandet av Calendar?

Ja, egenskapen firstWeekday är skrivbar. Ändringen påverkar weekOfMonth, weekOfYear och alla beräkningar relaterade till veckonummer. Vid inställning av locale = Locale(identifier: "sv_SE") blir firstWeekday automatiskt 2 (måndag). Manuell inställning åsidosätter värdet från locale.

Sammanfattning

  • Calendar — Foundation-klass för kalenderberäkningar som kopplar Date till mänskligt läsbara komponenter via DateComponents.
  • 17 kalendersystem stöds av Foundation — från gregorianska till buddhistiska och japanska, med automatisk hänsyn till regionala regler.
  • Calendar.current motsvarar användarens systemkalender — använd den för UI och DateFormatter.
  • Calendar.dateInterval och Calendar.range — nyckelmetoder för arbete med periodsgränser och komponentintervall.
  • Calendar.date(byAdding:) hanterar korrekt olika månadslängder och skottår — ersätt den inte med TimeInterval-aritmetik.
  • TimeZone och Locale som egenskaper hos Calendar påverkar alla kalenderberäkningar — ställ in dem explicit för förutsägbart beteende.
  • firstWeekday bestäms av locale och påverkar veckonummer — för globala applikationer, ställ in den explicit eller använd Calendar.current.

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å