TimeZone est une classe Foundation dans iOS et macOS qui abstrait les informations sur les fuseaux horaires pour une conversion correcte de l’heure entre les régions géographiques. Selon Apple Developer Documentation, 2024, TimeZone fournit des méthodes pour travailler avec les identifiants de fuseaux horaires (IANA Time Zone Database), les décalages par rapport à UTC et les règles de passage à l’heure d’été. La classe est intégrée avec DateFormatter et Calendar, assurant l’application automatique du bon fuseau horaire lors du formatage des dates. Contrairement au calcul manuel du décalage, TimeZone met automatiquement à jour les données lorsque le fuseau horaire de l’appareil change.
Points clés
TimeZone est un type valeur en Swift qui fournit des informations sur un fuseau horaire géographique : décalage UTC, nom, abréviation et règles d’heure d’été. En Objective-C, la classe s’appelle NSTimeZone. Les deux classes reposent sur la IANA Time Zone Database (également connue sous le nom de base de données Olson), qui contient l’historique des changements de fuseaux horaires depuis 1970.
Chaque instance TimeZone stocke un identifiant de fuseau horaire (par exemple, Europe/Moscow), le décalage actuel en secondes par rapport à UTC, le drapeau isDaylightSavingTime et la date de la prochaine transition. L’identifiant est la clé primaire : lors de l’initialisation TimeZone(identifier:), le système charge l’enregistrement correspondant depuis la base de données des fuseaux horaires de l’appareil.
Selon IANA (2024), la base de données contient plus de 600 identifiants uniques de fuseaux horaires. Apple fournit un instantané de cette base de données avec chaque version d’iOS et macOS, garantissant des calculs cohérents sur tous les appareils sans nécessité de requêtes réseau.
Architecture de TimeZone dans Foundation est construite sur un système à deux niveaux : l’identifiant de fuseau horaire (nom lisible) et sa représentation numérique (décalage UTC). Le système sélectionne automatiquement le fuseau horaire actuel à partir des paramètres de l’appareil, mais le développeur peut le remplacer pour des opérations de formatage spécifiques.
TimeZone est étroitement lié à Calendar et DateFormatter. Lors du formatage d’une date, DateFormatter utilise la propriété timeZone d’une instance TimeZone pour convertir un moment absolu dans le temps (Date) en une représentation chaîne dans le fuseau horaire souhaité. Si timeZone n’est pas défini, le fuseau horaire système par défaut est utilisé — TimeZone.current.
| Type | Initialisation | Caractéristiques |
|---|---|---|
| Actuel | TimeZone.current | Se met à jour automatiquement lors du changement de région dans les réglages, suit l’heure d’été |
| Fixe | TimeZone(identifier:) | Indépendant de la région de l’appareil. Applique constamment l’identifiant sélectionné |
| UTC | TimeZone(secondsFromGMT: 0) | Fuseau horaire sans correction. Identifiant : GMT |
| Avec décalage arbitraire | TimeZone(secondsFromGMT: 10800) | Décalage fixe en secondes. Ne tient pas compte de l’heure d’été |
Note importante : TimeZone(identifier:) retourne nil pour les identifiants inconnus. C’est une cause fréquente de plantage d’application — les développeurs oublient de traiter la valeur optionnelle lors du passage d’un identifiant invalide depuis une saisie utilisateur. Pour les identifiants IANA, la casse est importante : Europe/Moscow est valide, europe/moscow retourne nil.
La IANA Time Zone Database utilise le format « Région/Ville » (Continent/Ville), où la région est l’un des continents (Africa, America, Asia, Atlantic, Australia, Europe, Indian, Pacific) ou un océan, et la ville est la localité la plus peuplée dans la zone de couverture du fuseau horaire. Ce format garantit l’unicité et la lisibilité de l’identifiant.
En plus du format principal, TimeZone prend en charge trois méthodes d’identification supplémentaires : les abréviations (MSK, EST, PST), les codes à trois lettres des fuseaux horaires (GMT, UTC) et les décalages numériques (+0300, -0500). Cependant, les abréviations sont ambiguës : EST peut signifier Eastern Standard Time (GMT-5) ou Eastern Summer Time (GMT+10) en Australie. Apple recommande d’utiliser exclusivement les identifiants IANA.
import Foundation
// Obtenir tous les identifiants de fuseaux horaires connus
let allIdentifiers: [String] = TimeZone.knownTimeZoneIdentifiers
print("Total des fuseaux horaires : \(allIdentifiers.count)")
// Filtrer par région
let europeZones = allIdentifiers.filter { $0.hasPrefix("Europe/") }
print("Fuseaux horaires européens : \(europeZones)")
// Abréviations (non recommandé pour la production)
if let moscowTimeZone = TimeZone(abbreviation: "MSK") {
print("Secondes MSK depuis GMT : \(moscowTimeZone.secondsFromGMT())")
}
// Trouver un identifiant par décalage
let utcPlus3 = TimeZone(secondsFromGMT: 10800)
print("Identifiant : \(utcPlus3.identifier)")
Abréviations dans TimeZone.abbreviationDictionary contiennent les abréviations de tous les fuseaux horaires connus, mais ce dictionnaire ne garantit pas l’unicité : la clé PST peut correspondre à America/Los_Angeles ou à Pacific/Pago_Pago. Pour le code de production, utilisez toujours les identifiants IANA.
TimeZone tient automatiquement compte des passages à l’heure d’été (DST) pour toutes les régions où elle est observée. Le système utilise les données historiques de la IANA Time Zone Database, qui incluent les dates précises de transition pour chaque fuseau horaire. La propriété isDaylightSavingTime retourne true si le fuseau horaire est actuellement en heure d’été.
La méthode nextDaylightSavingTimeTransition permet de connaître la date de la prochaine transition, utile pour planifier des événements futurs. Cette fonctionnalité est particulièrement importante pour les régions aux changements fréquents de règles DST, comme le Brésil ou le Maroc — jusqu’en 2024, le Brésil changeait les dates de transition chaque année, et le calcul manuel entraînait des erreurs dans les applications.
Selon Apple WWDC 2023, la bibliothèque ICU (International Components for Unicode), qui sous-tend Foundation, met à jour les données DST à chaque mise à jour d’iOS. Les applications ne doivent pas mettre en cache les données d’heure d’été plus d’un jour après une mise à jour système — la base de données IANA peut changer même sans mise à jour de la version de l’OS via des ajustements de fuseaux horaires.
import Foundation
// Vérifier DST pour Europe/Moscow
let moscow = TimeZone(identifier: "Europe/Moscow")!
let now = Date()
let isMoscowDST = moscow.isDaylightSavingTime(for: now)
print("Moscou actuellement en DST : \(isMoscowDST)")
// Obtenir la date de la prochaine transition DST
if let nextTransition = moscow.nextDaylightSavingTimeTransition(
after: now
) {
let dstOffset = moscow.daylightSavingTimeOffset(
for: nextTransition
)
print("Prochaine transition : \(nextTransition), décalage DST : \(dstOffset)s")
}
// Conversion sécurisée avec connaissance de DST
let newYork = TimeZone(identifier: "America/New_York")!
let offsetNY = newYork.secondsFromGMT(for: now)
print("Décalage actuel de NY : \(offsetNY / 3600)h")
Nuance critique : secondsFromGMT(for:) tient compte de DST pour la date spécifiée, tandis que secondsFromGMT() ne s’applique qu’à l’heure actuelle. Lors du formatage de dates historiques, utilisez toujours la version avec le paramètre Date : secondsFromGMT(for: someHistoricalDate). La différence peut atteindre 1 à 2 heures, ce qui est critique pour les logs ou les données historiques.
Formater une date avec un fuseau horaire spécifique est la tâche la plus courante avec TimeZone. DateFormatter utilise la propriété timeZone pour convertir un Date en chaîne. Si timeZone n’est pas défini explicitement, le formateur utilise TimeZone.current — le fuseau horaire défini sur l’appareil de l’utilisateur, ce qui peut donner des résultats inattendus pour les données serveur.
import Foundation
// Formater la date dans un fuseau horaire spécifique
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let tokyo = TimeZone(identifier: "Asia/Tokyo")!
formatter.timeZone = tokyo
let tokyoTime = formatter.string(from: Date())
print("Heure de Tokyo : \(tokyoTime)")
// Identifiants disponibles pour la sélection utilisateur
let displayNames: [(String, String)] = TimeZone.knownTimeZoneIdentifiers
.prefix(20)
.map { ($0, TimeZone(identifier: $0)!.localizedName(
for: .generic, locale: .current
)) }
// Comparer deux fuseaux horaires
let london = TimeZone(identifier: "Europe/London")!
let difference = tokyo.secondsFromGMT(for: Date())
- london.secondsFromGMT(for: Date())
print("Différence Tokyo-Londres : \(difference / 3600)h")
// Travailler avec le dictionnaire d’abréviations
let knownAbbrevs = TimeZone.abbreviationDictionary
for (abbr, ident) in knownAbbrevs.sorted(by: { $0.key < $1.key }).prefix(5) {
print("\(abbr) -> \(ident)")
}
Nom localisé d’un fuseau horaire via localizedName(for:locale:) retourne un nom lisible dans la langue spécifiée. Par exemple, pour Europe/Moscow avec les paramètres régionaux russes, la méthode retourne le nom russe « Moskva », et avec les paramètres régionaux anglais — « Moscow Time ». Styles disponibles : .standard (nom standard), .daylightSaving (heure d’été) et .shortGeneric (court).
import Foundation
let paris = TimeZone(identifier: "Europe/Paris")!
let nameRU = paris.localizedName(
for: .standard,
locale: Locale(identifier: "ru_RU")
)
print("Nom en russe : \(nameRU)")
// Vérifier si la région est dans le même jour
let isSameDay = Calendar.current.isDate(
Date(),
equalTo: Date(),
toGranularity: .day
)
print("Même jour dans différents fuseaux horaires : \(isSameDay)")
Sérialisation de l’identifiant de fuseau horaire est la meilleure pratique pour stocker TimeZone dans des bases de données ou UserDefaults. Enregistrez l’identifiant (une chaîne comme Europe/Moscow), pas le décalage en secondes ni une abréviation. Le décalage peut changer avec les modifications DST, et les abréviations sont ambiguës. Restauration : TimeZone(identifier: savedString).
Utiliser un décalage fixe au lieu d’un identifiant de fuseau horaire est l’erreur la plus fréquente. TimeZone(secondsFromGMT: 10800) ne tient pas compte de DST, donc pour Europe/Moscow en été, cette construction donne un décalage incorrect d’une heure. Utilisez toujours l’identifiant IANA pour les régions avec heure d’été.
Gestion de nil oubliée lors de l’initialisation de TimeZone(identifier:) est la deuxième erreur la plus fréquente. Si un utilisateur saisit un identifiant incorrect (par exemple, « moscow » au lieu de « Europe/Moscow »), le constructeur retourne nil. Sans gestion de la valeur optionnelle, l’application plante avec une erreur d’exécution. Utilisez guard let ou TimeZone(identifier:) avec un fallback connu.
Ignorer DST lors du travail avec des dates futures. TimeZone.secondsFromGMT(for:) est la seule façon correcte d’obtenir le décalage pour une date spécifique. Utiliser secondsFromGMT() sans paramètre pour des dates historiques ou futures donne le décalage pour le moment actuel, qui peut ne pas correspondre au décalage réel à la date spécifiée, en particulier pour les régions qui ont aboli ou introduit DST.
Selon Stack Overflow (2024), environ 15 % des questions sur DateFormatter concernent une configuration incorrecte de timeZone. Scénario typique : le serveur envoie une date en UTC, le développeur la formate sans définir le timeZone du formateur, et la date s’affiche dans le fuseau horaire de l’appareil, créant une confusion chez les utilisateurs de différentes régions. Règle : définissez toujours explicitement le timeZone du formateur pour les données serveur.
Foire aux questions
TimeZone est une classe Foundation pour travailler avec les fuseaux horaires dans iOS et macOS. Elle fournit des informations sur le décalage UTC, les règles d’heure d’été et les identifiants de fuseaux horaires basés sur la IANA Time Zone Database.
Trois formats : identifiants IANA (Europe/Moscow), abréviations (MSK, EST) et décalages numériques (+0300). Apple recommande d’utiliser les identifiants IANA comme seul format non ambigu pour le code de production.
Automatiquement via les méthodes secondsFromGMT(for:) et isDaylightSavingTime(for:). TimeZone utilise les données historiques IANA, mises à jour à chaque version d’iOS, garantissant des transitions DST correctes pour toute date.
TimeZone.current retourne le fuseau horaire sélectionné par l’utilisateur dans les réglages (peut différer du fuseau géographique). TimeZone.system retourne le fuseau horaire de l’appareil, déterminé automatiquement par géolocalisation et non modifiable par l’utilisateur.
TimeZone.current retourne le fuseau horaire actuel de l’appareil. Pour obtenir l’identifiant, utilisez la propriété identifier : TimeZone.current.identifier. Pour un nom localisé, appelez localizedName(for:locale:).
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