ISO8601DateFormatter: concepte cheie și formatare ISO 8601

Autor: IT Sectr Publicat: 2026-07-13 Timp de citire: 9 min

ISO8601DateFormatter — este o clasă Foundation în iOS și macOS, destinată formatării și parsării datelor în standardul internațional ISO 8601. Conform Apple Developer Documentation, 2024, ISO8601DateFormatter procesează automat formatele cu milisecunde, fusuri orare și fracțiuni de secundă fără a fi nevoie să setezi manual DateFormat. Spre deosebire de DateFormatter, această clasă nu depinde de Locale și TimeZone — funcționează strict conform specificației ISO 8601, ceea ce o face ideală pentru schimbul de date între server și client. Clasa este disponibilă începând cu iOS 10 și macOS 10.12.

Principalele puncte

  • ISO8601DateFormatter — clasă Foundation pentru formatarea datelor conform standardului ISO 8601
  • Nu necesită DateFormat — formatul este determinat automat de setările opțiunilor
  • Independent de localizare — funcționează la fel pe toate dispozitivele fără configurarea Locale
  • Suport pentru milisecunde — procesează fracțiuni de secundă de orice precizie (trei, șase și mai multe caractere)
  • Opțiuni de formatare — withFullDate, withTime, withMilliseconds, withTimeZone și altele controlează componentele rezultatului

Ce este ISO8601DateFormatter?

ISO8601DateFormatter — este o subclasă specializată a Formatter în Foundation, care implementează conversia bidirecțională între Date și un șir în formatul ISO 8601. Standardul ISO 8601 (International Standard for the Representation of Dates and Times) definește formatul internațional pentru schimbul de date și timp: 2024-07-21T14:30:00+00:00. Spre deosebire de DateFormatter, această clasă nu necesită specificarea dateFormat și determină automat structura șirului pe baza opțiunilor date.

Principalele avantaje ale ISO8601DateFormatter față de DateFormatter: absența dependenței de locale (parsarea funcționează la fel pe orice dispozitiv), suportul încorporat pentru fracțiuni de secundă (cu orice număr de zecimale) și determinarea automată a formatului pe baza opțiunilor transmise. Clasa gestionează corect și sufixul Z (desemnarea UTC), fusurile orare în formatul +HH:mm și precizia redusă (doar data fără timp).

Conform ISO Specification (ISO 8601-1:2019), standardul suportă patru niveluri de precizie: an (2024), an-lună (2024-07), dată completă (2024-07-21) și dată-timp cu fus orar (2024-07-21T14:30:00+00:00). ISO8601DateFormatter acoperă toate aceste niveluri prin combinarea opțiunilor de format, eliberând dezvoltatorul de construirea manuală a șirului dateFormat.

Cum funcționează ISO8601DateFormatter în Foundation?

Principiul de funcționare al ISO8601DateFormatter se bazează pe combinarea opțiunilor binare (formatOptions), fiecare activând o anumită componentă de dată sau timp în rezultat. De exemplu, opțiunea .withFullDate activează anul, luna și ziua; .withTime — orele, minutele și secundele. Combinând opțiunile, dezvoltatorul obține nivelul de precizie dorit fără a scrie un șir dateFormat.

Intern, ISO8601DateFormatter folosește biblioteca ICU pentru parsare, dar cu reguli fixe ISO 8601. Aceasta înseamnă că ignoră setările Locale și TimeZone instalate pe dispozitiv — rezultatul este întotdeauna previzibil. Pentru setarea fusului orar se folosește proprietatea timeZone, care implicit este egală cu UTC. Dacă timeZone este setat la nil, se folosește timpul local al dispozitivului.

OpțiuneDescriereExemplu rezultat
.withFullDateAn, lună, zi2024-07-21
.withTimeOre, minute, secunde14:30:00
.withMillisecondsFracțiuni de secundă (până la 3 caractere).123
.withFractionalSecondsFracțiuni de secundă (orice precizie).123456
.withTimeZoneFus orar+03:00
.withColonSeparatorInTimeZoneSeparator : în fusul orar+03:00 (în loc de +0300)
.withInternetDateTimeFormat complet (date + time + tz)2024-07-21T14:30:00+00:00

Combinarea opțiunilor: .withInternetDateTime este echivalent cu combinarea .withFullDate, .withTime și .withTimeZone. Pentru parsarea șirurilor cu milisecunde, adăugați .withFractionalSeconds. Este important să rețineți că .withMilliseconds limitează fracțiunile de secundă la trei caractere, în timp ce .withFractionalSeconds suportă orice precizie — de la una până la nouă cifre zecimale.

Setările formatului ISO 8601

Opțiunile de format ISO8601DateFormatter se împart în trei grupuri: componente de dată (withFullDate, withYear, withMonth, withDay, withWeekOfYear), componente de timp (withTime, withHours, withMinutes, withSeconds) și setări suplimentare (withMilliseconds, withFractionalSeconds, withTimeZone, withColonSeparatorInTimeZone, withDashSeparatorInDate, withFullTime). Combinându-le, se poate obține practic orice subformat ISO 8601.

