SlideShare une entreprise Scribd logo
1  sur  103
Télécharger pour lire hors ligne
Ne perdez plus votre
Temps avec les Dates
#RetourAuxSources
4SH France
@fcamblor
Frédéric CAMBLOR
Bordeaux JUG
2019-02-21T19:00:00+01:00
#DateTimeBasics
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 avec Kubernetes, il est encore temps de
rentrer chez vous…
Ne perdez plus votre
Temps avec les Dates
#RetourAuxSources
4SH France
@fcamblor
Frédéric CAMBLOR
Workshop 4SH
2019-02-13T18:00:00+01:00
#DateTimeBasics
Photoby4SH
4SH cherche de nouveaux talents
Photoby4SH
🤔
Qui n’a jamais eu de soucis
avec le Temps (en général) ?
Apple
http://bit.ly/iphonote-bug-dst-apple
Microsoft
http://bit.ly/cnet-new-years-microsoft
Twitter
http://bit.ly/programmes-twitter-bug-2015
Y2K Bug anyone ?
https://en.wikipedia.org/wiki/Year_2000_problem
Un peu d'histoire...
AVANT LES
HORLOGES & MONTRES
MODERNES
ON UTILISAIT…
PhotobyTeeKaysurWikimedia
Au Zenith,il est 12:00
PhotobyPatxiMartin
Avant les heures standards
L'arrivée des heures standards (1847-1972)
La seconde comme unité de temps
• Se mesure en base ... 60
• Confiance dans sa durée
• Défini à partir d'un élément physique
régulier & mesurable
🤔
9,192,631,770 ?
Temps atomique international (TAI)
PhotobyDnn87onWikimedia
Coordinated Universal Time (UTC)
• Basé sur le TAI
• Agnostic de la géographie / géopolitique
• Stable dans le temps

Pas d'heure d'été/hiver
• EPOCH : 1970-01-01
EPOCHs
https://fr.wikipedia.org/wiki/Epoch
Leap Seconds
• Variable d'ajustement entre UT1& TAI
• Annoncée ~6mois à l'avance
• Positionnée fin juin/décembre
• Nombre de Leap Seconds : 37
NTP (Network Time Protocol)
https://en.wikipedia.org/wiki/Network_Time_Protocol
Perspective
On voit souvent les Dates/Heures
depuis des angles différents
❓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
❓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
❓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 ?
Des représentations multiples
Chacune apportant des informations et en
en occultant d'autres
Les TIMEZONES
Ou comment construire des ponts entre les représentations
Timezone
Europe/Paris
America/New_York

