--- title: Types supplémentaires author: Steve Kossouho --- # Types supplémentaires ---- ## Un type pour les dates et heures La bibliothèque standard nous offre plusieurs types de données pour gérer des moments dans le temps, avec le module `datetime`. Dans ce module, le type pour les dates avec heure s'appelle aussi `datetime`. ```{.python .numberLines} from datetime import datetime now = datetime.now() then = datetime(2021, 1, 31) # arguments positionnels then2 = datetime(2021, 1, 31, hour=12) # arguments par défaut ``` ---- Les objets de ce type offrent un accès à plusieurs attributs, pour récupérer le jour, le mois, l'heure etc. ```{.python .numberLines} from datetime import datetime now = datetime.now() print(now.day, now.date()) # affiche le jour du mois, et la date sans l'heure ``` ---- ## Opérations arithmétiques entre dates et intervalles de temps Le module `datetime` propose un type qui représente un intervalle de temps, nommé `timedelta`. C'est ce que l'on obtient quand on soustrait deux dates (le temps écoulé entre les deux). Mais on peut aussi créer des objets `timedelta`{.python} et les ajouter (ou soustraire) à des dates. ```{.python .numberLines} from datetime import timedelta, datetime interval = timedelta(hours=15) now = datetime.now() then = datetime(2000, 1, 1) interval2 = now - then the_future = now + interval # dans 15 heures print(interval2, the_future) ``` ---- Les objets d'intervalle de temps donnent accès à peu d'attributs. Nous avons uniquement accès aux jours, secondes et microsecondes. On préférera utiliser le résultats renvoyés par la méthode `total_seconds()` comme base pour nos propres conversions d'ordres de grandeur. ```{.python .numberLines} from datetime import timedelta interval = timedelta(hours=14, minutes=31, seconds=53) print(interval.days, interval.seconds, interval.microseconds) print(interval.total_seconds()) ``` ---- ## Récupérer une date depuis un timestamp Un [timestamp]{.naming} est une date exprimée sous la forme d'un nombre entier (ou flottant). En général, un timestamp en programmation est le nombre de secondes depuis le 1er janvier 1970 à 00:00:00 UTC. On appelle ce moment l'epoch Unix. On peut calculer un objet `datetime`{.python} depuis un timestamp, ou un timestamp depuis un objet `datetime`{.python}. ```python {.numberLines} from datetime import datetime timestamp = 1577836800 as_datetime = datetime.fromtimestamp(timestamp) print(as_datetime) ``` ---- ## Convertir une date en chaîne Pour convertir une date vers une chaîne, ou convertir une chaîne vers un objet de date, consultez toujours la même ressource : [Table de référence pour le format de dates](https://docs.python.org/fr/3/library/datetime.html#strftime-and-strptime-format-codes) ---- ### Éléments de date localisés dans la langue système Pour une raison inconnue, probablement un bug sous certaines distributions Linux, Python n'utilise pas la langue configurée sur votre système, et vous voyez un formatage tel que `Sunday` s'afficher au lieu de `Dimanche`. Pas de panique, il existe une solution pour forcer Python à utiliser la langue que vous désirez. ```{.python .numberLines} import locale locale.setlocale(locale.LC_ALL, "") # utilise les paramètres de langue de l'utilisateur ``` [Documentation sur setlocale](https://docs.python.org/fr/3/library/locale.html) ---- Pour convertir un objet `datetime` vers une chaîne, grâce à la table de référence, c'est simple : ```{.python .numberLines} from datetime import datetime now = datetime.now() text = now.strftime("%d/%m/%Y %H:%M et %S secondes.") other = f"{now:%d/%m/%Y %H:%M et %S secondes}" # via des f-strings print(text, other) ``` ---- ## Convertir une chaîne en date Dans l'autre sens, c'est à peine plus compliqué : ```{.python .numberLines} from datetime import datetime text = "24 12 2003 15:17" moment = datetime.strptime(text, "%d %m %Y %H:%M") print(moment) ``` ---- ## Bonus : Fuseaux horaires Par défaut, les objets de date que vous confectionnez sont dits naïfs, car ils ne contiennent pas d'information de fuseau horaire. Vous pouvez créer ou modifier des objets pour porter ces informations si vous en avez besoin. La façon de s'en servir changera selon que vous utilisez Python 3.9 ou une version antérieure. ---- ### Fuseaux horaires avant Python 3.9 Avant Python 3.9, il est conseillé d'installer `pytz` et `tzlocal` avec `pip`, puis de définir vos dates ainsi : ```{.python .numberLines} import pytz from datetime import datetime moment = datetime(2013, 4, 16, tzinfo=pytz.timezone("Europe/Paris")) moment2 = datetime(2010, 1, 1) moment2 = moment2.replace(tzinfo=pytz.UTC) ``` ---- Vous pouvez convertir votre date de façon à la représenter dans un autre fuseau horaire : ```{.python .numberLines} import pytz, tzlocal from datetime import datetime moment = datetime(2013, 4, 16, tzinfo=pytz.timezone("America/Chihuahua")) moment2 = moment.astimezone(tzlocal.get_localzone()) ``` ---- ### Fuseaux horaires avec Python 3.9+ Python 3.9 ajoute enfin `zoneinfo`, qui couvre presque totalement les larges lacunes de `tzinfo`. (il demeure impossible de connaître le fuseau horaire local) ```{.python .numberLines} from datetime import datetime from zoneinfo import ZoneInfo moment = datetime(1975, 3, 1, hour=13, tzinfo=ZoneInfo("Europe/Madrid")) ``` ---- ## Bonus : Bibliothèques tierces pour les dates L'écosystème Python propose de temps en temps des alternatives plus abordables que les outils présents dans la bibliothèque standard. La gestion de dates n'y échappe pas et je peux proposer deux bibliothèques élégantes et simples à comprendre pour Python : - [Arrow](https://arrow.readthedocs.io/en/latest/) : Better dates and times for Python - [Pendulum](https://pendulum.eustace.io/) : Python datetimes made easy