ISO8601DateFormatter : concepts clés et formatage ISO 8601

Auteur : IT Sectr Publié le : 2026-07-13 Temps de lecture : 9 min

ISO8601DateFormatter est une classe Foundation dans iOS et macOS conçue pour formater et analyser les dates selon la norme internationale ISO 8601. Selon Apple Developer Documentation, 2024, ISO8601DateFormatter gère automatiquement les formats avec millisecondes, fuseaux horaires et fractions de seconde sans avoir à définir DateFormat manuellement. Contrairement à DateFormatter, cette classe ne dépend pas de Locale ni de TimeZone — elle fonctionne strictement selon la spécification ISO 8601, ce qui la rend idéale pour l'échange de dates entre serveur et client. La classe est disponible depuis iOS 10 et macOS 10.12.

Points clés

  • ISO8601DateFormatter — classe Foundation pour formater les dates selon la norme ISO 8601
  • Ne nécessite pas DateFormat — le format est déterminé automatiquement par les réglages d'options
  • Indépendant de la locale — fonctionne à l'identique sur tous les appareils sans configuration Locale
  • Prise en charge des millisecondes — gère les fractions de seconde de toute précision (trois, six chiffres ou plus)
  • Options de formatage — withFullDate, withTime, withMilliseconds, withTimeZone et autres contrôlent les composants de sortie

Qu'est-ce que ISO8601DateFormatter ?

ISO8601DateFormatter est une sous-classe spécialisée de Formatter dans Foundation qui implémente la conversion bidirectionnelle entre Date et les chaînes au format ISO 8601. La norme ISO 8601 (International Standard for the Representation of Dates and Times) définit un format international pour l'échange de dates et d'heures : 2024-07-21T14:30:00+00:00. Contrairement à DateFormatter, cette classe ne nécessite pas de spécifier dateFormat et détermine automatiquement la structure de la chaîne en fonction des options fournies.

Les principaux avantages de ISO8601DateFormatter par rapport à DateFormatter : absence de dépendance à la locale (l'analyse fonctionne à l'identique sur tout appareil), prise en charge intégrée des fractions de seconde (avec n'importe quel nombre de décimales) et détection automatique du format basée sur les options passées. La classe gère également correctement le suffixe Z (désignation UTC), les fuseaux horaires au format +HH:mm et la précision réduite (date seule sans heure).

Selon la Spécification ISO (ISO 8601-1:2019), la norme prend en charge quatre niveaux de précision : année (2024), année-mois (2024-07), date complète (2024-07-21) et date-heure avec fuseau horaire (2024-07-21T14:30:00+00:00). ISO8601DateFormatter couvre tous ces niveaux grâce à une combinaison d'options de format, libérant le développeur de la construction manuelle de chaînes dateFormat.

Comment fonctionne ISO8601DateFormatter dans Foundation ?

Le principe de fonctionnement de ISO8601DateFormatter est basé sur une combinaison d'options binaires (formatOptions), dont chacune inclut un composant spécifique de date ou d'heure dans la sortie. Par exemple, l'option .withFullDate inclut l'année, le mois et le jour ; .withTime inclut les heures, les minutes et les secondes. En combinant les options, le développeur obtient le niveau de précision souhaité sans écrire de chaîne dateFormat.

En interne, ISO8601DateFormatter utilise la bibliothèque ICU pour l'analyse, mais avec des règles ISO 8601 fixes. Cela signifie qu'il ignore les paramètres Locale et TimeZone de l'appareil — le résultat est toujours prévisible. Pour définir le fuseau horaire, on utilise la propriété timeZone, dont la valeur par défaut est UTC. Si timeZone est défini sur nil, l'heure locale de l'appareil est utilisée.

OptionDescriptionExemple de sortie
.withFullDateAnnée, mois, jour2024-07-21
.withTimeHeures, minutes, secondes14:30:00
.withMillisecondsFractions de seconde (jusqu'à 3 chiffres).123
.withFractionalSecondsFractions de seconde (toute précision).123456
.withTimeZoneFuseau horaire+03:00
.withColonSeparatorInTimeZoneSéparateur deux-points dans le fuseau horaire+03:00 (contre +0300)
.withInternetDateTimeFormat complet (date + heure + fuseau)2024-07-21T14:30:00+00:00

Combinaison d'options : .withInternetDateTime équivaut à combiner .withFullDate, .withTime et .withTimeZone. Pour analyser des chaînes avec millisecondes, ajoutez .withFractionalSeconds. Il est important de se rappeler que .withMilliseconds limite les fractions de seconde à trois chiffres, tandis que .withFractionalSeconds prend en charge toute précision — d'un à neuf chiffres après la virgule décimale.

Options de format ISO 8601

Les options de format de ISO8601DateFormatter sont divisées en trois groupes : composants de date (withFullDate, withYear, withMonth, withDay, withWeekOfYear), composants d'heure (withTime, withHours, withMinutes, withSeconds) et paramètres supplémentaires (withMilliseconds, withFractionalSeconds, withTimeZone, withColonSeparatorInTimeZone, withDashSeparatorInDate, withFullTime). En les combinant, vous pouvez obtenir pratiquement n'importe quel sous-format ISO 8601.

Combinaisons principales d'options

  • .withFullDate — date uniquement : 2024-07-21. Pour analyser les chaînes YYYY-MM-DD
  • .withFullDate + .withTime — date et heure sans fuseau horaire : 2024-07-21T14:30:00
  • .withInternetDateTime — format complet : 2024-07-21T14:30:00Z ou 2024-07-21T14:30:00+03:00
  • .withInternetDateTime + .withFractionalSeconds — avec fractions de seconde : 2024-07-21T14:30:00.123456+00:00
  • .withFullDate + .withTime + .withTimeZone — format complet sans deux-points dans tz : 2024-07-21T14:30:00+0300

Nuance importante : .withFractionalSeconds et .withMilliseconds sont mutuellement exclusifs — si les deux sont définis, .withFractionalSeconds s'applique. Pour analyser les millisecondes des données serveur, .withFractionalSeconds est recommandé, car de nombreux serveurs envoient des fractions de seconde avec trois, six ou neuf chiffres, et .withFractionalSeconds gère n'importe quelle longueur.

swift
import Foundation

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

// Different format option combinations
formatter.formatOptions = [.withFullDate]
let dateOnly = formatter.string(from: Date())
print("Date: \(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("Full: \(full)")

// Parse string with milliseconds
let serverString = "2024-07-21T14:30:00.123456+03:00"
if let parsed = formatter.date(from: serverString) {
    print("Parsed: \(parsed)")
}

ISO8601DateFormatter en Swift : exemples de code

Utilisation de base de ISO8601DateFormatter se résume à créer une instance, configurer timeZone (UTC est recommandé pour les données serveur) et formatOptions, après quoi vous pouvez appeler string(from:) pour formater et date(from:) pour analyser. Contrairement à DateFormatter, nul besoin de se soucier de Locale — la classe ignore les paramètres régionaux.

swift
import Foundation

let formatter = ISO8601DateFormatter()

// Parse different ISO 8601 formats
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("Parsed '\(str)': \(autoParsed)")
    } else {
        // Use withFullDate for date-only strings
        formatter.formatOptions = [.withFullDate]
        if let fallback = formatter.date(from: str) {
            print("Fallback parsed '\(str)': \(fallback)")
        }
        formatter.formatOptions = [.withInternetDateTime]
    }
}

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

Analyser les dates avec des fractions de seconde de longueur variable est une caractéristique de nombreuses API modernes. Un serveur peut envoyer soit 2024-07-21T14:30:00.123Z (3 chiffres) soit 2024-07-21T14:30:00.123456Z (6 chiffres). ISO8601DateFormatter avec l'option .withFractionalSeconds gérera correctement les deux, tandis que DateFormatter avec dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" ne gérera que les millisecondes à trois chiffres.

swift
import Foundation

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

// Different fractional second precision
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)")
    }
}