Antarctica/South_Pole
...
2019-01-31T17:00:00Z
2019-01-31T18:00:00+01:00
2019-01-31T12:00:00-05:00
...
Timezone offset
⚠ Ce sont des notions très différentes !
Standard World Timezone Offsets
https://en.wikipedia.org/wiki/Time_zone
✅ Date ISO 8601 => Timestamp
2019-01-31T18:00:00+01:00
=> 1548954000000
❌ Timestamp => Date ISO 8601
1548954000000
=> 2019-01-31T17:00:00Z
=> 2019-01-31T18:00:00+01:00
=> 2019-02-01T01:00:00+08:00
=> ...
❌ Timezone offset => Timezone
2018-01-29T18:00:00+01:00
=> ✅ Europe/Paris
=> ✅ Africa/Casablanca
=> ...
🚫 Une Timezone ne peut pas être"calculée"
2018-06-29T18:00:00+02:00
=> ✅ Europe/Paris
=> ❌ Africa/Casablanca (+01:00)
❌ Timezone => Timezone offset
moment.tz("2018-01-29 18:00", "Europe/Paris").format()
=> 2018-01-29T18:00:00+01:00
moment.tz("2018-06-29 18:00", "Europe/Paris").format()
=> 2018-06-29T18:00:00+02:00
✅ Timezone + Datetime + TzTable
=> Timezone offset
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
Internet Assigned Numbers Authority (IANA) for Europe
https://github.com/eggert/tz/blob/master/europe
🤔
Comment mon système se
met-il à jour ?
En JAVA c'est packagé dans les JRE
http://bit.ly/JRE-IANA
Pour MySQL il faut le faire à la main
http://bit.ly/mysql-tzdata
Pour NodeJS il faut le gérer à la main
https://www.npmjs.com/package/geo-tz
tldr; posez-vous la question !
L'OS peut aussi mettre à disposition ces tables
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
Daylight Saving Time (DST)
moment.tz("2018-03-25T01:10:00", "Europe/Paris")
.format()
=> 2018-03-25T01:10:00+01:00
Certaines heures locales n'existent pas
(02:00 -> 03:00 pour Europe/Paris)
moment.tz("2018-03-25T01:10:00", "Europe/Paris")
.add(1, 'hours').format()
=> 2018-03-25T03:10:00+02:00
moment.tz("2018-03-25T02:10:00", "Europe/Paris")
.format()
=> 2018-03-25T03:10:00+02:00
Daylight Saving Time (DST)
moment.tz("2018-10-28T02:10:00", "Europe/Paris")
.format()
=> 2018-10-28T02:10:00+02:00
Certaines heures locales existent 2 fois
(02:00 -> 03:00 pour Europe/Paris)
moment.tz("2018-10-28T03:10:00", "Europe/Paris")
.format()
=> 2018-10-28T03:10:00+01:00
moment.tz("2018-10-28T02:10:00", "Europe/Paris")
.add(1, 'hour').format()
=> 2018-10-28T02:10:00+01:00
La date/heure DST varie en fonction de la timezone
http://bit.ly/dst-diffs
Consultation Européenne pour/contre DST
• Sondage sur 40j : 2018-07-04 --> 2018-08-16
• 4.6M de réponses
• 84% en faveur d'une abolition de DST
Cependant considérée comme un sondage non représentatif
https://ec.europa.eu/info/consultations/2018-summertime-
arrangements_en
🤔
DST varie-t-il *toujours* d'1h ?
Peut-il y avoir plus de 2 shifts par an ?
"A one-hour shift is customary."
"Twenty-minute and two-hour shifts
have been used in the past."
https://en.wikipedia.org/wiki/Daylight_saving_time
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é"
🤦 )
"Notre batch de facturation passe tous les
jours à 2h30 1h30 du matin (heure locale)
UTC, car il s'agit du moment où le système est
le moins sollicité"
Le batch s'exécutera (heure locale) à 2h30
(en hiver) ou 3h30 (en été) mais au moins il
passera tous les jours 1 et 1 seule fois.
Numéros de semaine
moment("2017-01-02T00:00:00+01:00").format("GGGG-WW")
=> 2017-01
moment("2016-01-02T00:00:00+01:00").format("GGGG-WW")
=> 2015-53
Explorons un certain
nombre d'idées reçues...
"Il y a 24h dans une journée
et 365 jours dans une année"
#FakeNews
(facile!)
Années bissextiles
Duration.between(
ZonedDateTime.parse("2004-01-01T00:00:00+01:00[Europe/Paris]"),
ZonedDateTime.parse("2005-01-01T00:00:00+01:00[Europe/Paris]")
).toDays()
=> 366
• Tous les 4 ans
• Sauf années séculaires (tous les 100 ans)
• Sauf années multiples de 400
2000 était bissextile,mais 2100 ne le sera pas.
Daylight Saving Time
var ZDTFactory = (str, timezone) -> ZonedDateTime.of(
LocalDateTime.parse(str), ZoneId.of(timezone)
);
Duration.between(
ZDTFactory("2018-03-25T00:00:00", "Europe/Paris"),
ZDTFactory("2018-03-26T00:00:00", "Europe/Paris")
).toHours()
=> 23
Duration.between(
ZDTFactory("2018-10-28T00:00:00", "Europe/Paris"),
ZDTFactory("2018-10-29T00:00:00", "Europe/Paris")
).toHours()
=> 25
🤔
Qui a raison ?
public ZonedDateTime calculateNextThingAfter(ZonedDateTime d) {
return d.plusDays(1);
}
public ZonedDateTime calculateNextThingAfter(ZonedDateTime d) {
return d.plusHours(24);
}
#scaleMatters
Fun fact : aucun 2011-12-30 (Friday) aux Samoa
https://www.timeanddate.com/news/time/samoa-dateline.html
"Comparer des dates,
c'est facile"
#FakeNews
...
Vousvoulezvraimentlasource???
🙈
🤮 #NIH
Comparator<String> strDatesComparator =
(strD1, strD2) -> strD1.compareTo(strD2);
✅ Il existe généralement une API...
Comparator<String> strDatesComparator =
Comparator.comparing(ZonedDateTime::parse);
✅ À défaut,passer par des timestamps
Comparator<String> strDatesComparator = ????
strDatesComparator.compare(
"2019-01-31T18:00:00-02:00[America/Sao_Paulo]"
"2019-01-31T20:00:00+01:00[Europe/Paris]")
🤔
Mais où est le problème ?
boolean datesAreEqual(ZonedDateTime d1, ZonedDateTime d2) {
return Objects.equals(d1, d2);
}
ZonedDateTime.parse("2018-03-25T00:00:00+01:00[Europe/Berlin]")
.equals(ZonedDateTime.parse("2018-03-25T00:00:00+01:00[Europe/Paris]"))
=> false
ZonedDateTime.parse("2018-03-25T00:00:00+01:00[Europe/Berlin]")
.isEqual(ZonedDateTime.parse("2018-03-25T00:00:00+01:00[Europe/Paris]"))
=> true
Égalité vs Identité
"L'objet Date en Javascript,
c'est de la balle !"
#FakeNews
Format standard => date UTC | Format non standard => date Locale
https://twitter.com/seldo/status/1091861205260500992
D'autres blagues
• Les mois commencent à 0

