DateFormatter — dit is een Foundation-klasse die bedoeld is voor de bidirectionele conversie tussen Date-objecten en hun tekenreeksrepresentatie. De klasse houdt rekening met de locale, de tijdzone en de kalender van de gebruiker, waardoor datums in elke regio van de wereld correct worden weergegeven. Volgens Apple Developer Documentation (2025) ondersteunt DateFormatter vier vooraf ingestelde stijlen voor datum en tijd, evenals volledig aangepaste formaten via een patroontekenreeks. Zonder DateFormatter is het onmogelijk om de datum correct aan de gebruiker weer te geven in een geïnternationaliseerde app.
Kernpunten
DateFormatter — dit is een klasse uit het Foundation-framework die de bidirectionele conversie tussen Date en een tekenreeks implementeert. Het verscheen in OpenStep als NSDateFormatter en blijft sindsdien het belangrijkste hulpmiddel voor datumopmaak op alle Apple-platforms. De klasse erft van Formatter en biedt een handige API voor gelokaliseerde weergave van datums.
Het werkingsprincipe van DateFormatter is gebaseerd op Unicode LDML-patronen — dezelfde die in ICU (International Components for Unicode) worden gebruikt. Het patroon wordt ingesteld via de eigenschap dateFormat, waarbij de tekens y, M, d, H, m, s overeenkomen met jaar, maand, dag, uren, minuten, seconden. Herhaling van een teken bepaalt het formaat: „y“ — een jaar met twee cijfers, „yyyy“ — met vier cijfers.
Het maken van een DateFormatter is een dure bewerking, omdat bij de initialisatie de locale- en kalendergegevens worden geladen. Apple raadt aan om de formatter één keer per opmaaktype te maken en opnieuw te gebruiken. In SwiftUI en UIKit worden formatters vaak in statische eigenschappen gecachet of lui aangemaakt bij de eerste aanroep.
DateFormatter wordt in veel systeemcomponenten van iOS gebruikt. UIDatePicker gebruikt intern DateFormatter om datums in de countDownTimer-modus weer te geven. Een TextField met een formatter kan automatisch een door de gebruiker ingevoerde datum valideren. Core Data ondersteunt kenmerken van het type Date, maar de tekenreeksweergave daarvan wordt altijd uitgevoerd via DateFormatter.
Thread Safety — DateFormatter is niet thread-safe. Het wijzigen van formatter-eigenschappen vanuit verschillende threads leidt tot ongedefinieerd gedrag. Maak voor multithreaded gebruik aparte formatter-instanties voor elke thread of gebruik synchronisatie via NSLock of een serial queue.
dateStyle en timeStyle zijn de eenvoudigste manieren om de weergave van de datum in te stellen. Elke stijl heeft vier varianten: .short, .medium, .long, .full. Door dateStyle en timeStyle te combineren kunt u het datum- en tijdformaat onafhankelijk instellen, en de eigenschap .none schakelt het betreffende deel uit.
Voor de Amerikaanse locale formatteert .short de datum als „7/21/26“, en voor de Russische als „21.07.2026“. De stijl .long geeft voor de Russische locale „21 juli 2026“ weer, en .full — „dinsdag, 21 juli 2026“ met vermelding van de dag van de week. Alle vier de stijlen passen zich automatisch aan de regionale standaarden aan, inclusief de volgorde van de componenten en de scheidingstekens.
SFDateFormatter in iOS 15+ biedt een alternatieve benadering via RelativeDateFormatter en DateIntervalFormatter. RelativeDateFormatter toont „vandaag“, „gisteren“, „over 3 dagen“ voor een actuele context. DateIntervalFormatter geeft datumbereiken weer: „21–25 juli 2026“ — voor boekingen en planning.
| Stijl | Voorbeeld (ru_RU) | Voorbeeld (en_US) |
|---|---|---|
| .short | 21.07.2026 | 7/21/26 |
| .medium | 21 jul. 2026 | Jul 21, 2026 |
| .long | 21 juli 2026 | July 21, 2026 |
| .full | dinsdag, 21 juli 2026 | Tuesday, July 21, 2026 |
Bij het combineren van stijlen kiest DateFormatter automatisch het scheidingsteken: voor .short.date + .short.time kan het resultaat „21.07.2026, 14:30“ zijn. Voor .full.date + .full.time — „dinsdag, 21 juli 2026, 14:30:00 MSK“. Het scheidingsteken wordt bepaald door de locale, niet door de ontwikkelaar — dit garandeert dat het overeenkomt met de regionale verwachtingen van de gebruiker.
dateFormat maakt het mogelijk om een willekeurig opmaakpatroon op te geven met behulp van de tekens van de Unicode LDML-specificatie. Dit geeft volledige controle over de weergave: u kunt alleen jaar en maand tonen, of de dag van de week zonder getal, of de tijd zonder seconden. Een aangepast formaat is onmisbaar voor specifieke ontwerpeisen.
De belangrijkste tekens zijn yyyy (jaar: 2026), MM (maand: 07), dd (dag: 21), HH (uren: 14), mm (minuten: 30), ss (seconden: 00). Gebruik voor de volledige naam van de maand MMMM (juli), voor de afgekorte — MMM (jul.). De dag van de week is EEEE (dinsdag), afgekort — E (di).
Bij het gebruik van dateFormat is het belangrijk om de locale van de formatter in te stellen. Als er geen locale is ingesteld, gebruikt de formatter de systeemlocale, wat ongewenst kan zijn voor een vast formaat in een API. Apple raadt aan om locale = Locale(identifier: „en_US_POSIX“) in te stellen voor een vast interregionaal formaat, vooral bij het parsen van datums uit serverantwoorden.
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.dateFormat = "d MMMM yyyy"
let customString = formatter.string(from: Date())
// "21 juli 2026"
// Parsen van een aangepaste tekenreeks
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = formatter.date(from: "2026-07-21 14:30:00")!
Een fout in dateFormat is een van de meest voorkomende oorzaken van crashes in apps. Als het formaat niet overeenkomt met de tekenreeks, retourneert de methode date(from:) nil. Gebruik guard let of ?? om een optionele waarde veilig te extraheren. Test het formaat op alle ondersteunde talen — sommige LDML-tekens werken in verschillende locales anders.
Locale bepaalt hoe de namen van maanden en dagen van de week worden weergegeven en welke scheidingstekens worden gebruikt. DateFormatter gebruikt standaard Locale.current, maar in sommige scenario's moet u een specifieke locale opgeven: gebruik voor een vast formaat in logs en_US_POSIX, en voor serverdatums een locale die overeenkomt met de server.
De eigenschap TimeZone bepaalt de tijdzone voor de weergave. Standaard wordt de systeemtijdzone gebruikt, maar voor apps met een internationaal publiek is het vaak nodig om datums in de tijdzone van de gebruiker of in UTC weer te geven. Het wijzigen van timeZone heeft alleen invloed op de weergave — de waarde van Date blijft ongewijzigd.
Een belangrijk kenmerk: als DateFormatter wordt gebruikt om een tekenreeks te parsen en de tekenreeks bevat een tijdszone-aanwijzing (bijvoorbeeld „2026-07-21T14:30:00Z“ met Z voor UTC), wordt de eigenschap timeZone genegeerd — de formatter gebruikt de tijdzone uit de tekenreeks. Als er geen tijdzone in de tekenreeks staat, wordt de timeZone van de formatter toegepast.
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
formatter.dateStyle = .long
formatter.timeStyle = .short
let moscowTime = formatter.string(from: Date())
// "21 juli 2026, 14:30"
// Parsen zonder tijdzone in de tekenreeks
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd HH:mm"
let utcDate = formatter.date(from: "2026-07-21 10:30")!
AutoupdatingCurrentLocale — een speciaal type locale dat automatisch wordt bijgewerkt wanneer de systeeminstellingen van de gebruiker veranderen. DateFormatter ondersteunt dit standaard. Als de app op de achtergrond draait en de gebruiker de systeemtaal wijzigt, blijft de formatter die vóór de wijziging is gemaakt de oude locale gebruiken — om bij te werken moet u een nieuwe instantie maken.
ISO8601DateFormatter — een gespecialiseerde formatter voor het werken met datums in het ISO 8601-formaat. Dit formaat is de de facto standaard voor REST API's, JSON en gegevensuitwisseling. ISO8601DateFormatter werkt aanzienlijk sneller dan DateFormatter, omdat het niet afhankelijk is van de locale en een vaste parsesyntaxis gebruikt.
De belangrijkste opties van de formatter zijn .withInternetDateTime (2026-07-21T14:30:00Z), .withFractionalSeconds (voegt milliseconden toe), .withTimeZone (bevat de tijdszone-offset). Door opties te combineren kunt u elke ISO 8601-variant verkrijgen: met milliseconden, met tijdszone, met datum zonder tijd.
JSONEncoder.DateEncodingStrategy maakt het mogelijk om de codering van datums voor alle Codable-modellen globaal in te stellen. De opties zijn .iso8601 (gebruikt ISO8601DateFormatter), .formatted(DateFormatter), .millisecondsSince1970, .secondsSince1970. De keuze van de strategie beïnvloedt de hele levenscyclus van de serialisatie en moet voor alle API-endpoints uniform zijn.
// ISO8601DateFormatter
let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let isoString = isoFormatter.string(from: Date())
// "2026-07-21T14:30:00.000Z"
// JSONEncoder met ISO8601
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
// Alternatief: JSONEncoder met een aangepaste formatter
let customEncoder = JSONEncoder()
customEncoder.dateEncodingStrategy = .formatted(myFormatter)
DateFormatter vs ISO8601DateFormatter — kies ISO8601DateFormatter voor serialisatie en het parsen van datums in een API, omdat het 5-10 keer sneller werkt dan DateFormatter en niet gevoelig is voor lokalisatiefouten. Gebruik DateFormatter voor de gebruikersinterface, waar een gelokaliseerde weergave met namen van maanden en dagen van de week in de moedertaal van de gebruiker vereist is.
Laten we echte scenario's bekijken voor het gebruik van DateFormatter in een iOS-app: weergave in een nieuwsfeed, invoer van een geboortedatum en export van een rapport met datums in verschillende tijdzones.
RelativeDateFormatter is optimaal voor nieuwsfeeds. Het toont „zojuist“, „5 minuten geleden“, „gisteren“ voor actueel nieuws en schakelt over naar de volledige datum voor ouder nieuws. De drempel voor overschakelen wordt ingesteld via calendar: gebruik voor nieuws een drempel van 24 uur, voor messengers — een week.
func formatRelativeDate(_ date: Date) -> String {
let relative = RelativeDateFormatter()
relative.unitsStyle = .full
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let daysDiff = Calendar.current.dateComponents(
[.day], from: date, to: Date()
).day ?? 0
return daysDiff < 1
? relative.localizedString(for: date, relativeTo: Date())
: formatter.string(from: date)
}
Invoer van de geboortedatum — nog een veelvoorkomend scenario. DateFormatter wordt geconfigureerd met een specifiek dateFormat „dd.MM.yyyy“ en locale „ru_RU“. Bij het parsen van de ingevoerde tekenreeks is het belangrijk om mogelijke fouten af te handelen: de formatter retourneert nil voor een ongeldige tekenreeks. Na succesvol parsen wordt de datum gecontroleerd op een geldig bereik — niet vóór 1900, niet later dan vandaag.
Export van een rapport met datums vereist een vast formaat dat onafhankelijk is van de locale van de gebruiker. Gebruik dateFormat „yyyy-MM-dd HH:mm:ss“ met locale en_US_POSIX en tijdzone UTC. Deze aanpak garandeert dat het bestand in elk land correct wordt geopend, ongeacht de regionale systeeminstellingen.
| Scenario | Formatter | Belangrijkste instelling |
|---|---|---|
| Nieuwsfeed | RelativeDateFormatter | unitsStyle = .full |
| Datum invoeren | DateFormatter | dateFormat + fallback |
| API-serialisatie | ISO8601DateFormatter | withInternetDateTime |
| Export van rapport | DateFormatter | en_US_POSIX + UTC |
Veelgestelde vragen
De meest voorkomende oorzaak is een mismatch tussen dateFormat en het formaat van de tekenreeks. Het formaat „dd.MM.yyyy“ kan bijvoorbeeld de tekenreeks „2026-07-21“ niet parsen. De tweede oorzaak is een lokalisatiefout: de tekenreeks „July 21, 2026“ wordt niet geparsed met locale ru_RU. De derde zijn typefouten in LDML-tekens: gebruik yyyy, niet YYYY (verschillende betekenis).
Nee. DateFormatter is een zwaar object; de initialisatie omvat het laden van locale-gegevens. Maak één instantie per opmaaktype en hergebruik deze. Gebruik in een multithreaded omgeving thread-local storage of een pool van formatters met een serial queue voor synchronisatie.
DateFormatter toont een absolute datum (21 juli 2026), terwijl RelativeDateFormatter een relatieve toont (vandaag, gisteren, over 3 dagen). RelativeDateFormatter is verschenen in iOS 15+ en gebruikt hetzelfde LDML-patroon, maar kiest automatisch de relatieve weergave.
Stel de timeZone van de formatter in op UTC vóór het parsen. Als de server een datum in lokale tijd levert zonder tijdzone-aanduiding, controleer dan de API-specificatie — hoogstwaarschijnlijk wordt UTC bedoeld. Voor ISO 8601 met Z aan het einde is timeZone niet nodig — de formatter parset de offset uit de tekenreeks.
Gebruik niet één instantie vanuit verschillende threads zonder synchronisatie. Maak in elke thread een nieuwe instantie of gebruik Thread.current.threadDictionary voor opslag. Een alternatief is NSLock met een blokkering voor de duur van string(from:) en date(from:).
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