// Use withMilliseconds (3 digits only)
variantFormatter.formatOptions = [
    .withInternetDateTime,
    .withMilliseconds
]
let milliParsed = variantFormatter.string(from: Date())
print("With milliseconds: \(milliParsed)")

Test d'analyse de toutes les variantes : le code présenté démontre que ISO8601DateFormatter avec .withFractionalSeconds gère avec succès les fractions de seconde de n'importe quelle longueur, de 1 à 9 chiffres. Ceci est important pour la compatibilité avec différentes plates-formes serveur : .NET génère souvent 7 chiffres (ticks de 100 nanosecondes), Python — 6, Java — 3 ou 9 selon la version.

Comparaison avec DateFormatter pour ISO 8601

DateFormatter peut également analyser ISO 8601, mais nécessite une configuration manuelle de dateFormat, locale et timeZone. Le problème principal est que DateFormatter dépend de Locale, et si vous ne définissez pas en_US_POSIX, l'analyse peut échouer pour les utilisateurs de régions avec des formats de date non standard. ISO8601DateFormatter résout ce problème au niveau architectural : il n'utilise pas Locale.

ParamètreISO8601DateFormatterDateFormatter
Configuration LocaleNon requise (ignore)en_US_POSIX obligatoire
DateFormatAutomatique (via options)Chaîne de format manuelle
Fractions de secondeToute précision (.withFractionalSeconds)SSS fixe
Suffixe ZGère correctementVia dateFormat
PerformanceSupérieure (spécialisé)Inférieure (général)
NormeISO 8601 uniquementTout format
Version iOSiOS 10+iOS 2+

Quand utiliser DateFormatter : si vous devez formater une date dans un format non ISO 8601 (par exemple, « 21 juillet 2024 » pour l'interface utilisateur) ou si vous devez prendre en charge iOS 9 et versions antérieures. Pour toutes les tâches d'échange de dates entre serveur et client, utilisez ISO8601DateFormatter — c'est plus sûr, plus performant et nécessite moins de code. DateFormatter pour ISO 8601 est une source d'erreurs potentielles liées à la locale et aux paramètres régionaux.

Migration de DateFormatter vers ISO8601DateFormatter : remplacez la création de DateFormatter + configuration de dateFormat + locale + timeZone par la création de ISO8601DateFormatter + configuration de formatOptions + timeZone. L'analyse de la chaîne reste inchangée via date(from:). Pour la rétrocompatibilité, vous pouvez utiliser #available(iOS 10, *) avec un fallback vers DateFormatter.

Erreurs courantes lors de l'analyse ISO 8601

Configuration oubliée de formatOptions fait que le formateur utilise la valeur par défaut — .withInternetDateTime. Si le serveur envoie une date sans heure (2024-07-21), l'analyse retournera nil. Vérifiez toujours que formatOptions couvre tous les formats possibles pouvant provenir du serveur. Pour les API avec des formats variables, utilisez des tentatives de fallback avec différentes combinaisons d'options.

Confusion entre withMilliseconds et withFractionalSeconds est une erreur courante lors de l'analyse de dates avec fractions de seconde. withMilliseconds s'attend à exactement 3 chiffres après la virgule décimale. Si le serveur envoie 6 chiffres (microsecondes), l'analyse avec withMilliseconds échouera. Utilisez .withFractionalSeconds pour la compatibilité avec n'importe quel nombre de chiffres. .withFractionalSeconds est disponible depuis iOS 13 ; pour les versions antérieures, utilisez DateFormatter avec dateFormat.

Ignorer le fuseau horaire est un autre problème courant. Si le serveur envoie une date avec fuseau horaire (+03:00) et que le formateur est réglé sur UTC, l'analyse ne échouera pas, mais le résultat sera en UTC. Les développeurs s'attendent souvent à ce que Date conserve le fuseau horaire, mais Date est un moment absolu dans le temps — il ne stocke pas d'informations de fuseau horaire. Pour un affichage correct, enregistrez le fuseau horaire séparément ou utilisez ISO8601DateFormatter avec le timeZone approprié.

Selon l'Apple Forum (2024), environ 20 % des questions sur ISO8601DateFormatter concernent le format où les secondes sont facultatives. La norme ISO 8601 permet un format sans secondes : 2024-07-21T14:30+03:00. ISO8601DateFormatter avec .withInternetDateTime ne prend pas en charge ce format — pour l'analyser, vous aurez besoin de DateFormatter avec dateFormat = "yyyy-MM-dd'T'HH:mmZ". Cette limitation est importante à prendre en compte lors du travail avec des API utilisant le format horaire abrégé.

Questions fréquentes

Qu'est-ce que ISO8601DateFormatter ?

ISO8601DateFormatter est une classe Foundation spécialisée pour formater et analyser les dates au format ISO 8601, disponible depuis iOS 10. Gère automatiquement les formats standard sans définir manuellement dateFormat.

En quoi ISO8601DateFormatter diffère-t-il de DateFormatter ?

ISO8601DateFormatter ne dépend pas de Locale, utilise des options au lieu de dateFormat et gère correctement les fractions de seconde de n'importe quelle longueur. DateFormatter est universel, mais nécessite une configuration manuelle et est sujet aux erreurs liées aux paramètres régionaux.

Comment gérer les fractions de seconde de longueur variable ?

Utilisez l'option .withFractionalSeconds — elle prend en charge de 1 à 9 chiffres après la virgule décimale. N'utilisez pas .withMilliseconds si la précision peut varier. .withFractionalSeconds est disponible depuis iOS 13.

Quel fuseau horaire utilise ISO8601DateFormatter ?

UTC par défaut. Pour le changer, définissez la propriété timeZone. Si timeZone = nil, l'heure locale de l'appareil est utilisée. Lors de l'analyse d'une chaîne avec un fuseau horaire explicite au format +HH:MM, le formateur en tient compte automatiquement.

Pourquoi l'analyse d'une date sans heure retourne-t-elle nil ?

Parce que formatOptions par défaut est .withInternetDateTime, qui attend date + heure + fuseau horaire. Pour analyser uniquement la date, définissez formatOptions = [.withFullDate]. Pour prendre en charge les deux formats, utilisez un fallback avec différentes options.

Résumé

  • ISO8601DateFormatter — classe spécialisée pour ISO 8601, plus sûre et plus simple que DateFormatter
  • Options de format remplacent le dateFormat manuel — combinez .withFullDate, .withTime, .withTimeZone
  • Indépendant de Locale — l'analyse fonctionne à l'identique sur tous les appareils sans configurer la locale
  • .withFractionalSeconds gère les fractions de seconde de toute précision (1 à 9 chiffres)
  • DateFormatter est inférieur en performances, sécurité et simplicité pour les tâches ISO 8601
  • Confusion d'options — withMilliseconds et withFractionalSeconds ne sont pas interchangeables
  • Format sans secondes (2024-07-21T14:30+03:00) non pris en charge — DateFormatter nécessaire

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi