DateFormatter est une classe Foundation conçue pour la conversion bidirectionnelle entre les objets Date et leur représentation en chaîne. La classe prend en compte les paramètres régionaux, le fuseau horaire et le calendrier de l'utilisateur, garantissant un affichage correct des dates dans n'importe quelle région du monde. Selon la documentation développeur Apple (2025), DateFormatter prend en charge quatre styles prédéfinis de date et d'heure, ainsi que des formats entièrement personnalisés via une chaîne de modèle. Sans DateFormatter, il est impossible d'afficher correctement une date à l'utilisateur dans une application internationalisée.
Points clés
DateFormatter est une classe du framework Foundation qui implémente la conversion bidirectionnelle entre Date et chaîne. Elle est apparue pour la première fois dans OpenStep sous le nom de NSDateFormatter et est depuis restée l'outil principal de formatage des dates sur toutes les plateformes Apple. La classe hérite de Formatter et fournit une API pratique pour l'affichage localisé des dates.
DateFormatter fonctionne sur la base de modèles Unicode LDML — les mêmes que ceux utilisés dans ICU (International Components for Unicode). Le modèle est défini via la propriété dateFormat, où les symboles y, M, d, H, m, s correspondent à l'année, au mois, au jour, aux heures, aux minutes, aux secondes. La répétition d'un symbole détermine le format : « y » (année à deux chiffres), « yyyy » (année à quatre chiffres).
Créer un DateFormatter est une opération coûteuse, car les données des paramètres régionaux et du calendrier sont chargées lors de l'initialisation. Apple recommande de créer un formateur une fois pour chaque type de formatage et de le réutiliser. Dans SwiftUI et UIKit, les formateurs sont souvent mis en cache dans des propriétés statiques ou créés paresseusement lors du premier accès.
DateFormatter est utilisé dans de nombreux composants système iOS. UIDatePicker utilise DateFormatter en interne pour afficher les dates en mode countDownTimer. Un TextField avec un formateur peut valider automatiquement les dates saisies par l'utilisateur. Core Data prend en charge les attributs de type Date, mais leur représentation en chaîne est toujours gérée via DateFormatter.
Sécurité des threads — DateFormatter n'est pas thread-safe. La modification des propriétés du formateur à partir de différents threads entraîne un comportement indéfini. Pour une utilisation multi-thread, créez des instances séparées du formateur pour chaque thread ou utilisez la synchronisation via NSLock ou une file d'attente série.
dateStyle et timeStyle sont les moyens les plus simples de configurer l'affichage des dates. Chaque style a quatre variantes : .short, .medium, .long, .full. La combinaison de dateStyle et timeStyle permet une configuration indépendante du format de date et d'heure, et la propriété .none désactive la partie correspondante.
Pour les paramètres régionaux américains, .short formate la date comme « 7/21/26 », et pour les russes comme « 21.07.2026 ». Le style .long pour les paramètres régionaux russes affiche « 21 juillet 2026 », et .full affiche « mardi, 21 juillet 2026 » avec le jour de la semaine. Les quatre styles s'adaptent automatiquement aux normes régionales, y compris l'ordre des composants et les séparateurs.
SFDateFormatter dans iOS 15+ offre une approche alternative via RelativeDateFormatter et DateIntervalFormatter. RelativeDateFormatter affiche « aujourd'hui », « hier », « dans 3 jours » pour un contexte immédiat. DateIntervalFormatter affiche les plages de dates : « 21–25 juillet 2026 » — pour les réservations et la planification.
| Style | Exemple (ru_RU) | Exemple (en_US) |
|---|---|---|
| .short | 21.07.2026 | 7/21/26 |
| .medium | 21 juil. 2026 | Jul 21, 2026 |
| .long | 21 juillet 2026 | July 21, 2026 |
| .full | mardi, 21 juillet 2026 | Tuesday, July 21, 2026 |
Lors de la combinaison des styles, DateFormatter sélectionne automatiquement le séparateur : pour .short.date + .short.time, le résultat pourrait être « 21.07.2026, 14:30 ». Pour .full.date + .full.time — « mardi, 21 juillet 2026, 14:30:00 MSK ». Le séparateur est géré par les paramètres régionaux, pas par le développeur — cela garantit la conformité avec les attentes régionales de l'utilisateur.
dateFormat permet de définir un motif de formatage arbitraire à l'aide de symboles de spécification Unicode LDML. Cela donne un contrôle total sur l'affichage : vous pouvez afficher uniquement l'année et le mois, ou le jour de la semaine sans la date, ou l'heure sans les secondes. Le format personnalisé est indispensable pour des exigences de conception spécifiques.
Symboles principaux — yyyy (année : 2026), MM (mois : 07), dd (jour : 21), HH (heures : 14), mm (minutes : 30), ss (secondes : 00). Pour le nom complet du mois, utilisez MMMM (juillet), pour l'abrégé — MMM (juil.). Jour de la semaine — EEEE (mardi), abrégé — E (mar.).
Lors de l'utilisation de dateFormat, il est important de définir les paramètres régionaux du formateur. Si les paramètres régionaux ne sont pas définis, le formateur utilise les paramètres régionaux du système, ce qui peut être indésirable pour un format fixe dans une API. Apple recommande de définir locale = Locale(identifier: « en_US_POSIX ») pour un format fixe inter-régional, en particulier lors de l'analyse des dates provenant des réponses du serveur.
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.dateFormat = "d MMMM yyyy"
let customString = formatter.string(from: Date())
// "21 July 2026"
// Analyse d'une chaîne personnalisée
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = formatter.date(from: "2026-07-21 14:30:00")!
Une erreur dans dateFormat est l'une des causes courantes de plantage de l'application. Si le format ne correspond pas à la chaîne, la méthode date(from:) renvoie nil. Utilisez guard let ou ?? pour le déballage sécurisé des optionnels. Pour valider le format, testez-le dans toutes les langues prises en charge — certains symboles LDML fonctionnent différemment selon les paramètres régionaux.
Locale détermine comment les noms des mois, des jours de la semaine et les séparateurs sont affichés. DateFormatter utilise Locale.current par défaut, mais dans certains scénarios, des paramètres régionaux spécifiques doivent être spécifiés : pour un format fixe dans les journaux, utilisez en_US_POSIX, pour les dates du serveur — les paramètres régionaux correspondant au serveur.
La propriété TimeZone détermine le fuseau horaire pour l'affichage. Par défaut, le fuseau horaire du système est utilisé, mais pour les applications avec un public international, il est souvent nécessaire d'afficher les dates dans le fuseau horaire de l'utilisateur ou en UTC. La modification de timeZone n'affecte que l'affichage — la valeur Date reste inchangée.
Une caractéristique importante : si DateFormatter est utilisé pour analyser une chaîne et que la chaîne contient une indication de fuseau horaire (par exemple, « 2026-07-21T14:30:00Z » avec Z pour UTC), la propriété timeZone est ignorée — le formateur utilise le fuseau horaire de la chaîne. Si le fuseau horaire est absent de la chaîne, le timeZone du formateur est appliqué.
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 July 2026, 14:30"
// Analyse sans fuseau horaire dans la chaîne
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd HH:mm"
let utcDate = formatter.date(from: "2026-07-21 10:30")!
AutoupdatingCurrentLocale — un type spécial de paramètres régionaux qui se met automatiquement à jour lorsque les paramètres système de l'utilisateur changent. DateFormatter le prend en charge par défaut. Si l'application s'exécute en arrière-plan et que l'utilisateur change la langue du système, un formateur créé avant le changement continuera d'utiliser les anciens paramètres régionaux — pour le mettre à jour, une nouvelle instance doit être créée.
ISO8601DateFormatter est un formateur spécialisé pour travailler avec des dates au format ISO 8601. Ce format est le standard de facto pour les API REST, JSON et l'échange de données. ISO8601DateFormatter fonctionne beaucoup plus rapidement que DateFormatter car il ne dépend pas des paramètres régionaux et utilise une grammaire d'analyse fixe.
Options principales du formateur — .withInternetDateTime (2026-07-21T14:30:00Z), .withFractionalSeconds (ajoute des millisecondes), .withTimeZone (inclut le décalage horaire). En combinant les options, vous pouvez obtenir n'importe quelle variante ISO 8601 : avec millisecondes, avec fuseau horaire, avec date uniquement.
JSONEncoder.DateEncodingStrategy permet de configurer globalement l'encodage des dates pour tous les modèles Codable. Options — .iso8601 (utilise ISO8601DateFormatter), .formatted(DateFormatter), .millisecondsSince1970, .secondsSince1970. Le choix de la stratégie affecte l'ensemble du cycle de vie de la sérialisation et doit être cohérent sur tous les points de terminaison de l'API.
// ISO8601DateFormatter
let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let isoString = isoFormatter.string(from: Date())
// "2026-07-21T14:30:00.000Z"
// JSONEncoder avec ISO8601
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
// Alternative : JSONEncoder avec formateur personnalisé
let customEncoder = JSONEncoder()
customEncoder.dateEncodingStrategy = .formatted(myFormatter)
DateFormatter vs ISO8601DateFormatter — choisissez ISO8601DateFormatter pour sérialiser et analyser les dates dans l'API, car il est 5 à 10 fois plus rapide que DateFormatter et n'est pas sujet aux erreurs de localisation. Utilisez DateFormatter pour l'interface utilisateur où un affichage localisé avec les noms des mois et des jours dans la langue maternelle de l'utilisateur est requis.
Examinons des scénarios réels d'utilisation de DateFormatter dans une application iOS : affichage dans un fil d'actualités, saisie d'une date de naissance et exportation d'un rapport avec des dates dans différents fuseaux horaires.
RelativeDateFormatter est optimal pour les fils d'actualités. Il affiche « à l'instant », « il y a 5 minutes », « hier » pour les actualités récentes et passe à la date complète pour les anciennes. Le seuil de basculement est configuré via le calendrier : pour les actualités, utilisez un seuil de 24 heures, pour les messageries — une semaine.
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)
}
Saisie d'une date de naissance — un autre scénario courant. DateFormatter est configuré avec un dateFormat spécifique « dd.MM.yyyy » et locale « ru_RU ». Lors de l'analyse de la chaîne saisie, il est important de gérer les erreurs potentielles : le formateur renvoie nil pour une chaîne invalide. Après une analyse réussie, la date est vérifiée pour être dans une plage acceptable — pas avant 1900, pas après aujourd'hui.
Exportation d'un rapport avec des dates nécessite un format fixe indépendant des paramètres régionaux de l'utilisateur. Utilisez dateFormat « yyyy-MM-dd HH:mm:ss » avec locale en_US_POSIX et fuseau horaire UTC. Cette approche garantit que le fichier s'ouvrira correctement dans n'importe quel pays, indépendamment des paramètres régionaux du système.
| Scénario | Formateur | Configuration clé |
|---|---|---|
| Fil d'actualités | RelativeDateFormatter | unitsStyle = .full |
| Saisie de date | DateFormatter | dateFormat + secours |
| Sérialisation API | ISO8601DateFormatter | withInternetDateTime |
| Exportation de rapport | DateFormatter | en_US_POSIX + UTC |
Foire aux questions
La raison la plus courante — une inadéquation entre dateFormat et le format de la chaîne. Par exemple, le format « dd.MM.yyyy » n'analysera pas la chaîne « 2026-07-21 ». La deuxième raison — une inadéquation des paramètres régionaux : la chaîne « July 21, 2026 » ne sera pas analysée avec les paramètres régionaux ru_RU. La troisième — des fautes de frappe dans les symboles LDML : utilisez yyyy, pas YYYY (signification différente).
Non. DateFormatter est un objet lourd, son initialisation inclut le chargement des données des paramètres régionaux. Créez une instance par type de formatage et réutilisez-la. Dans un environnement multi-thread, utilisez le stockage local de thread ou un pool de formateurs avec une file d'attente série pour la synchronisation.
DateFormatter affiche une date absolue (21 juillet 2026), tandis que RelativeDateFormatter affiche une date relative (aujourd'hui, hier, dans 3 jours). RelativeDateFormatter a été introduit dans iOS 15+ et utilise le même modèle LDML mais sélectionne automatiquement l'affichage relatif.
Définissez le timeZone du formateur sur UTC avant l'analyse. Si le serveur renvoie une date en heure locale sans indication de fuseau horaire, vérifiez la spécification de l'API — très probablement, UTC est implicite. Pour ISO 8601 avec Z à la fin, timeZone n'est pas nécessaire — le formateur analyse le décalage à partir de la chaîne.
N'utilisez pas une seule instance à partir de différents threads sans synchronisation. Créez une nouvelle instance dans chaque thread ou utilisez Thread.current.threadDictionary pour le stockage. Une alternative est NSLock avec verrouillage pendant la durée de string(from:) et date(from:).
Résumé
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.
Lisez aussi