Combinații principale de opțiuni

  • .withFullDate — doar data: 2024-07-21. Pentru parsarea șirurilor de tip YYYY-MM-DD
  • .withFullDate + .withTime — dată și timp fără fus orar: 2024-07-21T14:30:00
  • .withInternetDateTime — format complet: 2024-07-21T14:30:00Z sau 2024-07-21T14:30:00+03:00
  • .withInternetDateTime + .withFractionalSeconds — cu fracțiuni de secundă: 2024-07-21T14:30:00.123456+00:00
  • .withFullDate + .withTime + .withTimeZone — format complet fără două puncte în tz: 2024-07-21T14:30:00+0300

Nuanță importantă: .withFractionalSeconds și .withMilliseconds se exclud reciproc — dacă ambele sunt setate, se aplică .withFractionalSeconds. Pentru parsarea milisecundelor din datele serverului, se recomandă .withFractionalSeconds, deoarece multe servere trimit fracțiuni de secundă cu trei, șase sau nouă caractere, iar .withFractionalSeconds gestionează orice lungime.

swift
import Foundation

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

// Diferite combinații de opțiuni de format
formatter.formatOptions = [.withFullDate]
let dateOnly = formatter.string(from: Date())
print("Data: \(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("Complet: \(full)")

// Parsează șirul cu milisecunde
let serverString = "2024-07-21T14:30:00.123456+03:00"
if let parsed = formatter.date(from: serverString) {
    print("Parsat: \(parsed)")
}

ISO8601DateFormatter în Swift: exemple de cod

Utilizarea de bază a ISO8601DateFormatter se reduce la crearea unei instanțe, setarea timeZone (se recomandă UTC pentru datele serverului) și formatOptions, după care se poate apela string(from:) pentru formatare și date(from:) pentru parsare. Spre deosebire de DateFormatter, nu trebuie să vă faceți griji despre Locale — clasa ignoră setările regionale.

swift
import Foundation

let formatter = ISO8601DateFormatter()

// Parsează diferite formate ISO 8601
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("Parsat '\(str)': \(autoParsed)")
    } else {
        // Folosește withFullDate pentru șiruri doar cu dată
        formatter.formatOptions = [.withFullDate]
        if let fallback = formatter.date(from: str) {
            print("Fallback parsat '\(str)': \(fallback)")
        }
        formatter.formatOptions = [.withInternetDateTime]
    }
}

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

Parsarea datelor cu secunde fracționare de lungime variabilă — caracteristica multor API-uri moderne. Serverul poate trimite atât 2024-07-21T14:30:00.123Z (3 caractere), cât și 2024-07-21T14:30:00.123456Z (6 caractere). ISO8601DateFormatter cu opțiunea .withFractionalSeconds va gestiona corect ambele variante, în timp ce DateFormatter cu dateFormat = „yyyy-MM-dd’T’HH:mm:ss.SSSZ” va procesa doar milisecunde cu trei cifre.

swift
import Foundation

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

// Diferite precizii de secunde fracționare
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)")
    }
}

// Folosește withMilliseconds (doar 3 cifre)
variantFormatter.formatOptions = [
    .withInternetDateTime,
    .withMilliseconds
]
let milliParsed = variantFormatter.string(from: Date())
print("Cu milisecunde: \(milliParsed)")

Testarea parsării tuturor variantelor: codul de mai sus demonstrează că ISO8601DateFormatter cu .withFractionalSeconds procesează cu succes fracțiuni de secundă de orice lungime de la 1 la 9 caractere. Acest lucru este important pentru compatibilitatea cu diferite platforme server: .NET generează adesea 7 caractere (ticuri de 100 de nanosecunde), Python — 6, Java — 3 sau 9 în funcție de versiune.

Comparație cu DateFormatter pentru ISO 8601

DateFormatter poate de asemenea să parseze ISO 8601, dar necesită setarea manuală a dateFormat, locale și timeZone. Problema principală este că DateFormatter depinde de Locale, iar dacă nu se setează en_US_POSIX, parsarea se poate strica la utilizatorii din regiuni cu formate de dată non-standard. ISO8601DateFormatter rezolvă această problemă la nivel de arhitectură: nu folosește Locale.

ParametruISO8601DateFormatterDateFormatter
Configurare LocaleNu este necesară (ignoră)en_US_POSIX obligatoriu
DateFormatAutomat (prin opțiuni)Șir format manual
Secunde fracționareOrice precizie (.withFractionalSeconds)SSS fix
Sufix ZGestionează corectPrin dateFormat
PerformanțăMai mare (specializat)Mai mică (general)
StandardDoar ISO 8601Orice format
Versiune iOSiOS 10+iOS 2+

Când să folosiți DateFormatter: dacă trebuie să formatați o dată într-un format non-ISO 8601 (de exemplu, „21 iulie 2024” pentru UI) sau dacă este necesară suportarea iOS 9 și mai vechi. Pentru toate sarcinile de schimb de date cu serverul, folosiți ISO8601DateFormatter — este mai sigur, mai performant și necesită mai puțin cod. DateFormatter pentru ISO 8601 este o sursă de potențiale bug-uri legate de locale și setări regionale.

Migrarea de la DateFormatter la ISO8601DateFormatter: înlocuiți crearea DateFormatter + setarea dateFormat + locale + timeZone cu crearea ISO8601DateFormatter + setarea formatOptions + timeZone. Parsarea șirului rămâne neschimbată prin date(from:). Pentru compatibilitate inversă, puteți folosi #available(iOS 10, *) cu fallback pe DateFormatter.

Erori tipice la parsarea ISO 8601

Setarea uitată a formatOptions face ca formatter-ul să folosească valoarea implicită — .withInternetDateTime. Dacă serverul trimite doar data fără timp (2024-07-21), parsarea va returna nil. Verificați întotdeauna că formatOptions acoperă toate formatele posibile care pot veni de la server. Pentru API-uri cu formate variabile, folosiți încercări de fallback cu diferite combinații de opțiuni.

Confuzia între withMilliseconds și withFractionalSeconds — o eroare frecventă la parsarea datelor cu fracțiuni de secundă. withMilliseconds așteaptă exact 3 cifre zecimale. Dacă serverul trimite 6 cifre (microsecunde), parsarea cu withMilliseconds va eșua. Folosiți .withFractionalSeconds pentru compatibilitate cu orice număr de caractere. .withFractionalSeconds a apărut în iOS 13; pentru versiunile mai vechi, folosiți DateFormatter cu dateFormat.

Ignorarea fusului orar — o altă problemă frecventă. Dacă serverul trimite data cu un fus orar (+03:00), iar formatter-ul este setat la UTC, parsarea nu va eșua, dar rezultatul va fi în UTC. Dezvoltatorii se așteaptă adesea ca Date să păstreze fusul orar, dar Date este un moment absolut în timp și nu stochează informații despre fusul orar. Pentru afișarea corectă, salvați fusul orar separat sau folosiți ISO8601DateFormatter cu timeZone corect.

Conform Apple Forum (2024), aproximativ 20% din întrebările referitoare la ISO8601DateFormatter sunt legate de formatul în care secundele sunt opționale. Standardul ISO 8601 permite formatul fără secunde: 2024-07-21T14:30+03:00. ISO8601DateFormatter cu .withInternetDateTime nu suportă acest format — pentru parsarea lui este necesar DateFormatter cu dateFormat = „yyyy-MM-dd’T’HH:mmZ”. Această limitare trebuie luată în considerare atunci când lucrați cu API-uri care folosesc formatul scurtat de timp.

Întrebări frecvente

Ce este ISO8601DateFormatter?

ISO8601DateFormatter — o clasă Foundation specializată pentru formatarea și parsarea datelor în format ISO 8601, disponibilă de la iOS 10. Procesează automat formatele standard fără setarea manuală a dateFormat.

Cu ce diferă ISO8601DateFormatter de DateFormatter?

ISO8601DateFormatter nu depinde de Locale, folosește opțiuni în loc de dateFormat și gestionează corect fracțiuni de secundă de orice lungime. DateFormatter este universal, dar necesită configurare manuală și este susceptibil la bug-uri legate de setările regionale.

Cum să gestionăm fracțiunile de secundă de lungime variabilă?

Folosiți opțiunea .withFractionalSeconds — suportă de la 1 la 9 caractere zecimale. Nu folosiți .withMilliseconds dacă precizia poate varia. .withFractionalSeconds este disponibil din iOS 13.

Ce fus orar folosește ISO8601DateFormatter?

Implicit UTC. Pentru a-l schimba, setați proprietatea timeZone. Dacă timeZone = nil, se folosește timpul local al dispozitivului. La parsarea unui șir cu un fus orar explicit în format +HH:MM, formatter-ul îl ia în considerare automat.

De ce parsarea unei date fără timp returnează nil?

Pentru că formatOptions implicit = .withInternetDateTime, care așteaptă dată + timp + fus orar. Pentru parsarea doar a datei, setați formatOptions = [.withFullDate]. Pentru a suporta ambele variante, folosiți fallback cu opțiuni diferite.

Rezumat

  • ISO8601DateFormatter — clasă specializată pentru ISO 8601, mai sigură și mai simplă decât DateFormatter
  • Opțiunile de format înlocuiesc dateFormat manual — combinați .withFullDate, .withTime, .withTimeZone
  • Nu depinde de Locale — parsarea funcționează la fel pe toate dispozitivele fără configurarea locale
  • .withFractionalSeconds gestionează fracțiuni de secundă de orice precizie (1–9 caractere)
  • DateFormatter pierde în performanță, siguranță și simplitate pentru sarcinile ISO 8601
  • Confuzia opțiunilor — withMilliseconds și withFractionalSeconds nu sunt interschimbabile
  • Formatul fără secunde (2024-07-21T14:30+03:00) nu este suportat — necesită DateFormatter

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și