ISO8601DateFormatter — is een Foundation-klasse in iOS en macOS, bedoeld voor het formatteren en parsen van datums in de internationale standaard ISO 8601. Volgens Apple Developer Documentation, 2024, verwerkt ISO8601DateFormatter automatisch formaten met milliseconden, tijdzones en fracties van seconden zonder dat je DateFormat handmatig hoeft in te stellen. In tegenstelling tot DateFormatter is deze klasse niet afhankelijk van Locale en TimeZone — hij werkt strikt volgens de ISO 8601-specificatie, wat hem ideaal maakt voor het uitwisselen van datums tussen server en client. De klasse is beschikbaar vanaf iOS 10 en macOS 10.12.
Belangrijkste punten
ISO8601DateFormatter — is een gespecialiseerde subklasse van Formatter in Foundation die bidirectionele conversie implementeert tussen Date en een string in ISO 8601-formaat. De ISO 8601-standaard (International Standard for the Representation of Dates and Times) definieert het internationale formaat voor het uitwisselen van datums en tijden: 2024-07-21T14:30:00+00:00. In tegenstelling tot DateFormatter vereist deze klasse geen dateFormat en bepaalt hij automatisch de structuur van de string op basis van de gegeven opties.
De belangrijkste voordelen van ISO8601DateFormatter ten opzichte van DateFormatter: geen afhankelijkheid van locale (parsen werkt hetzelfde op elk apparaat), ingebouwde ondersteuning voor fracties van seconden (met elk aantal decimalen) en automatische bepaling van het formaat op basis van doorgegeven opties. De klasse verwerkt ook correct het Z-suffix (UTC-aanduiding), tijdzones in +HH:mm-formaat en verminderde precisie (alleen datum zonder tijd).
Volgens ISO Specification (ISO 8601-1:2019) ondersteunt de standaard vier niveaus van precisie: jaar (2024), jaar-maand (2024-07), volledige datum (2024-07-21) en datum-tijd met tijdzone (2024-07-21T14:30:00+00:00). ISO8601DateFormatter dekt al deze niveaus via combinaties van formaatopties, waardoor de ontwikkelaar geen handmatige dateFormat-string hoeft te construeren.
Werkingsprincipe van ISO8601DateFormatter is gebaseerd op combinaties van bitopties (formatOptions), die elk een specifieke datum- of tijdcomponent in de uitvoer inschakelen. Bijvoorbeeld, de optie .withFullDate schakelt jaar, maand en dag in; .withTime — uren, minuten en seconden. Door opties te combineren, krijgt de ontwikkelaar het gewenste precisieniveau zonder een dateFormat-string te schrijven.
Intern gebruikt ISO8601DateFormatter de ICU-bibliotheek voor het parsen, maar met vaste ISO 8601-regels. Dit betekent dat hij de Locale- en TimeZone-instellingen op het apparaat negeert — het resultaat is altijd voorspelbaar. Voor het instellen van de tijdzone wordt de eigenschap timeZone gebruikt, die standaard gelijk is aan UTC. Als timeZone is ingesteld op nil, wordt de lokale tijd van het apparaat gebruikt.
| Optie | Beschrijving | Voorbeelduitvoer |
|---|---|---|
| .withFullDate | Jaar, maand, dag | 2024-07-21 |
| .withTime | Uren, minuten, seconden | 14:30:00 |
| .withMilliseconds | Fracties van seconden (tot 3 tekens) | .123 |
| .withFractionalSeconds | Fracties van seconden (elke precisie) | .123456 |
| .withTimeZone | Tijdzone | +03:00 |
| .withColonSeparatorInTimeZone | Scheidingsteken : in tijdzone | +03:00 (in plaats van +0300) |
| .withInternetDateTime | Volledig formaat (date + time + tz) | 2024-07-21T14:30:00+00:00 |
Opties combineren: .withInternetDateTime is gelijk aan de combinatie van .withFullDate, .withTime en .withTimeZone. Voor het parsen van strings met milliseconden, voeg .withFractionalSeconds toe. Het is belangrijk te onthouden dat .withMilliseconds fracties van seconden beperkt tot drie tekens, terwijl .withFractionalSeconds elke precisie ondersteunt — van een tot negen cijfers achter de komma.
Formaatopties van ISO8601DateFormatter zijn verdeeld in drie groepen: datumcomponenten (withFullDate, withYear, withMonth, withDay, withWeekOfYear), tijdcomponenten (withTime, withHours, withMinutes, withSeconds) en aanvullende instellingen (withMilliseconds, withFractionalSeconds, withTimeZone, withColonSeparatorInTimeZone, withDashSeparatorInDate, withFullTime). Door ze te combineren, kun je vrijwel elk subformaat van ISO 8601 verkrijgen.
Belangrijke nuance: .withFractionalSeconds en .withMilliseconds sluiten elkaar uit — als beide zijn ingesteld, wordt .withFractionalSeconds toegepast. Voor het parsen van milliseconden uit servergegevens wordt .withFractionalSeconds aanbevolen, omdat veel servers fracties van seconden met drie, zes of negen tekens sturen, en .withFractionalSeconds verwerkt elke lengte.
import Foundation
// Configureer ISO8601DateFormatter
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
// Verschillende combinaties van formaatopties
formatter.formatOptions = [.withFullDate]
let dateOnly = formatter.string(from: Date())
print("Datum: \(dateOnly)")
formatter.formatOptions = [.withFullDate, .withTime]
let dateTime = formatter.string(from: Date())
print("DateTime: \(dateTime)")
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let full = formatter.string(from: Date())
print("Volledig: \(full)")
// Parseer string met milliseconden
let serverString = "2024-07-21T14:30:00.123456+03:00"
if let parsed = formatter.date(from: serverString) {
print("Geparsed: \(parsed)")
}
Basisgebruik van ISO8601DateFormatter komt neer op het maken van een instantie, het instellen van timeZone (UTC wordt aanbevolen voor servergegevens) en formatOptions, waarna string(from:) kan worden aangeroepen voor formattering en date(from:) voor parsen. In tegenstelling tot DateFormatter hoef je je geen zorgen te maken over Locale — de klasse negeert regionale instellingen.
import Foundation
let formatter = ISO8601DateFormatter()
// Parseer verschillende ISO 8601-formaten
let strings: [String] = [
"2024-07-21T14:30:00Z",
"2024-07-21T14:30:00+03:00",
"2024-07-21T14:30:00.123Z",
"2024-07-21"
]
for str in strings {
if let autoParsed = formatter.date(from: str) {
print("Geparsed '\(str)': \(autoParsed)")
} else {
// Gebruik withFullDate voor strings met alleen datum
formatter.formatOptions = [.withFullDate]
if let fallback = formatter.date(from: str) {
print("Fallback geparsed '\(str)': \(fallback)")
}
formatter.formatOptions = [.withInternetDateTime]
}
}
// Serialiseer naar RFC 3339 (GitHub API)
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let rfc3339 = formatter.string(from: Date())
print("RFC 3339: \(rfc3339)")
Parsen van datums met fractionele seconden van variabele lengte — een kenmerk van veel moderne API's. De server kan zowel 2024-07-21T14:30:00.123Z (3 tekens) als 2024-07-21T14:30:00.123456Z (6 tekens) sturen. ISO8601DateFormatter met de optie .withFractionalSeconds zal beide varianten correct verwerken, terwijl DateFormatter met dateFormat = “yyyy-MM-dd’T’HH:mm:ss.SSSZ” alleen milliseconden met drie cijfers verwerkt.
import Foundation
let variantFormatter = ISO8601DateFormatter()
variantFormatter.formatOptions = [
.withInternetDateTime,
.withFractionalSeconds
]
// Verschillende precisie van fractionele seconden
let variants: [String] = [
"2024-07-21T14:30:00.1Z",
"2024-07-21T14:30:00.12Z",
"2024-07-21T14:30:00.123Z",
"2024-07-21T14:30:00.123456Z",
"2024-07-21T14:30:00.123456789Z"
]
for variant in variants {
if let parsed = variantFormatter.date(from: variant) {
print("OK: \(variant) -> \(parsed)")
} else {
print("FAIL: \(variant)")
}
}
// Gebruik withMilliseconds (alleen 3 cijfers)
variantFormatter.formatOptions = [
.withInternetDateTime,
.withMilliseconds
]
let milliParsed = variantFormatter.string(from: Date())
print("Met milliseconden: \(milliParsed)")
Testen van het parsen van alle varianten: bovenstaande code toont aan dat ISO8601DateFormatter met .withFractionalSeconds fracties van seconden van elke lengte van 1 tot 9 tekens succesvol verwerkt. Dit is belangrijk voor compatibiliteit met verschillende serverplatforms: .NET genereert vaak 7 tekens (100-nanosecond ticks), Python — 6, Java — 3 of 9 afhankelijk van de versie.
DateFormatter kan ook ISO 8601 parsen, maar vereist handmatige configuratie van dateFormat, locale en timeZone. Het grootste probleem is dat DateFormatter afhankelijk is van Locale, en als je geen en_US_POSIX instelt, kan het parsen mislukken bij gebruikers uit regio's met niet-standaard datumformaten. ISO8601DateFormatter lost dit probleem op architectuurniveau op: hij gebruikt geen Locale.
| Parameter | ISO8601DateFormatter | DateFormatter |
|---|---|---|
| Locale-configuratie | Niet nodig (negeert) | en_US_POSIX verplicht |
| DateFormat | Automatisch (via opties) | Handmatige format-string |
| Fractionele seconden | Elke precisie (.withFractionalSeconds) | Vaste SSS |
| Z-suffix | Correcte verwerking | Via dateFormat |
| Prestaties | Hoger (gespecialiseerd) | Lager (algemeen) |
| Standaard | Alleen ISO 8601 | Elk formaat |
| iOS-versie | iOS 10+ | iOS 2+ |
Wanneer DateFormatter gebruiken: als je een datum moet formatteren in een niet-ISO 8601-formaat (bijvoorbeeld „21 juli 2024” voor de UI) of als ondersteuning voor iOS 9 en ouder vereist is. Gebruik voor alle taken van datumuitwisseling met de server ISO8601DateFormatter — hij is veiliger, performanter en vereist minder code. DateFormatter voor ISO 8601 is een bron van potentiële bugs gerelateerd aan locale en regionale instellingen.
Migratie van DateFormatter naar ISO8601DateFormatter: vervang het maken van DateFormatter + configuratie van dateFormat + locale + timeZone door het maken van ISO8601DateFormatter + configuratie van formatOptions + timeZone. Het parsen van de string blijft ongewijzigd via date(from:). Voor achterwaartse compatibiliteit kun je #available(iOS 10, *) gebruiken met een fallback naar DateFormatter.
Vergeten formatOptions-configuratie zorgt ervoor dat de formatter de standaardwaarde gebruikt — .withInternetDateTime. Als de server alleen een datum zonder tijd stuurt (2024-07-21), retourneert het parsen nil. Controleer altijd of formatOptions alle mogelijke formaten dekt die van de server kunnen komen. Gebruik voor API's met variabele formaten fallback-pogingen met verschillende optiecombinaties.
Verwarring tussen withMilliseconds en withFractionalSeconds — een veelgemaakte fout bij het parsen van datums met fracties van seconden. withMilliseconds verwacht precies 3 cijfers achter de komma. Als de server 6 cijfers (microseconden) stuurt, zal het parsen met withMilliseconds mislukken. Gebruik .withFractionalSeconds voor compatibiliteit met elk aantal tekens. .withFractionalSeconds verscheen in iOS 13; gebruik voor oudere versies DateFormatter met dateFormat.
Negeren van de tijdzone — nog een veelvoorkomend probleem. Als de server een datum met tijdzone stuurt (+03:00) en de formatter is ingesteld op UTC, zal het parsen niet mislukken, maar het resultaat is in UTC. Ontwikkelaars verwachten vaak dat Date de tijdzone behoudt, maar Date is een absoluut moment in de tijd en slaat geen tijdzone-informatie op. Sla voor correcte weergave de tijdzone apart op of gebruik ISO8601DateFormatter met de juiste timeZone.
Volgens Apple Forum (2024) heeft ongeveer 20% van de vragen over ISO8601DateFormatter betrekking op het formaat waarin seconden optioneel zijn. De ISO 8601-standaard staat een formaat zonder seconden toe: 2024-07-21T14:30+03:00. ISO8601DateFormatter met .withInternetDateTime ondersteunt dit formaat niet — voor het parsen ervan is DateFormatter nodig met dateFormat = „yyyy-MM-dd’T’HH:mmZ”. Met deze beperking moet rekening worden gehouden bij het werken met API's die een verkort tijdsformaat gebruiken.
Veelgestelde vragen
ISO8601DateFormatter — een gespecialiseerde Foundation-klasse voor het formatteren en parsen van datums in ISO 8601-formaat, beschikbaar vanaf iOS 10. Verwerkt automatisch standaardformaten zonder handmatige dateFormat.
ISO8601DateFormatter is niet afhankelijk van Locale, gebruikt opties in plaats van dateFormat en verwerkt correct fracties van seconden van elke lengte. DateFormatter is universeel, maar vereist handmatige configuratie en is vatbaar voor bugs gerelateerd aan regionale instellingen.
Gebruik de optie .withFractionalSeconds — ondersteunt 1 tot 9 tekens achter de komma. Gebruik .withMilliseconds niet als de precisie kan variëren. .withFractionalSeconds is beschikbaar vanaf iOS 13.
Standaard UTC. Wijzig de eigenschap timeZone om dit aan te passen. Als timeZone = nil, wordt de lokale tijd van het apparaat gebruikt. Bij het parsen van een string met een expliciete tijdzone in +HH:MM-formaat, houdt de formatter er automatisch rekening mee.
Omdat formatOptions standaard = .withInternetDateTime is, die datum + tijd + tijdzone verwacht. Stel voor het parsen van alleen de datum formatOptions = [.withFullDate] in. Gebruik fallback met verschillende opties om beide varianten te ondersteunen.
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