Calendar — is een Foundation-klasse die het kalendersysteem definieert en methoden biedt voor kalenderberekeningen: het extraheren van datumcomponenten, het berekenen van het verschil tussen datums, het vinden van periodegrenzen en het verschuiven van datums. De kalender verbindt absolute tijd (Date) met menselijk leesbare componenten en houdt rekening met regionale kenmerken: begin van de week, tijdzone en zomertijd. Volgens Apple Developer Documentation (2025) ondersteunt Foundation 17 kalendersystemen — van Gregoriaans tot Boeddhistisch en Japans, wat Calendar een universeel hulpmiddel maakt voor geïnternationaliseerde applicaties.
Belangrijkste punten
Calendar — is een Foundation-klasse die kalenderberekeningen implementeert op basis van ICU (International Components for Unicode). De kalender bepaalt hoe absolute tijd (Date) wordt afgebeeld op kalendercomponenten: jaar, maand, dag, uur, minuut, seconde. Zonder Calendar is het onmogelijk te weten welk jaar, maand en dag het is — Date zelf bevat deze informatie niet.
De kalender houdt rekening met drie groepen parameters: kalendersysteem (Gregoriaans, Boeddhistisch, Japans), tijdzone en locale. Calendar.current combineert alle drie uit de systeeminstellingen van de gebruiker. Calendar.autoupdatingCurrent is een speciale versie die automatisch wordt bijgewerkt bij wijziging van instellingen zonder herstart van de applicatie via NotificationCenter.
De kalender is een waardetype (value type) in Foundation. Calendar(identifier:) maakt een nieuwe instantie met vaste parameters. De kalender kan worden gekopieerd, vergeleken met == en gebruikt als sleutel in een woordenboek. Dit maakt het mogelijk kalenders met specifieke timeZone- en locale-instellingen te maken voor testdoeleinden.
Calendar — de Swift-versie van Objective-C NSCalendar, met de brug as Calendar / as NSCalendar. In modern Swift wordt overal Calendar gebruikt. NSCalendar blijft voor achterwaartse compatibiliteit met Objective-C API. Calendar heeft een volledige set methoden zonder NS-voorvoegsel, met type-safe argumenten en Swift-optionaliteit.
Thread Safety — Calendar is thread-safe voor lezen. Een gemaakte instantie kan veilig uit meerdere threads worden gelezen. Wijziging van eigenschappen (timeZone, locale) is niet thread-safe — maak voor verschillende configuraties aparte Calendar-instanties.
Foundation ondersteunt 17 kalendersystemen via de Calendar.Identifier-enum. Elk systeem heeft zijn eigen regels voor schrikkeljaren, aantal maanden en het begin van het tijdperk. De kalenderkeuze beïnvloedt alle berekeningen: dateComponents, dateInterval, nextDate.
Belangrijkste kalendersystemen:
Calendar(identifier: .gregorian) — meest gebruikt. Het voldoet aan de internationale standaard ISO 8601 en is de standaardkalender in de meeste landen. Gebruik voor applicaties met een internationaal publiek Calendar.current — deze komt automatisch overeen met de systeemkalender van de gebruiker.
| Identificatie | Type | Gebruiksregio |
|---|---|---|
| .gregorian | Zonne- | Internationaal |
| .buddhist | Zonne- | Thailand, Cambodja |
| .japanese | Zonne- | Japan |
| .hebrew | Maan-zonne- | Israël |
| .islamic | Maan- | Islamitische landen |
| .chinese | Maan-zonne- | China |
DateComponents en Calendar — een onafscheidelijk paar. Calendar.dateComponents(_:from:) extraheert componenten uit Date met inachtneming van de tijdzone van de kalender. Calendar.date(from:) bouwt Date uit DateComponents, waarbij ontbrekende velden worden ingevuld met standaardwaarden: dag = 1, uur = 0, minuut = 0, seconde = 0.
De methode Calendar.component extraheert één component, wat handig is voor snelle controle. Calendar.dateComponents extraheert een set componenten in één aanroep — dit is efficiënter omdat Calendar de kalenderberekeningen één keer uitvoert, niet voor elke component afzonderlijk. Gebruik voor een lijst van 3+ componenten altijd dateComponents.
Calendar.compare vergelijkt twee Date met opgegeven precisie. De parameter toGranularity bepaalt tot welke component de vergelijking wordt uitgevoerd: .year vergelijkt alleen het jaar, .month — jaar en maand, .day — jaar, maand, dag. Dit is handig om te controleren of twee datums tot dezelfde dag behoren, zonder rekening te houden met de tijd.
let calendar = Calendar.current
let now = Date()
// Extractie van één component
let year = calendar.component(.year, from: now)
// Extractie van een set componenten
let comps = calendar.dateComponents(
[.year, .month, .day], from: now
)
// Vergelijking met dagprecisie
let isSameDay = calendar.compare(date1, to: date2,
toGranularity: .day) == .orderedSame
// Controleer of datum vandaag is
let isToday = calendar.isDateInToday(someDate)
Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday — methoden voor relatieve controles. Calendar.isDate(_:inSameDayAs:) controleert of twee datums op dezelfde kalenderdag vallen met inachtneming van de tijdzone van de kalender. Deze methoden gebruiken intern Calendar.compare en zijn geoptimaliseerd voor frequent gebruik.
Calendar.dateInterval — een van de nuttigste methoden voor analyse en UI. Het retourneert DateInterval voor de opgegeven component: begin en einde van dag, week, maand, jaar. DateInterval bevat start (Date) en end (Date) — de grenzen van de periode. Bijvoorbeeld, dateInterval(of: .weekOfYear, for: Date()) retourneert het begin van maandag en het einde van zondag van de huidige week.
Calendar.date met byAdding — methode voor datumverschuiving. Calendar.date(byAdding: .day, value: 7, to: Date()) retourneert de datum over een week. Calendar.date(byAdding: DateComponents) — een flexibelere versie waarmee meerdere componenten tegelijk kunnen worden verschoven: +1 maand +3 dagen. Calendar houdt automatisch rekening met verschillende maandlengtes en schrikkeljaren.
Calendar.nextDate zoekt de volgende datum die overeenkomt met opgegeven DateComponents. De parameter matchingPolicy bepaalt het gedrag bij niet-overeenkomen: .nextTime — volgende overeenkomst in tijd, .nextTimePreservingSmallerComponents — behoudt minuten en seconden uit de originele datum, .strict — vereist exacte overeenkomst.
let calendar = Calendar.current
let today = Date()
// Begin en einde van de week
let weekInterval = calendar.dateInterval(
of: .weekOfYear, for: today
)!
// Verschuiving met 1 maand
let nextMonth = calendar.date(
byAdding: .month, value: 1, to: today
)!
// Verschuiving via DateComponents
var delta = DateComponents()
delta.month = 1
delta.day = 3
let shifted = calendar.date(byAdding: delta, to: today)!
// Volgende vrijdag de 13e
let friday13Components = DateComponents(
weekday: 6, day: 13
)
let nextFriday13 = calendar.nextDate(
after: today, matching: friday13Components,
matchingPolicy: .nextTime
)
EnumerateDates — een krachtige methode voor het itereren van datums volgens een patroon. Calendar.enumerateDates(startingAfter:matching:matchingPolicy:using:) roept een block aan voor elke overeenkomst totdat het block stop = true retourneert. Wordt gebruikt voor het genereren van terugkerende gebeurtenissen in kalenders en schema's. De methode is efficiënter dan een handmatige lus met nextDate omdat deze is geoptimaliseerd door ICU.
TimeZone — een onlosmakelijk onderdeel van Calendar. De tijdzone bepaalt welke kalendertijd overeenkomt met de absolute Date. Dezelfde Date in UTC en in Moskou geeft verschillende componenten: Date() in UTC kan 10:00 tonen, en in MSK — 13:00. Calendar.timeZone is standaard gelijk aan TimeZone.current.
Locale beïnvloedt de eerste dag van de week, het minimum aantal dagen in de eerste week van het jaar (minDaysInFirstWeek) en de namen van maanden/dagen van de week (bij conversie via DateFormatter). Calendar.locale is standaard gelijk aan Locale.current. In de Nederlandse locale begint de week op maandag, in de Amerikaanse — op zondag.
Calendar.availableIdentifiers retourneert een lijst van alle ondersteunde kalenderidentificaties. static property Calendar.availableCalendarIdentifiers — een array van strings met dezelfde identificaties. Wordt gebruikt voor het bouwen van een UI voor kalenderkeuze en voor het controleren van de beschikbaarheid van een specifiek kalendersysteem op het apparaat.
// Kalender met specifieke tijdzone
var utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!
// Kalender met Russische locale
var russianCalendar = Calendar(identifier: .gregorian)
russianCalendar.locale = Locale(identifier: "ru_RU")
// Eerste weekdag is afhankelijk van locale
let firstWeekday = russianCalendar.firstWeekday
// 2 = maandag (in nl_NL)
// Lijst van beschikbare kalenders
for identifier in Calendar.availableIdentifiers {
print(identifier)
}
firstWeekday — de eigenschap van Calendar die bepaalt welke dag van de week als eerste wordt beschouwd. In de Nederlandse locale is Sunday = 2 (maandag eerste). In de Amerikaanse is Sunday = 1. Dit beïnvloedt de werking van weekOfMonth en weekOfYear: dezelfde datum kan in verschillende locales aan verschillende weeknummers worden toegewezen. Gebruik voor applicaties met datums Calendar.current of stel firstWeekday expliciet in.
Laten we praktische scenario's bekijken die de mogelijkheden van Calendar demonstreren. Elk voorbeeld lost een specifieke taak in iOS-ontwikkeling op en toont de juiste manier van kalenderberekeningen.
Calendar.dateInterval(of: .month, for:) retourneert de grenzen van de huidige maand. Het controleren of Date binnen dit interval valt — de snelste manier om te bepalen of de datum tot de huidige maand behoort. Alternatieve manier — Calendar.compare met granularity .month: als het resultaat .orderedSame is, komt de maand overeen.
func isInCurrentMonth(_ date: Date) -> Bool {
let calendar = Calendar.current
let monthInterval = calendar.dateInterval(
of: .month, for: Date()
)!
return monthInterval.contains(date)
}
// Aantal dagen in een maand
func daysInMonth(for date: Date) -> Int {
let calendar = Calendar.current
return calendar.range(
of: .day, in: .month, for: date
)?.count ?? 0
}
// Toevoegen van maanden met correcte afronding
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:) retourneert het bereik van toegestane waarden voor de opgegeven component in de context van een andere component. Bijvoorbeeld, range(of: .day, in: .month, for: date) retourneert 1..<32 voor maanden met 31 dagen of 1..<29 voor februari van een niet-schrikkeljaar. Dit is de juiste manier om het aantal dagen in een maand te weten te komen, niet het gebruik van hardgecodeerde waarden.
Toevoegen van maanden via Calendar.date(byAdding:value:to:) verwerkt grensdaten correct. Als aan 31 januari 1 maand wordt toegevoegd, retourneert Calendar 28 februari (of 29 in een schrikkeljaar), niet 3 maart, zoals zou gebeuren bij eenvoudige toevoeging van 30 dagen via TimeInterval. Dit is nog een reden om geen TimeInterval te gebruiken voor kalenderberekeningen.
| Calendar methode | Doel | Voorbeeld |
|---|---|---|
| dateInterval | Periodegrenzen | Begin en einde van de maand |
| range(of:in:for:) | Componentbereik | Dagen in huidige maand |
| date(byAdding:) | Datumverschuiving | +1 maand vanaf vandaag |
| isDateInToday | Controle of vandaag | Is de datum vandaag |
| compare(toGranularity:) | Vergelijking met precisie | Zelfde dag zonder tijd |
Veelgestelde vragen
Calendar.current retourneert de kalender uit de systeeminstellingen van de gebruiker — deze kan niet-Gregoriaans zijn (bijvoorbeeld Boeddhistisch in Thailand). Calendar(identifier: .gregorian) maakt altijd een Gregoriaanse kalender, ongeacht de instellingen. Gebruik voor het weergeven van datums Calendar.current, voor bedrijfslogica — de expliciet gekozen identificatie.
Dit komt door de verschillende lengte van maanden. Als de huidige datum 31 januari is, geeft het toevoegen van 1 maand 28 februari, omdat februari geen 31 dagen heeft. Calendar vult de datum automatisch aan tot de laatste toegestane dag van de maand. Gebruik voor nauwkeurige controle DateComponents met day: 1 om naar de eerste dag van de maand te gaan.
DateFormatter gebruikt Calendar.current — de systeemkalender van de gebruiker. Als de applicatie altijd datums in de Gregoriaanse kalender moet tonen ongeacht de instellingen, stel dan formatter.calendar = Calendar(identifier: .gregorian) in. Dit garandeert een uniforme weergave voor alle gebruikers.
Calendar.range(of: .day, in: .year, for: date) retourneert 365 of 366 dagen. Eenvoudiger: Calendar.date(from: DateComponents(year: jaar, month: 2, day: 29)) != nil — als 29 februari bestaat, is het jaar een schrikkeljaar. Calendar houdt zelf rekening met de regels voor het specifieke kalendersysteem.
Ja, de eigenschap firstWeekday is beschrijfbaar. Wijziging beïnvloedt weekOfMonth, weekOfYear en alle berekeningen met betrekking tot weeknummers. Bij het instellen van locale = Locale(identifier: "nl_NL") wordt firstWeekday automatisch 2 (maandag). Handmatige instelling overschrijft de waarde uit locale.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook