À l'interne, Swift utilise un nombre de type Double pour représenter une date. Ce nombre correspond aux secondes écoulées entre la date représentée et le 1er janvier 2001 (début du troisième millénaire) dans le fuseau horaire GMT (Greenwich Mean Time).
Par exemple, si une date représente le 8 mai 2024 à 13:52:35 dans le fuseau horaire de Montréal, Swift représentera cette date à l'interne par le nombre 736883555.662463.
Il est à noter que ceci diffère de plusieurs langages, tels que PHP, pour qui la date de référence est le 1er janvier 1970 (époque Unix).
Prenons l'exemple de dates créées ainsi :
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date1String = "2001-01-01 00:00:00"
let date2String = "1970-01-01 00:00:00"
let date1 = dateFormatter.date(from: date1String)! // on sait que la chaîne représente une date au bon format donc ok de mettre le !
let date2 = dateFormatter.date(from: date2String)!
Si on place un point d'arrêt dans le code juste après ces initialisations et qu'on vérifie le contenu des variables date1 et date2, voici ce qu'on obtient.
(lldb) po date1
▿ 2001-01-01 05:00:00 +0000
- timeIntervalSinceReferenceDate : 18000.0
(lldb) po date2
▿ 1970-01-01 05:00:00 +0000
- timeIntervalSinceReferenceDate : -978289200.0
On voit que date1 corresopnd au 1er janvier 2001 à 5h, représenté par le nombre 18000.0. Pourtant, on se serait attendus à avoir la valeur 0.
La différence est due au fuseau horaire. Par défaut, la date créée utilise le fuseau horaire de l'appareil alors que la représentation interne utilise le fuseau horaire GMT. Dans le cas présent, la date a été créée avec le fuseau horaire de Montréal, soit 5 heures (18000 secondes) de différence avec le fuseau GMT.
Ce qu'il faut comprendre, c'est que la représentation interne est toujours à l'heure neutre. C'est le format lisible de la date qui s'ajuste selon le fuseau horaire et ce, autant lors de l'initialisation avec un DateFormatter que lors de l'affichage.
Cette démonstration illustre clairement le fait que la date de référence n'est pas le 1er janvier 1970 puisque la seconde date est représentée par un gros nombre négatif. Une valeur négative représente une date avant la date de référence.
Refaisons l'exercice mais cette fois, en créant la date au fuseau horaire GMT.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
let date3String = "2001-01-01 00:00:00"
let date3 = dateFormatter.date(from: date1String)!
Cette fois, on obtient bel et bien le nombre 0.
(lldb) po date3
▿ 2001-01-01 00:00:00 +0000
- timeIntervalSinceReferenceDate : 0.0
Si vous avez en main la représentation interne d'une date, sans avoir recours à la programmation, il est difficile de décoder quelle date ce nombre représente.
Par exemple, lorsqu'une date est enregistrée dans une base de données à l'aide de SwiftData, c'est sa représentation interne qui est enregistrée.
Pour retrouver une date à partir de sa représentation interne :
let date4 = Date(timeIntervalSinceReferenceDate: 0)
print(date4) // affiche 2001-01-01 00:00:00 +0000, soit la date au fuseau horaire GMT (indiqué par le +0000)
print(dateFormatter.string(from: date4)) // affiche 2000-12-31 19:00:00, soit 5h avant l'heure GMT pour être au fuseau horaire de Montréal
Autre exemple :
let date5 = Date(timeIntervalSinceReferenceDate: 737038273.680801)
print(date5) // affiche 2024-05-10 12:51:13 +0000
print(dateFormatter.string(from: date5)) // affiche 2024-05-10 08:51:13
Inversement, si on a en main une date et qu'on désire voir sa représentation interne, on peut procéder comme suit :
let representationInterne = date3.timeIntervalSinceReferenceDate
print(representationInterne) // affiche 0.0
Swift a prévu un mécanisme pour convertir une date afin qu'elle représente le nombre de secondes entre la date et le 1er janvier 1970.
let conversionDateInterne3 = date3.timeIntervalSince1970
print(conversionDateInterne3) // affiche 978307200.0
▼Publicité