On a trouvé d'où vient le "Java" de "Javascript" !
• Aucune gestion des timezones
• Aucune gestion de l'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/
"L'API Date/Calendar de
Java (<8) est bien meilleure"
#FakeNews
Les perles en Java
• Années basées sur 1900
• Structures mutables (Date / Calendar)
• SimpleDateFormat non thread-safe
• Pas de notion de "Local" / "Zoned" Dates
• Indigestion de Constantes
• Des defaults basés sur "now" => difficilement testable
• Date.toString() qui se base sur la Locale système
new Date(2017, Calendar.FEBRUARY, 13).toString()
=> Tue Feb 13 00:00:00 GMT 3917 😱
Utilisez une librairie
• En JS :
• momentjs + moment-timezone
• dayjs / Luxon
• date-fns
• En Java : Joda time ou JSR 310 (Java 8+)
🤔
#MomentJS #FunFacts
De quelle Locale parle-t-on ?
moment().add(4, 'hours').locale('tlh').fromNow()
=> loS rep pIq
🖖
"Les dates dans le futur ?
Tranquille !"
Vous connaissez votre propre avenir,ce qui veut dire que vous
pouvez le changer si vous le voulez.Vous avez encore le choix.
Minority Report
Problème des dates dans le futur
Je suis actuellement à Bordeaux,j'aimerais programmer une
campagne d'envoi de mails toutes les semaines le lundi à 10h
sur les 52 semaines à venir.
• Solution Naïve : Générer tous les timestamps à l'avance
• Problème : les Timezones offset peuvent changer en
fonction de la géopolitique
• Que se passe-t-il si dans 6 mois l'Europe abolit l'heure
d'hiver ?
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é)
Bon,on devrait avoir fait
le tour de toutes les règles
bizarres maintenant...
L’ignorance c’est comme des chaussures trop petites !
Dr Who
Le premier jour de la semaine peut varier...
https://en.wikipedia.org/wiki/Week
La notion de Chronology
• ISO 8601 = Calendrier Grégorien de facto
• Il en existe plein d'autres : Julien, Ethiopien,
Bouddhiste, Islamiste, Copte...
• Règles différentes sur l'année de départ
• Règles différentes sur les années bissextiles
• Répartition différente des jours dans les mois
AM / PM (sacrés British)
• 12 AM (=00:00) < 1 AM (=01:00)
• Notation ambigüe à l'oral
if(hour === 0) {
ampm = 'AM'; hour = 12;
} else if(hour < 12) {
ampm = 'AM'; hour = hour;
} else if(hour == 12) {
ampm = 'PM'; hour = 12;
} else {
ampm = 'PM'; hour -= 12;
}
Quelques bonnes pratiques
issues de la vie réelle
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
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
L'intervalle de temps implicite
// Assumes client and server timezones are the same
SELECT * FROM messages WHERE published_on = '2019-02-09';
👍 Expected👎 Result
👎 GET /messages?date=2019-02-09
L'intervalle de temps implicite
1/ Convert date to date midnight using Europe/Paris Timezone
2019-02-09 => 2019-02-09T00:00:00+01:00
👍 Expected
👋 GET /messages?date=2019-02-09&tz=Europe/Paris
👎 Result
# Swap 2 & 3 for expected result !
2/ Convert to UTC
=> 2019-02-08T23:00:00Z
3/ Transform to Range using startOf/endOf day
=> [ 2019-02-08T00:00:00Z, 2019-02-08T23:59:59Z ]
L'intervalle de temps implicite
1/ Convert date to date midnight using Europe/Paris Timezone
2019-02-09 => 2019-02-09T00:00:00+01:00
2/ Transform to Range using startOf/endOf day
=> [ 2019-02-09T00:00:00+01:00, 2019-02-09T23:59:59+01:00 ]
3/ Convert to UTC
=> [ 2019-02-08T23:00:00Z, 2019-02-09T22:59:59Z ]
👍 Expected
👋 GET /messages?date=2019-02-09&tz=Europe/Paris
👍 Result
L'intervalle de temps implicite
// Nothing fancy happening serverside since we're
// working with timestamps
SELECT * FROM messages WHERE published_on
BETWEEN '2019-02-08T23:00:00Z' AND '2019-02-09T23:00:00Z' ;
👍 Expected👍 Result
👍 GET /messages?start=2019-02-09T00:00:00+01:00

