ISO8601DateFormatter: nyckelbegrepp och ISO 8601-formatering

Författare: IT Sectr Publicerad: 2026-07-13 Lästid: 9 min

ISO8601DateFormatter — är en Foundation-klass i iOS och macOS, avsedd för formatering och tolkning av datum i den internationella standarden ISO 8601. Enligt Apple Developer Documentation, 2024, hanterar ISO8601DateFormatter automatiskt format med millisekunder, tidszoner och bråkdelar av sekunder utan att man behöver ställa in DateFormat manuellt. Till skillnad från DateFormatter är denna klass inte beroende av Locale och TimeZone — den arbetar strikt enligt ISO 8601-specifikationen, vilket gör den idealisk för utbyte av datum mellan server och klient. Klassen är tillgänglig från iOS 10 och macOS 10.12.

Huvudpunkter

  • ISO8601DateFormatter — Foundation-klass för formatering av datum enligt ISO 8601
  • Kräver inte DateFormat — formatet bestäms automatiskt baserat på alternativinställningar
  • Lokaliseringsoberoende — fungerar likadant på alla enheter utan Locale-konfiguration
  • Stöd för millisekunder — hanterar bråkdelar av sekunder med valfri precision (tre, sex och fler tecken)
  • Formateringsalternativ — withFullDate, withTime, withMilliseconds, withTimeZone och andra styr utdatakomponenterna

Vad är ISO8601DateFormatter?

ISO8601DateFormatter — är en specialiserad underklass av Formatter i Foundation som implementerar tvåvägskonvertering mellan Date och en sträng i ISO 8601-format. Standarden ISO 8601 (International Standard for the Representation of Dates and Times) definierar det internationella formatet för utbyte av datum och tid: 2024-07-21T14:30:00+00:00. Till skillnad från DateFormatter kräver denna klass inte att man anger dateFormat och bestämmer automatiskt strängens struktur baserat på givna alternativ.

De främsta fördelarna med ISO8601DateFormatter jämfört med DateFormatter: inget beroende av locale (tolkning fungerar likadant på alla enheter), inbyggt stöd för bråkdelar av sekunder (med valfritt antal decimaler) och automatisk bestämning av format baserat på överförda alternativ. Klassen hanterar också korrekt Z-suffixet (UTC-beteckning), tidszoner i formatet +HH:mm och reducerad precision (endast datum utan tid).

Enligt ISO Specification (ISO 8601-1:2019) stöder standarden fyra precisionsnivåer: år (2024), år-månad (2024-07), fullständigt datum (2024-07-21) och datum-tid med tidszon (2024-07-21T14:30:00+00:00). ISO8601DateFormatter täcker alla dessa nivåer genom kombinationer av formatalternativ, vilket befriar utvecklaren från att manuellt konstruera en dateFormat-sträng.

Hur fungerar ISO8601DateFormatter i Foundation?

Funktionsprincip för ISO8601DateFormatter baseras på kombinationer av bitalternativ (formatOptions), där var och en aktiverar en specifik datum- eller tidkomponent i utdata. Till exempel aktiverar alternativet .withFullDate år, månad och dag; .withTime — timmar, minuter och sekunder. Genom att kombinera alternativ uppnår utvecklaren önskad precisionsnivå utan att skriva en dateFormat-sträng.

Internt använder ISO8601DateFormatter ICU-biblioteket för tolkning, men med fasta ISO 8601-regler. Detta innebär att det ignorerar Locale- och TimeZone-inställningar på enheten — resultatet är alltid förutsägbart. För inställning av tidszon används egenskapen timeZone, som som standard är lika med UTC. Om timeZone är inställt på nil, används enhetens lokala tid.

AlternativBeskrivningExempel på utdata
.withFullDateÅr, månad, dag2024-07-21
.withTimeTimmar, minuter, sekunder14:30:00
.withMillisecondsBråkdelar av sekunder (upp till 3 tecken).123
.withFractionalSecondsBråkdelar av sekunder (valfri precision).123456
.withTimeZoneTidszon+03:00
.withColonSeparatorInTimeZoneKolonseparator i tidszon+03:00 (istället för +0300)
.withInternetDateTimeFullständigt format (date + time + tz)2024-07-21T14:30:00+00:00

Kombinera alternativ: .withInternetDateTime är likvärdigt med att kombinera .withFullDate, .withTime och .withTimeZone. För tolkning av strängar med millisekunder, lägg till .withFractionalSeconds. Det är viktigt att komma ihåg att .withMilliseconds begränsar bråkdelar av sekunder till tre tecken, medan .withFractionalSeconds stöder valfri precision — från en till nio decimaler.

ISO 8601-formatinställningar

Formatalternativ för ISO8601DateFormatter är indelade i tre grupper: datumkomponenter (withFullDate, withYear, withMonth, withDay, withWeekOfYear), tidskomponenter (withTime, withHours, withMinutes, withSeconds) och ytterligare inställningar (withMilliseconds, withFractionalSeconds, withTimeZone, withColonSeparatorInTimeZone, withDashSeparatorInDate, withFullTime). Genom att kombinera dem kan man få praktiskt taget vilket underformat av ISO 8601 som helst.

