Whenever – bibliothèque de gestion des dates et heures sûre pour les types et le DST pour Python
(github.com/ariebovenberg)- Whenever est une bibliothèque de date et heure pour Python qui empêche par le typage les mélanges entre
datetimenaive et aware ainsi que les erreurs de calcul liées au DST, et qui peut être utilisée avec une implémentation Rust ou une implémentation Python pure - La bibliothèque standard
datetimene prend pas toujours en compte le DST, et l’exempledatetime(2023, 3, 25, 22, tzinfo=ZoneInfo("Europe/Paris")) + timedelta(hours=8)montre qu’elle renvoie 6 h au lieu de 7 h alors qu’une heure a été sautée à cause du DST - Le système de types ne peut pas distinguer naive et aware avec le seul type
datetime, mais Whenever sépare des types selon l’usage commeInstant,ZonedDateTimeetPlainDateTime, afin que le vérificateur de types puisse repérer les erreurs - Dans le tableau comparatif, Arrow et Pendulum ne remplissent pas simultanément les critères de sûreté DST, de distinction typed aware/naive et de performance, tandis que Whenever annonce prendre en charge DST-safe, typed aware/naive et fast
- Le projet n’est pas encore en 1.0, donc l’API peut changer dans les versions mineures ; les changements sont expliqués dans le changelog, et le vérificateur de types ou l’IDE peuvent aider à l’adaptation
Le problème que Whenever cherche à résoudre
- Whenever est une bibliothèque conçue pour aider à écrire en Python du code de date et heure correct et vérifiable par typage
- Elle propose une implémentation Rust, ainsi qu’une version Python pure pour les utilisateurs qui ne veulent pas de Rust
- Elle est conçue à partir de concepts éprouvés utilisés dans les bibliothèques modernes de date et heure d’autres langages
- Elle est présentée comme bien plus rapide que les autres bibliothèques tierces, et souvent même plus rapide que la bibliothèque standard
- La sortie de la version 1.0 est retardée afin d’affiner davantage l’API à long terme, en particulier autour des durations, sur lesquelles l’auteur recueille encore des retours
Les limites de la bibliothèque standard datetime
- Le
datetimede Python a évolué pendant plus de 20 ans, avec certains aspects qui ne correspondent plus à ce qu’on attend d’une bibliothèque moderne de date et heure -
Problèmes de calcul DST
datetimene prend pas toujours en compte le Daylight Saving Time (DST)- Dans l’exemple, si l’on ajoute 8 heures à 22 h le 25 mars 2023 dans le fuseau
Europe/Paris, le résultat devrait être 7 h puisqu’une heure a été sautée à cause du DST, maisdatetimerenvoie 6 h - Ce n’est pas un bug, mais un choix de conception visant à ne prendre en compte le DST que dans les calculs impliquant deux fuseaux horaires
-
Problème de distinction de type entre naive et aware
- Avec le seul type
datetime, le système de types ne peut pas distinguer un naive datetime d’un aware datetime - Une signature de fonction comme
def schedule_meeting(at: datetime) -> None: ...ne permet pas de savoir si elle attend une valeur naive ou aware
- Avec le seul type
Comparaison avec Arrow et Pendulum
- Selon le tableau comparatif, Whenever remplit les trois critères : DST-safe, typed aware/naive et fast
datetimene satisfait que le critère fast, mais pas DST-safe ni typed aware/naive- Arrow cherche à fournir une API plus agréable que celle de la bibliothèque standard, sans pour autant résoudre les problèmes de fond
- Il conserve les mêmes pièges
- Le choix de tout ramener à un seul type,
arrow.Arrow, rend plus difficile pour le vérificateur de types de détecter les erreurs
- Pendulum mettait en avant en 2016 une meilleure gestion du DST et de meilleures performances, mais ne corrige que certains pièges liés au DST
- Les performances se sont fortement dégradées avec le temps
- Le projet traverse une longue période de maintenance ralentie, avec seulement deux releases au cours des quatre dernières années et de nombreux problèmes graves et anciens encore ouverts
Fonctionnalités principales
- Prise en charge d’une arithmétique DST-safe
- API sûre du point de vue du typage pour éviter les bugs fréquents
- Corrige des problèmes qu’Arrow et Pendulum n’ont pas su résoudre
- Repose sur des concepts éprouvés et familiers
- Offre de hautes performances
- Dispose de tests et d’une documentation solides
- Prend en charge l’arithmétique sur les dates
- Prend en charge une précision à la nanoseconde
- Fournit une prise en charge SQLAlchemy
- La prise en charge de Pydantic est en bêta
- Propose une implémentation Rust et une option Python pure
- La prise en charge du free-threading est en bêta
- Prend en charge le per-interpreter GIL
Exemples d’utilisation
- Des types explicites comme
Instant,ZonedDateTimeetPlainDateTimesont utilisés pour représenter différents cas d’usage Instant.now()identifie un instant précis sans complexité liée au fuseau horaire ni au calendrier- La conversion de fuseau horaire se fait explicitement, comme avec
now.to_tz("Europe/Paris") PlainDateTime("2023-10-28 22:00")ne se mélange pas accidentellement avec d’autres types- Si l’on appelle
add(hours=6), unNaiveArithmeticWarningindique que l’ajustement d’heure locale ignore le DST - Il faut supposer explicitement un fuseau horaire via
assume_tz("Europe/Amsterdam")
- Si l’on appelle
- Sur un
ZonedDateTime, l’appel àadd(hours=6)tient compte de la transition DST et renvoie2023-10-29 03:00:00+01:00[Europe/Amsterdam] - La bibliothèque prend en charge les comparaisons, l’arrondi et la troncature, l’analyse de formats ISO8601·RFC3339·RFC2822, ainsi que le formatage avec des motifs personnalisés
- Si nécessaire, on peut convertir vers le
datetimede la bibliothèque standard ou dans l’autre sens - L’utilisation détaillée est décrite dans la feature overview et la API reference
Contraintes et politique de stabilité
- La plage prise en charge va de l’an 1 à 9999 dans le calendrier grégorien proleptique
- Les offsets de fuseau horaire sont limités à des entiers en secondes, en cohérence avec l’IANA TZ DB
- Whenever suit le semantic versioning
- Avant la version 1.0, l’API peut changer dans les releases mineures
- Les breaking changes sont expliqués en détail dans le changelog
- Comme l’API est entièrement typée, le vérificateur de types ou l’IDE peuvent aider à s’adapter aux changements d’API
Licence et influences de conception
- Whenever est distribué sous licence MIT
- Les binary wheels incluent des dépendances Rust sous des licences permissives similaires, comme MIT et Apache-2.0
- Noda Time et Joda Time ont été pionniers dans l’approche par types distincts selon les concepts, et la hiérarchie de types de Noda Time a directement inspiré la conception de Whenever
- Temporal a inspiré la gestion des cas complexes autour des ambiguïtés DST et de l’arrondi
- Le module
datetimede Python est largement utilisé dans l’implémentation Python pure de Whenever pour le traitement bas niveau des dates et heures - Certaines idées de Jiff ont aussi été reprises
- Le graphique comparatif de benchmarks est adapté du projet Ruff
Aucun commentaire pour le moment.