&end=2019-02-09T23:59:59+01:00
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
Attention aux"Heures locales"
[On est le 21/02 à Bordeaux]
"Le magasin ouvre à 9h du matin"
"J'aimerais planifier une réunion à 15h
(Europe/Paris) tous les lundi"
Heure sans Date attachée
Attention aux"Heures locales"
👎 POST /recurrentMeetings

{ "frequency": "WEEKLY","weekDays": ["MONDAY"],

"utcTime": "14:00" }
[On est le 21/02 à Bordeaux]
"J'aimerais planifier une réunion à 15h (Europe/Paris) tous les lundi"
ℹ GET /meetings?date=2019-02-25&tz=Europe/Paris

[{"date": "2019-02-25T15:00:00+01:00"}]
ℹ GET /meetings?date=2019-06-24&tz=Europe/Paris

[{"date": "2019-06-24T16:00:00+02:00"}]
Attention aux"Heures locales"
[On est le 21/02 à Bordeaux]
"J'aimerais planifier une réunion à 15h (Europe/Paris) tous les lundi"
ℹ GET /meetings?date=2019-02-25&tz=Europe/Paris

[{"date": "2019-02-25T15:00:00+01:00"}]
ℹ GET /meetings?date=2019-06-24&tz=Europe/Paris

[{"date": "2019-06-24T15:00:00+02:00"}]
👍 POST /recurrentMeetings

{ "frequency": "WEEKLY","weekDays": ["MONDAY"],

"localTime": "15:00 [Europe/Paris]"}
ℹ GET /meetings?date=2019-06-24&tz=America/New_York

[{"date": "2019-06-24T09:00:00-04:00"}]
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
Attention aux"Dates locales"
"Je suis né
le 29 juin 1983 près de Bordeaux [sous-entendu en France]"



"Georges Washington est né
le 22 février 1732 [lieu non précisé]"
Date sans Heure attachée,
et potentiellement sans Timezone
Attention aux"Dates locales"
• Pas de "Silver bullet" ici