Huvudsakliga alternativkombinationer

  • .withFullDate — endast datum: 2024-07-21. För tolkning av strängar i formatet YYYY-MM-DD
  • .withFullDate + .withTime — datum och tid utan tidszon: 2024-07-21T14:30:00
  • .withInternetDateTime — fullständigt format: 2024-07-21T14:30:00Z eller 2024-07-21T14:30:00+03:00
  • .withInternetDateTime + .withFractionalSeconds — med bråkdelar av sekunder: 2024-07-21T14:30:00.123456+00:00
  • .withFullDate + .withTime + .withTimeZone — fullständigt format utan kolon i tz: 2024-07-21T14:30:00+0300

Viktig nyans: .withFractionalSeconds och .withMilliseconds är ömsesidigt uteslutande — om båda är inställda tillämpas .withFractionalSeconds. För tolkning av millisekunder från serverdata rekommenderas .withFractionalSeconds, eftersom många servrar skickar bråkdelar av sekunder med tre, sex eller nio tecken, och .withFractionalSeconds hanterar vilken längd som helst.

swift
import Foundation

// Konfigurera ISO8601DateFormatter
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)

// Olika kombinationer av formatalternativ
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("Fullständig: \(full)")

// Tolka sträng med millisekunder
let serverString = "2024-07-21T14:30:00.123456+03:00"
if let parsed = formatter.date(from: serverString) {
    print("Tolkat: \(parsed)")
}

ISO8601DateFormatter i Swift: kodexempel

Grundläggande användning av ISO8601DateFormatter handlar om att skapa en instans, ställa in timeZone (UTC rekommenderas för serverdata) och formatOptions, varefter man kan anropa string(from:) för formatering och date(from:) för tolkning. Till skillnad från DateFormatter behöver man inte oroa sig för Locale — klassen ignorerar regionala inställningar.

swift
import Foundation

let formatter = ISO8601DateFormatter()

// Tolka olika ISO 8601-format
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("Tolkat '\(str)': \(autoParsed)")
    } else {
        // Använd withFullDate för strängar med endast datum
        formatter.formatOptions = [.withFullDate]
        if let fallback = formatter.date(from: str) {
            print("Fallback tolkat '\(str)': \(fallback)")
        }
        formatter.formatOptions = [.withInternetDateTime]
    }
}

// Serialisera till RFC 3339 (GitHub API)
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let rfc3339 = formatter.string(from: Date())
print("RFC 3339: \(rfc3339)")

Tolkning av datum med bråkdelar av sekunder av varierande längd — en egenskap hos många moderna API:er. Servern kan skicka både 2024-07-21T14:30:00.123Z (3 tecken) och 2024-07-21T14:30:00.123456Z (6 tecken). ISO8601DateFormatter med alternativet .withFractionalSeconds kommer att hantera båda varianterna korrekt, medan DateFormatter med dateFormat = „yyyy-MM-dd’T’HH:mm:ss.SSSZ” endast kommer att bearbeta tresiffriga millisekunder.

swift
import Foundation

let variantFormatter = ISO8601DateFormatter()
variantFormatter.formatOptions = [
    .withInternetDateTime,
    .withFractionalSeconds
]

// Olika precision för bråkdelar av sekunder
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)")
    }
}

// Använd withMilliseconds (endast 3 siffror)
variantFormatter.formatOptions = [
    .withInternetDateTime,
    .withMilliseconds
]
let milliParsed = variantFormatter.string(from: Date())
print("Med millisekunder: \(milliParsed)")

Testa tolkning av alla varianter: koden ovan visar att ISO8601DateFormatter med .withFractionalSeconds framgångsrikt bearbetar bråkdelar av sekunder av valfri längd från 1 till 9 tecken. Detta är viktigt för kompatibilitet med olika serverplattformar: .NET genererar ofta 7 tecken (100-nanosekunders tickar), Python — 6, Java — 3 eller 9 beroende på version.

Jämförelse med DateFormatter för ISO 8601

DateFormatter kan också tolka ISO 8601, men kräver manuell inställning av dateFormat, locale och timeZone. Huvudproblemet är att DateFormatter är beroende av Locale, och om man inte ställer in en_US_POSIX kan tolkningen gå sönder för användare från regioner med icke-standardiserade datumformat. ISO8601DateFormatter löser detta problem på arkitekturnivå: det använder inte Locale.

ParameterISO8601DateFormatterDateFormatter
Locale-inställningKrävs inte (ignorerar)en_US_POSIX obligatoriskt
DateFormatAutomatisk (via alternativ)Manuell formatsträng
Bråkdelar av sekunderValfri precision (.withFractionalSeconds)Fast SSS
Z-suffixKorrekt hanteringVia dateFormat
PrestandaHögre (specialiserad)Lägre (allmän)
StandardEndast ISO 8601Valfritt format
iOS-versioniOS 10+iOS 2+

