La gestion du Temps sur une application client/serveur peut sembler simple de prime abord, mais se révélera beaucoup plus complexe au fur et à mesure des usages : timezones multiples, heures récurrentes, heure d'été/d'hiver, traitements cron, leap seconds sont des exemples parmi tant d'autres.
Saviez-vous même que la Commission Européenne envisage d'abolir le passage en heure d'hiver ? Quels impacts cela aurait sur nos applications ?
Mon objectif : qu'à partir de lundi prochain, vous vous posiez les bonnes questions à chaque fois que vous travaillerez sur une date ou une heure dans vos applications.
Pour cela, reprenons les bases du Temps en informatique : composantes d'une date, norme ISO 8601, Timezones et IANA.
Une fois ces bases posées, nous verrons, au travers d'un certain nombre de cas d'utilisation issus de la vraie vie, les bonnes questions qu'il convient de se poser pour mettre le doigt sur les complexités d'implémentation et éviter de tomber dans une faille spatio-temporelle lors du prochain changement d'heure.
Ce talk est accessible à tous et ne se focalisera pas sur un langage / une API en particulier : les concepts prévaudront sur le code.
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Back to Basics - Ne perdez plus votre Temps avec les Dates - Bordeaux JS Edition
1. Ne perdez plus votre
Temps avec les Dates
#RetourAuxSources
4SH France
@fcamblor
Frédéric CAMBLOR
Bordeaux JS
2019-04-11T19:00:00+02:00
#DateTimeBasics
2. Avertissement
Cette présentation n’aborde pas vraiment des technologies à la mode.
Pire, vous risquez de ressortir de cette présentation avec moins de
certitudes que vous n’en aviez en arrivant.
Acceptez-vous de poursuivre la présentation ?
Si vous voulez savoir comment déployer dans la blockchain des
microservices Kotlin en Kubernetes Native, il est encore temps
de rentrer chez vous…
3.
4. Ne perdez plus votre
Temps avec les Dates
#RetourAuxSources
4SH France
@fcamblor
Frédéric CAMBLOR
Bordeaux JS
2019-04-11T19:00:00+02:00
#DateTimeBasics
17. Coordinated Universal Time (UTC)
• Basé sur le TAI
• Agnostic de la géographie / géopolitique
• Stable/Continu dans le temps
Pas d'heure d'été/hiver
• EPOCH : 1970-01-01T00:00:00Z
18. Leap Seconds
• Variable d'ajustement entre UT1& TAI
• Annoncée ~6mois à l'avance
• Positionnée fin juin/décembre
• Nombre de Leap Seconds : 37
19. NTP (Network Time Protocol)
https://en.wikipedia.org/wiki/Network_Time_Protocol
21. ❓Ce qu'on ne connaît pasℹ Ce qu'on connaît
Timestamps
Unix milliseconds : 1548954000000
Unix : 1548954000
•Le positionnement absolu
dans le temps
•Comparaison triviale
•La date/heure
•Est-ce le jour ou la nuit ?
•En sec. ou en millisec. ?
•La timezone
⚠ à l'overflow le 2038-01-19T03:14:07
22. ❓Ce qu'on ne connaît pasℹ Ce qu'on connaît
Datetime ISO 8601 / RFC 3339
2019-01-31T18:00:00+01:00
2019-01-31T17:00:00Z
•Le positionnement absolu
dans le temps
•Comparaison
(⚠ au timezone offset)
•Est-ce le jour ou la nuit ?
•Le jour de la semaine
•La timezone
https://www.w3.org/TR/NOTE-datetime
23. ❓Ce qu'on ne connaît pasℹ Ce qu'on connaît
Date & Time"Local"
Jeudi 31 Janvier 2019, 06:00 PM
2019-01-31T18:00:00
2019-01-31
•C'est un jeudi
•C'est le soir
•On est en hiver
•Quel point UTC ?
•Non comparable à une
date provenant d'une
autre région
•Quelle heure sera-t-il si
on ajoute 24h ?
30. TIMEZONES: Points clef
• Région du globe observant une évolution
uniforme de son heure
• Heure définie par des offsets depuis UTC
Ces offsets peuvent changer
• Les offsets sont "généralement" d'1h
• Ils varient de -12:00 à +14:00
• Référence : IANA & Windows TimeZones
31. Internet Assigned Numbers Authority (IANA) for Europe
https://github.com/eggert/tz/blob/master/europe
33. En JAVA c'est packagé dans les JRE + TZUpdater tool
http://bit.ly/JRE-IANA
34. Pour MySQL il faut le faire à la main
http://bit.ly/mysql-tzdata
35. Pour NodeJS il faut le gérer à la main
https://www.npmjs.com/package/geo-tz
36. tldr; posez-vous la question !
L'OS peut aussi mettre à disposition ces tables
37. TZ Data: Points clef
• Très lié à la géopolitique
• Les règles changent régulièrement
• Les règles changent subitement
• Une multitude de libs existent
• Ne rien considérer comme acquis
⚠ ⚠ ⚠ aux dates dans le futur
38. Lorsque vous stockez une Date+Heure
dans le futur,stockez en plus l'heure
et la timezone de l'utilisateur à
l'origine de la manipulation
Vous pourrez détecter & corriger le
problème s'il survient
(et que vous en êtes informé)
39. Daylight Saving Time (DST)
tzDate("2018-03-25T01:10:00", "Europe/Paris")
=> 2018-03-25T01:10:00+01:00
Certaines heures locales n'existent pas (Local Time Gap)
(02:00 -> 03:00 pour Europe/Paris)
tzDate("2018-03-25T01:10:00", "Europe/Paris").add(1, 'hour')
=> 2018-03-25T03:10:00+02:00
tzDate("2018-03-25T02:10:00", "Europe/Paris")
=> 2018-03-25T03:10:00+02:00
40. Daylight Saving Time (DST)
tzDate("2018-10-28T02:10:00", "Europe/Paris")
=> 2018-10-28T02:10:00+02:00
Certaines heures locales existent 2 fois
(02:00 -> 03:00 pour Europe/Paris)
tzDate("2018-10-28T03:10:00", "Europe/Paris")
=> 2018-10-28T03:10:00+01:00
tzDate("2018-10-28T02:10:00", "Europe/Paris").add(1, 'hour')
=> 2018-10-28T02:10:00+01:00
41. Fausse bonne idée
"Notre batch de facturation passe tous les jours à
2h30 du matin (heure locale),car il s'agit du
moment où le système est le moins sollicité"
🤦 )
47. 🤔
Qui a raison ?
public ZonedDateTime calculateNextThingAfter(ZonedDateTime d) {
return d.plusDays(1);
}
public ZonedDateTime calculateNextThingAfter(ZonedDateTime d) {
return d.plusHours(24);
}
#scaleMatters
48. Fun fact : aucun 2011-12-30 (Friday) aux Samoa
https://www.timeanddate.com/news/time/samoa-dateline.html
53. Format standard => date UTC | Format non standard => date Locale
https://twitter.com/seldo/status/1091861205260500992
54. D'autres blagues
• Les mois commencent à 0
On a trouvé d'où vient le "Java" de "Javascript" !
• Aucune gestion des timezones / internationalisation
• La gestion des "anciens" timezone offsets est
(complètement) broken
... chez tout le monde (Chrome, Firefox, IE, Safari, Node)
https://codeofmatt.com/javascript-date-type-is-horribly-broken/
57. Les serveurs doivent être en UTC
•Timezone de l'OS
•Timezone de la DB
Il n'est pas tout le temps possible de la changer
•Timezone de votre serveur d'App
sudo timedatectl set-timezone UTC
# Or : sudo dpkg-reconfigure tzdata
-Duser.timezone=UTC
58. L'intervalle de temps implicite
👍 GET /messages?start=2019-02-09T00:00:00+01:00
&end=2019-02-09T23:59:59+01:00
👎 GET /messages?date=2019-02-09
👋 GET /messages?date=2019-02-09&tz=Europe/Paris
59. Date search Patterns
• Dans 99% des cas vous allez faire des
recherches sur des intervalles de temps
• Dans la mesure du possible, faites les
conversions coté appelant (client)
• Stockez vos datetime en UTC / Timestamp
60. Attention aux"Heures locales"
[On est le 08/03 à Bordeaux]
"Le magasin ouvre à 9h du matin les jours ouvrés"
"J'aimerais planifier une réunion à 15h
(Europe/Paris) tous les lundi"
Heure sans Date attachée
61. Attention aux"Heures locales"
[On est le 08/03 à Bordeaux]
"J'aimerais planifier une réunion à 15h (Europe/Paris) tous les lundi"
1/ "Le dernier lundi d'avril"
=> 2019-04-29 (Date Locale)
2/ Ajout de la composante heure + timezone offset
=> 2019-04-29T15:00:00+02:00
Attention aux cas exceptionnels !
👍 "localTime": "15:00 [Europe/Paris]"
3/ Décalage dans une tz cible (ex: America/New_York)
=> 2019-04-29T09:00:00-04:00
62. Time-only Patterns
• Évitez de stocker votre Time dans un
DateTime (1970-01-01T15:35:00Z)
• Stockez tout le temps la Timezone de
l'utilisateur ayant saisi l'heure
• Mettez à disposition la Timezone cible de
l'utilisateur faisant une recherche
63. Date-only Patterns
• Évitez de stocker votre Date dans un
DateTime (1732-02-22T00:00:00Z)
• Si vous êtes sûr de la Timezone,
stockez-la
• Utilisez une structure de données adhoc
64. Les"Local Datetime"
Aucun intérêt d'avoir un DateTime
sans Timezone
À éviter,à tout prix !
http://blog.schauderhaft.de/2018/03/14/dont-use-
localdatetime/