• Dépend énormément :
• des informations disponibles (Timezone notamment)
• de ce qu'on veut faire de cette Date locale
• En Java, il n'existe qu'une LocalDate
• Date sans Heure ni Timezone
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
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/
Pour conclure...
Bien considérer toutes les
perspectives
Bien faire la distinction
entre Temps local et absolu
Les Timezones sont
changeantes,rapidement
Mettez régulièrement à jour
vos tzdata
Évitez de stocker des dates dans le futur
Si vous n'avez pas le choix stockez
l'heure locale et la Timezone
Utilisez la bonne échelle de
temps lorsque vous faites des
opérations sur les Dates/Heures
Ne faites pas confiance aux
Dates Javascript
Ne prenez rien comme acquis
Questionnez-vous
...Tout le Temps
Des questions ?
Q&A Time

Contenu connexe

En vedette

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

En vedette (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Back to Basics - Ne perdez plus votre Temps avec les Dates - BordeauxJUG Edition

  • 1. Ne perdez plus votre Temps avec les Dates #RetourAuxSources 4SH France @fcamblor Frédéric CAMBLOR Bordeaux JUG 2019-02-21T19:00:00+01: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 avec Kubernetes, 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 Workshop 4SH 2019-02-13T18:00:00+01:00 #DateTimeBasics
  • 6. 4SH cherche de nouveaux talents Photoby4SH
  • 7. 🤔 Qui n’a jamais eu de soucis avec le Temps (en général) ?
  • 11. Y2K Bug anyone ? https://en.wikipedia.org/wiki/Year_2000_problem
  • 13. AVANT LES HORLOGES & MONTRES MODERNES ON UTILISAIT…
  • 15. Au Zenith,il est 12:00 PhotobyPatxiMartin
  • 16. Avant les heures standards
  • 17. L'arrivée des heures standards (1847-1972)
  • 18. La seconde comme unité de temps • Se mesure en base ... 60 • Confiance dans sa durée • Défini à partir d'un élément physique régulier & mesurable
  • 20. Temps atomique international (TAI) PhotobyDnn87onWikimedia
  • 21. Coordinated Universal Time (UTC) • Basé sur le TAI • Agnostic de la géographie / géopolitique • Stable dans le temps
 Pas d'heure d'été/hiver • EPOCH : 1970-01-01
  • 23. Leap Seconds • Variable d'ajustement entre UT1& TAI • Annoncée ~6mois à l'avance • Positionnée fin juin/décembre • Nombre de Leap Seconds : 37
  • 24. NTP (Network Time Protocol) https://en.wikipedia.org/wiki/Network_Time_Protocol
  • 25. Perspective On voit souvent les Dates/Heures depuis des angles différents
  • 26. ❓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
  • 27. ❓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
  • 28. ❓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 ?
  • 29. Des représentations multiples Chacune apportant des informations et en en occultant d'autres
  • 30. Les TIMEZONES Ou comment construire des ponts entre les représentations
  • 32. Standard World Timezone Offsets https://en.wikipedia.org/wiki/Time_zone
  • 33. ✅ Date ISO 8601 => Timestamp 2019-01-31T18:00:00+01:00 => 1548954000000 ❌ Timestamp => Date ISO 8601 1548954000000 => 2019-01-31T17:00:00Z => 2019-01-31T18:00:00+01:00 => 2019-02-01T01:00:00+08:00 => ...
  • 34. ❌ Timezone offset => Timezone 2018-01-29T18:00:00+01:00 => ✅ Europe/Paris => ✅ Africa/Casablanca => ... 🚫 Une Timezone ne peut pas être"calculée" 2018-06-29T18:00:00+02:00 => ✅ Europe/Paris => ❌ Africa/Casablanca (+01:00)
  • 35. ❌ Timezone => Timezone offset moment.tz("2018-01-29 18:00", "Europe/Paris").format() => 2018-01-29T18:00:00+01:00 moment.tz("2018-06-29 18:00", "Europe/Paris").format() => 2018-06-29T18:00:00+02:00 ✅ Timezone + Datetime + TzTable => Timezone offset
  • 36. 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
  • 37. Internet Assigned Numbers Authority (IANA) for Europe https://github.com/eggert/tz/blob/master/europe
  • 38. 🤔 Comment mon système se met-il à jour ?
  • 39. En JAVA c'est packagé dans les JRE http://bit.ly/JRE-IANA
  • 40. Pour MySQL il faut le faire à la main http://bit.ly/mysql-tzdata
  • 41. Pour NodeJS il faut le gérer à la main https://www.npmjs.com/package/geo-tz
  • 42. tldr; posez-vous la question ! L'OS peut aussi mettre à disposition ces tables
  • 43. 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
  • 44. Daylight Saving Time (DST) moment.tz("2018-03-25T01:10:00", "Europe/Paris") .format() => 2018-03-25T01:10:00+01:00 Certaines heures locales n'existent pas (02:00 -> 03:00 pour Europe/Paris) moment.tz("2018-03-25T01:10:00", "Europe/Paris") .add(1, 'hours').format() => 2018-03-25T03:10:00+02:00 moment.tz("2018-03-25T02:10:00", "Europe/Paris") .format() => 2018-03-25T03:10:00+02:00
  • 45. Daylight Saving Time (DST) moment.tz("2018-10-28T02:10:00", "Europe/Paris") .format() => 2018-10-28T02:10:00+02:00 Certaines heures locales existent 2 fois (02:00 -> 03:00 pour Europe/Paris) moment.tz("2018-10-28T03:10:00", "Europe/Paris") .format() => 2018-10-28T03:10:00+01:00 moment.tz("2018-10-28T02:10:00", "Europe/Paris") .add(1, 'hour').format() => 2018-10-28T02:10:00+01:00
  • 46. La date/heure DST varie en fonction de la timezone http://bit.ly/dst-diffs
  • 47. Consultation Européenne pour/contre DST • Sondage sur 40j : 2018-07-04 --> 2018-08-16 • 4.6M de réponses • 84% en faveur d'une abolition de DST Cependant considérée comme un sondage non représentatif https://ec.europa.eu/info/consultations/2018-summertime- arrangements_en
  • 48. 🤔 DST varie-t-il *toujours* d'1h ? Peut-il y avoir plus de 2 shifts par an ?
  • 49. "A one-hour shift is customary." "Twenty-minute and two-hour shifts have been used in the past." https://en.wikipedia.org/wiki/Daylight_saving_time
  • 50. 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é" 🤦 )
  • 51. "Notre batch de facturation passe tous les jours à 2h30 1h30 du matin (heure locale) UTC, car il s'agit du moment où le système est le moins sollicité" Le batch s'exécutera (heure locale) à 2h30 (en hiver) ou 3h30 (en été) mais au moins il passera tous les jours 1 et 1 seule fois.
  • 52. Numéros de semaine moment("2017-01-02T00:00:00+01:00").format("GGGG-WW") => 2017-01 moment("2016-01-02T00:00:00+01:00").format("GGGG-WW") => 2015-53
  • 53. Explorons un certain nombre d'idées reçues...
  • 54. "Il y a 24h dans une journée et 365 jours dans une année" #FakeNews (facile!)
  • 55. Années bissextiles Duration.between( ZonedDateTime.parse("2004-01-01T00:00:00+01:00[Europe/Paris]"), ZonedDateTime.parse("2005-01-01T00:00:00+01:00[Europe/Paris]") ).toDays() => 366 • Tous les 4 ans • Sauf années séculaires (tous les 100 ans) • Sauf années multiples de 400 2000 était bissextile,mais 2100 ne le sera pas.
  • 56. Daylight Saving Time var ZDTFactory = (str, timezone) -> ZonedDateTime.of( LocalDateTime.parse(str), ZoneId.of(timezone) ); Duration.between( ZDTFactory("2018-03-25T00:00:00", "Europe/Paris"), ZDTFactory("2018-03-26T00:00:00", "Europe/Paris") ).toHours() => 23 Duration.between( ZDTFactory("2018-10-28T00:00:00", "Europe/Paris"), ZDTFactory("2018-10-29T00:00:00", "Europe/Paris") ).toHours() => 25
  • 57. 🤔 Qui a raison ? public ZonedDateTime calculateNextThingAfter(ZonedDateTime d) { return d.plusDays(1); } public ZonedDateTime calculateNextThingAfter(ZonedDateTime d) { return d.plusHours(24); } #scaleMatters
  • 58. Fun fact : aucun 2011-12-30 (Friday) aux Samoa https://www.timeanddate.com/news/time/samoa-dateline.html
  • 59. "Comparer des dates, c'est facile" #FakeNews
  • 61. 🤮 #NIH Comparator<String> strDatesComparator = (strD1, strD2) -> strD1.compareTo(strD2); ✅ Il existe généralement une API... Comparator<String> strDatesComparator = Comparator.comparing(ZonedDateTime::parse); ✅ À défaut,passer par des timestamps Comparator<String> strDatesComparator = ???? strDatesComparator.compare( "2019-01-31T18:00:00-02:00[America/Sao_Paulo]" "2019-01-31T20:00:00+01:00[Europe/Paris]")
  • 62. 🤔 Mais où est le problème ? boolean datesAreEqual(ZonedDateTime d1, ZonedDateTime d2) { return Objects.equals(d1, d2); }
  • 64. "L'objet Date en Javascript, c'est de la balle !" #FakeNews
  • 65. Format standard => date UTC | Format non standard => date Locale https://twitter.com/seldo/status/1091861205260500992
  • 66. D'autres blagues • Les mois commencent à 0
 On a trouvé d'où vient le "Java" de "Javascript" ! • Aucune gestion des timezones • Aucune gestion de l'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/
  • 67. "L'API Date/Calendar de Java (<8) est bien meilleure" #FakeNews
  • 68. Les perles en Java • Années basées sur 1900 • Structures mutables (Date / Calendar) • SimpleDateFormat non thread-safe • Pas de notion de "Local" / "Zoned" Dates • Indigestion de Constantes • Des defaults basés sur "now" => difficilement testable • Date.toString() qui se base sur la Locale système new Date(2017, Calendar.FEBRUARY, 13).toString() => Tue Feb 13 00:00:00 GMT 3917 😱
  • 69. Utilisez une librairie • En JS : • momentjs + moment-timezone • dayjs / Luxon • date-fns • En Java : Joda time ou JSR 310 (Java 8+)
  • 70. 🤔 #MomentJS #FunFacts De quelle Locale parle-t-on ? moment().add(4, 'hours').locale('tlh').fromNow() => loS rep pIq 🖖
  • 71. "Les dates dans le futur ? Tranquille !" Vous connaissez votre propre avenir,ce qui veut dire que vous pouvez le changer si vous le voulez.Vous avez encore le choix. Minority Report
  • 72. Problème des dates dans le futur Je suis actuellement à Bordeaux,j'aimerais programmer une campagne d'envoi de mails toutes les semaines le lundi à 10h sur les 52 semaines à venir. • Solution Naïve : Générer tous les timestamps à l'avance • Problème : les Timezones offset peuvent changer en fonction de la géopolitique • Que se passe-t-il si dans 6 mois l'Europe abolit l'heure d'hiver ?
  • 73. 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é)
  • 74. Bon,on devrait avoir fait le tour de toutes les règles bizarres maintenant... L’ignorance c’est comme des chaussures trop petites ! Dr Who
  • 75. Le premier jour de la semaine peut varier... https://en.wikipedia.org/wiki/Week
  • 76. La notion de Chronology • ISO 8601 = Calendrier Grégorien de facto • Il en existe plein d'autres : Julien, Ethiopien, Bouddhiste, Islamiste, Copte... • Règles différentes sur l'année de départ • Règles différentes sur les années bissextiles • Répartition différente des jours dans les mois
  • 77. AM / PM (sacrés British) • 12 AM (=00:00) < 1 AM (=01:00) • Notation ambigüe à l'oral if(hour === 0) { ampm = 'AM'; hour = 12; } else if(hour < 12) { ampm = 'AM'; hour = hour; } else if(hour == 12) { ampm = 'PM'; hour = 12; } else { ampm = 'PM'; hour -= 12; }
  • 78. Quelques bonnes pratiques issues de la vie réelle
  • 79. 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
  • 80. 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
  • 81. L'intervalle de temps implicite // Assumes client and server timezones are the same SELECT * FROM messages WHERE published_on = '2019-02-09'; 👍 Expected👎 Result 👎 GET /messages?date=2019-02-09
  • 82. L'intervalle de temps implicite 1/ Convert date to date midnight using Europe/Paris Timezone 2019-02-09 => 2019-02-09T00:00:00+01:00 👍 Expected 👋 GET /messages?date=2019-02-09&tz=Europe/Paris 👎 Result # Swap 2 & 3 for expected result ! 2/ Convert to UTC => 2019-02-08T23:00:00Z 3/ Transform to Range using startOf/endOf day => [ 2019-02-08T00:00:00Z, 2019-02-08T23:59:59Z ]
  • 83. L'intervalle de temps implicite 1/ Convert date to date midnight using Europe/Paris Timezone 2019-02-09 => 2019-02-09T00:00:00+01:00 2/ Transform to Range using startOf/endOf day => [ 2019-02-09T00:00:00+01:00, 2019-02-09T23:59:59+01:00 ] 3/ Convert to UTC => [ 2019-02-08T23:00:00Z, 2019-02-09T22:59:59Z ] 👍 Expected 👋 GET /messages?date=2019-02-09&tz=Europe/Paris 👍 Result
  • 84. L'intervalle de temps implicite // Nothing fancy happening serverside since we're // working with timestamps SELECT * FROM messages WHERE published_on BETWEEN '2019-02-08T23:00:00Z' AND '2019-02-09T23:00:00Z' ; 👍 Expected👍 Result 👍 GET /messages?start=2019-02-09T00:00:00+01:00
 &end=2019-02-09T23:59:59+01:00
  • 85. 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
  • 86. Attention aux"Heures locales" [On est le 21/02 à Bordeaux] "Le magasin ouvre à 9h du matin" "J'aimerais planifier une réunion à 15h (Europe/Paris) tous les lundi" Heure sans Date attachée
  • 87. Attention aux"Heures locales" 👎 POST /recurrentMeetings
 { "frequency": "WEEKLY","weekDays": ["MONDAY"],
 "utcTime": "14:00" } [On est le 21/02 à Bordeaux] "J'aimerais planifier une réunion à 15h (Europe/Paris) tous les lundi" ℹ GET /meetings?date=2019-02-25&tz=Europe/Paris
 [{"date": "2019-02-25T15:00:00+01:00"}] ℹ GET /meetings?date=2019-06-24&tz=Europe/Paris
 [{"date": "2019-06-24T16:00:00+02:00"}]
  • 88. Attention aux"Heures locales" [On est le 21/02 à Bordeaux] "J'aimerais planifier une réunion à 15h (Europe/Paris) tous les lundi" ℹ GET /meetings?date=2019-02-25&tz=Europe/Paris
 [{"date": "2019-02-25T15:00:00+01:00"}] ℹ GET /meetings?date=2019-06-24&tz=Europe/Paris
 [{"date": "2019-06-24T15:00:00+02:00"}] 👍 POST /recurrentMeetings
 { "frequency": "WEEKLY","weekDays": ["MONDAY"],
 "localTime": "15:00 [Europe/Paris]"} ℹ GET /meetings?date=2019-06-24&tz=America/New_York
 [{"date": "2019-06-24T09:00:00-04:00"}]
  • 89. 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
  • 90. Attention aux"Dates locales" "Je suis né le 29 juin 1983 près de Bordeaux [sous-entendu en France]"
 
 "Georges Washington est né le 22 février 1732 [lieu non précisé]" Date sans Heure attachée, et potentiellement sans Timezone
  • 91. Attention aux"Dates locales" • Pas de "Silver bullet" ici
 • Dépend énormément : • des informations disponibles (Timezone notamment) • de ce qu'on veut faire de cette Date locale • En Java, il n'existe qu'une LocalDate • Date sans Heure ni Timezone
  • 92. 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
  • 93. 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/
  • 95. Bien considérer toutes les perspectives
  • 96. Bien faire la distinction entre Temps local et absolu
  • 98. Mettez régulièrement à jour vos tzdata
  • 99. Évitez de stocker des dates dans le futur Si vous n'avez pas le choix stockez l'heure locale et la Timezone
  • 100. Utilisez la bonne échelle de temps lorsque vous faites des opérations sur les Dates/Heures
  • 101. Ne faites pas confiance aux Dates Javascript
  • 102. Ne prenez rien comme acquis Questionnez-vous ...Tout le Temps