När ska DateFormatter användas: om man behöver formatera ett datum i ett icke-ISO 8601-format (till exempel „21 juli 2024” för UI) eller om stöd för iOS 9 och äldre krävs. För alla uppgifter som rör datumutbyte med servern, använd ISO8601DateFormatter — det är säkrare, mer prestandaeffektivt och kräver mindre kod. DateFormatter för ISO 8601 är en källa till potentiella buggar relaterade till locale och regionala inställningar.

Migrering från DateFormatter till ISO8601DateFormatter: ersätt skapandet av DateFormatter + inställning av dateFormat + locale + timeZone med skapandet av ISO8601DateFormatter + inställning av formatOptions + timeZone. Tolkningen av strängen förblir oförändrad via date(from:). För bakåtkompatibilitet kan man använda #available(iOS 10, *) med en fallback till DateFormatter.

Vanliga misstag vid tolkning av ISO 8601

Glömd formatOptions-inställning gör att formatteraren använder standardvärdet — .withInternetDateTime. Om servern endast skickar datum utan tid (2024-07-21), kommer tolkningen att returnera nil. Kontrollera alltid att formatOptions täcker alla möjliga format som kan komma från servern. För API:er med varierande format, använd fallback-försök med olika alternativkombinationer.

Förväxling mellan withMilliseconds och withFractionalSeconds — ett vanligt misstag vid tolkning av datum med bråkdelar av sekunder. withMilliseconds förväntar sig exakt 3 decimaler. Om servern skickar 6 siffror (mikrosekunder), kommer tolkning med withMilliseconds att misslyckas. Använd .withFractionalSeconds för kompatibilitet med valfritt antal tecken. .withFractionalSeconds kom i iOS 13; för äldre versioner, använd DateFormatter med dateFormat.

Ignorering av tidszon — ett annat vanligt problem. Om servern skickar datum med tidszon (+03:00) och formatteraren är inställd på UTC, kommer tolkningen inte att misslyckas, men resultatet blir i UTC. Utvecklare förväntar sig ofta att Date behåller tidszonen, men Date är ett absolut ögonblick i tiden och lagrar inte tidszoninformation. För korrekt visning, spara tidszonen separat eller använd ISO8601DateFormatter med rätt timeZone.

Enligt Apple Forum (2024) handlar cirka 20% av frågorna om ISO8601DateFormatter om formatet där sekunder är valfria. ISO 8601-standarden tillåter format utan sekunder: 2024-07-21T14:30+03:00. ISO8601DateFormatter med .withInternetDateTime stöder inte detta format — för att tolka det krävs DateFormatter med dateFormat = „yyyy-MM-dd’T’HH:mmZ”. Denna begränsning måste beaktas när man arbetar med API:er som använder förkortat tidsformat.

Vanliga frågor

Vad är ISO8601DateFormatter?

ISO8601DateFormatter — specialiserad Foundation-klass för formatering och tolkning av datum i ISO 8601-format, tillgänglig från iOS 10. Bearbetar automatiskt standardformat utan manuell inställning av dateFormat.

Vad är skillnaden mellan ISO8601DateFormatter och DateFormatter?

ISO8601DateFormatter är inte beroende av Locale, använder alternativ istället för dateFormat och hanterar korrekt bråkdelar av sekunder av valfri längd. DateFormatter är universell men kräver manuell konfiguration och är känslig för buggar relaterade till regionala inställningar.

Hur hanterar man bråkdelar av sekunder av varierande längd?

Använd alternativet .withFractionalSeconds — stöder 1 till 9 tecken efter decimalkommat. Använd inte .withMilliseconds om precisionen kan variera. .withFractionalSeconds är tillgänglig från iOS 13.

Vilken tidszon använder ISO8601DateFormatter?

Standard är UTC. För att ändra, ställ in egenskapen timeZone. Om timeZone = nil, används enhetens lokala tid. Vid tolkning av en sträng med explicit tidszon i formatet +HH:MM tar formatteraren automatiskt hänsyn till den.

Varför returnerar tolkning av datum utan tid nil?

Eftersom standard formatOptions = .withInternetDateTime, som förväntar sig datum + tid + tidszon. För tolkning av endast datum, ställ in formatOptions = [.withFullDate]. För att stödja båda varianterna, använd fallback med olika alternativ.

Sammanfattning

  • ISO8601DateFormatter — specialiserad klass för ISO 8601, säkrare och enklare än DateFormatter
  • Formatalternativ ersätter manuell dateFormat — kombinera .withFullDate, .withTime, .withTimeZone
  • Inte beroende av Locale — tolkning fungerar likadant på alla enheter utan locale-konfiguration
  • .withFractionalSeconds hanterar bråkdelar av sekunder med valfri precision (1–9 tecken)
  • DateFormatter förlorar i prestanda, säkerhet och enkelhet för ISO 8601-uppgifter
  • Alternativförväxling — withMilliseconds och withFractionalSeconds är inte utbytbara
  • Format utan sekunder (2024-07-21T14:30+03:00) stöds inte — DateFormatter krävs

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å