Utilisation de datetime Python pour travailler avec des dates et des heures – Real Python

By | mai 4, 2020

trouver un expert Python

Travailler avec des dates et des heures est l'un des plus grands défis de la programmation. Entre les fuseaux horaires, l'heure d'été et les différents formats de date écrits, il peut être difficile de garder une trace des jours et des heures auxquels vous faites référence. Heureusement, le Python intégré datetime Le module peut vous aider à gérer la nature complexe des dates et des heures.

Dans ce didacticiel, vous apprendrez:

  • Pourquoi programmer avec dates et heures est un tel défi
  • Quelles fonctions sont disponibles dans le Python datetime module
  • Comment imprimer ou lire une date et une heure dans un format spécifique
  • Comment faire arithmétique avec dates et heures

De plus, vous allez développer une application soignée pour décompter le temps restant jusqu'à la prochaine PyCon US!

Commençons!

Programmation avec dates et heures

Si vous avez déjà travaillé sur un logiciel qui devait suivre les temps dans plusieurs zones géographiques, vous comprenez probablement pourquoi la programmation avec le temps peut être si difficile. La déconnexion fondamentale est que les programmes informatiques préfèrent des événements parfaitement ordonnés et réguliers, mais la manière dont la plupart des humains utilisent et se réfèrent au temps est très irrégulière.

Un bon exemple de cette irrégularité est heure d'été. Aux États-Unis et au Canada, les horloges sont avancées d'une heure le deuxième dimanche de mars et reculées d'une heure le premier dimanche de novembre. Cependant, ce n'est le cas que depuis 2007. Avant 2007, les horloges étaient avancées le premier dimanche d'avril et reculées le dernier dimanche d'octobre.

Les choses deviennent encore plus compliquées quand on considère fuseaux horaires. Idéalement, les limites des fuseaux horaires suivraient exactement les lignes de longitude. Cependant, pour des raisons historiques et politiques, les lignes de fuseau horaire sont rarement droites. Souvent, les zones séparées par de grandes distances se trouvent dans le même fuseau horaire et les zones adjacentes se trouvent dans des fuseaux horaires différents. Il y a des fuseaux horaires avec des formes assez funky.

Comment les ordinateurs comptent le temps

Presque tous les ordinateurs comptent le temps à partir d'un instant appelé Époque Unix. Cela s'est produit le 1er janvier 1970 à 00 h 00 UTC. UTC signifie Temps universel coordonné et se réfère à l'heure à une longitude de 0 °. L'UTC est souvent aussi appelé Greenwich Mean Time, ou GMT. L'UTC n'est pas ajusté pour l'heure d'été, il conserve donc constamment vingt-quatre heures par jour.

Par définition, le temps Unix s'écoule au même rythme que UTC, donc un pas d'une seconde en UTC correspond à un pas d'une seconde en temps Unix. Vous pouvez généralement déterminer la date et l'heure en UTC d'un instant donné depuis le 1er janvier 1970, en comptant le nombre de secondes depuis l'époque Unix, à l'exception de secondes intercalaires. Des secondes intercalaires sont parfois ajoutées à l’UTC pour tenir compte du ralentissement de la rotation de la Terre, mais ne sont pas ajoutées au temps Unix.

Presque tous les langages de programmation, y compris Python, incorporent le concept du temps Unix. La bibliothèque standard de Python comprend un module appelé temps qui peut imprimer le nombre de secondes depuis l'époque Unix:

>>>

>>> importation temps
>>> temps.temps()
1579718137.550164

Dans cet exemple, vous importez le temps module et exécuter temps() pour imprimer le temps Unix, ou le nombre de secondes (hors secondes intercalaires) depuis l'époque.

En plus du temps Unix, les ordinateurs ont besoin d'un moyen de transmettre des informations de temps aux utilisateurs. Comme vous l'avez vu dans le dernier exemple, le temps Unix est presque impossible pour un humain à analyser. Au lieu de cela, l'heure Unix est généralement convertie en UTC, qui peut ensuite être convertie en heure locale à l'aide de décalages de fuseau horaire.

le Internet Assigned Numbers Authority (IANA) maintient une base de données de toutes les valeurs des décalages de fuseau horaire. L'IANA publie également des mises à jour régulières qui incluent toute modification des décalages de fuseau horaire. Cette base de données est souvent incluse avec votre système d'exploitation, bien que certaines applications puissent inclure une copie mise à jour.

La base de données contient une copie de tous les fuseaux horaires désignés et combien d'heures et de minutes ils sont décalés par rapport à l'UTC. Ainsi, pendant l'hiver, lorsque l'heure d'été n'est pas en vigueur, le fuseau horaire de l'Est américain a un décalage de -05: 00, ou cinq heures négatives par rapport à UTC. D'autres régions ont des décalages différents, qui peuvent ne pas être des heures entières. Le décalage UTC pour le Népal, par exemple, est de +05: 45, ou positif à cinq heures et quarante-cinq minutes de l'UTC.

Comment signaler les dates standard

Le temps Unix est la façon dont les ordinateurs comptent le temps, mais il serait incroyablement inefficace pour les humains de déterminer le temps en calculant le nombre de secondes à partir d'une date arbitraire. Au lieu de cela, nous travaillons en termes d'années, de mois, de jours, etc. Mais même avec ces conventions en place, une autre couche de complexité vient du fait que les différentes langues et cultures ont différentes manières d'écrire la date.

Aux États-Unis, par exemple, les dates sont généralement écrites en commençant par le mois, puis le jour, puis l'année. Cela signifie que le 31 janvier 2020 est écrit comme suit: 31-01-2020. Cela correspond étroitement à la version écrite longue de la date.

Cependant, la plupart des pays d'Europe et de nombreuses autres régions écrivent la date en commençant par le jour, puis le mois, puis l'année. Cela signifie que le 31 janvier 2020 est écrit comme suit: 31-01-2020. Ces différences peuvent provoquer toutes sortes de confusion lors de la communication entre les cultures.

Pour éviter les erreurs de communication, l'Organisation internationale de normalisation (ISO) a développé ISO 8601. Cette norme spécifie que toutes les dates doivent être écrites dans l'ordre des données les plus importantes aux moins importantes. Cela signifie que le format est l'année, le mois, le jour, l'heure, la minute et la seconde:

Dans cet exemple, Aaaa représente une année à quatre chiffres, et MM et DD sont le mois et le jour à deux chiffres, commençant par un zéro si nécessaire. Après ça, HH, MM, et SS représentent les heures, les minutes et les secondes à deux chiffres, en commençant par un zéro si nécessaire.

L'avantage de ce format est que la date peut être représentée sans ambiguïté. Dates écrites comme JJ-MM-AAAA ou MM-JJ-AAAA peut être mal interprété si le jour est un numéro de mois valide. Vous verrez un peu plus tard comment utiliser le format ISO 8601 avec Python datetime.

Comment le temps devrait être stocké dans votre programme

La plupart des développeurs qui ont travaillé avec le temps ont entendu les conseils pour convertir l'heure locale en UTC et stocker cette valeur pour référence ultérieure. Dans de nombreux cas, en particulier lorsque vous stockez des dates du passé, ces informations sont suffisantes pour effectuer l’arithmétique nécessaire.

Cependant, un problème peut se produire si un utilisateur de votre programme entre une date future dans son heure locale. Les règles de fuseau horaire et d'heure d'été changent assez fréquemment, comme vous l'avez vu précédemment avec le changement de 2007 en heure d'été pour les États-Unis et le Canada. Si les règles de fuseau horaire de l'emplacement de votre utilisateur changent avant la date future qu'il a entrée, l'UTC ne fournira pas suffisamment d'informations pour revenir à l'heure locale correcte.

Dans ce cas, vous devez stocker l'heure locale, y compris le fuseau horaire, que l'utilisateur a entrée ainsi que la version de la base de données de fuseau horaire IANA qui était en vigueur lorsque l'utilisateur a enregistré l'heure. De cette façon, vous pourrez toujours convertir l'heure locale en UTC. Cependant, cette approche ne vous permettra pas toujours de convertir UTC à l'heure locale correcte.

Utiliser le Python datetime Module

Comme vous pouvez le voir, travailler avec des dates et des heures dans la programmation peut être compliqué. Heureusement, vous avez rarement besoin d'implémenter des fonctionnalités compliquées à partir de zéro de nos jours car de nombreuses bibliothèques open-source sont disponibles pour vous aider. C'est certainement le cas en Python, qui comprend trois modules distincts dans la bibliothèque standard pour travailler avec les dates et les heures:

  1. calendrier génère des calendriers et fournit des fonctions à l'aide d'un calendrier grégorien idéalisé.
  2. datetime fournit des cours pour manipuler les dates et les heures.
  3. temps fournit des fonctions liées au temps où les dates ne sont pas nécessaires.

Dans ce didacticiel, vous vous concentrerez sur l'utilisation de Python datetime module. L'objectif principal de datetime consiste à simplifier l'accès aux attributs de l'objet liés aux dates, heures et fuseaux horaires. Étant donné que ces objets sont si utiles, calendrier renvoie également des instances de classes de datetime.

temps est moins puissant et plus compliqué à utiliser que datetime. De nombreuses fonctions temps retourner un spécial struct_time exemple. Cet objet possède une interface de tuple nommée pour accéder aux données stockées, ce qui le rend similaire à une instance de datetime. Cependant, il ne prend pas en charge toutes les fonctionnalités de datetime, en particulier la possibilité d'effectuer une arithmétique avec des valeurs de temps.

datetime fournit trois classes qui composent l'interface de haut niveau que la plupart des gens utiliseront:

  1. datetime.date est une date idéalisée qui suppose que le calendrier grégorien s'étend à l'infini dans le futur et le passé. Cet objet stocke le an, mois, et journée comme attributs.
  2. datetime.time est un temps idéal qui suppose qu'il y a 86 400 secondes par jour sans seconde intercalaire. Cet objet stocke le heure, minute, seconde, microseconde, et tzinfo (informations sur le fuseau horaire).
  3. datetime.datetime est une combinaison d'un Date et un temps. Il possède tous les attributs des deux classes.

Création de Python datetime Instances

Les trois classes qui représentent les dates et les heures datetime avoir similaire initialiseurs. Ils peuvent être instanciés en passant des arguments de mots clés pour chacun des attributs, tels que an, Date, ou heure. Vous pouvez essayer le code ci-dessous pour avoir une idée de la façon dont chaque objet est créé:

>>>

>>> de datetime importation Date, temps, datetime
>>> Date(an=2020, mois=1, journée=31)
datetime.date (2020, 1, 31)
>>> temps(heure=13, minute=14, seconde=31)
datetime.time (13, 14, 31)
>>> datetime(an=2020, mois=1, journée=31, heure=13, minute=14, seconde=31)
datetime.datetime (2020, 1, 31, 13, 14, 31)

Dans ce code, vous importez les trois classes principales de datetime et instancier chacun d'eux en passant des arguments au constructeur. Vous pouvez voir que ce code est quelque peu bavard, et si vous n'avez pas les informations dont vous avez besoin sous forme d'entiers, ces techniques ne peuvent pas être utilisées pour créer datetime instances.

Heureusement, datetime fournit plusieurs autres moyens pratiques de créer datetime instances. Ces méthodes ne vous obligent pas à utiliser des entiers pour spécifier chaque attribut, mais vous permettent à la place d'utiliser d'autres informations:

  1. date d'aujourd'hui() crée un datetime.date par exemple avec la date locale actuelle.
  2. datetime.now () crée un datetime.datetime par exemple avec la date et l'heure locales actuelles.
  3. datetime.combine () combine des instances de datetime.date et datetime.time en un seul datetime.datetime exemple.

Ces trois façons de créer datetime les instances sont utiles lorsque vous ne savez pas à l'avance quelles informations vous devez transmettre aux initialiseurs de base. Vous pouvez essayer ce code pour voir comment fonctionnent les autres initialiseurs:

>>>

>>> de datetime importation Date, temps, datetime
>>> aujourd'hui = Date.aujourd'hui()
>>> aujourd'hui
datetime.date (2020, 1, 24)
>>> maintenant = datetime.maintenant()
>>> maintenant
datetime.datetime (2020, 1, 24, 14, 4, 57, 10015)
>>> heure actuelle = temps(maintenant.heure, maintenant.minute, maintenant.seconde)
>>> datetime.combiner(aujourd'hui, heure actuelle)
datetime.datetime (2020, 1, 24, 14, 4, 57)

Dans ce code, vous utilisez date d'aujourd'hui(), datetime.now (), et datetime.combine () pour créer des instances de Date, datetime, et temps objets. Chaque instance est stockée dans une variable différente:

  1. aujourd'hui est un Date instance qui n'a que l'année, le mois et le jour.
  2. maintenant est un datetime instance qui a l'année, le mois, le jour, l'heure, la minute, la seconde et les microsecondes.
  3. heure actuelle est un temps instance dont l'heure, la minute et la seconde ont les mêmes valeurs que maintenant.

Sur la dernière ligne, vous combinez les informations de date dans aujourd'hui avec les informations de temps dans heure actuelle pour produire un nouveau datetime exemple.

Utilisation de chaînes pour créer Python datetime Instances

Une autre façon de créer Date instances est d'utiliser .fromisoformat (). Pour utiliser cette méthode, vous fournissez une chaîne avec la date au format ISO 8601 que vous avez connue plus tôt. Par exemple, vous pouvez fournir une chaîne avec l'année, le mois et la date spécifiés:

Cette chaîne représente la date du 31 janvier 2020, selon le format ISO 8601. Vous pouvez créer un Date par exemple avec l'exemple suivant:

>>>

>>> de datetime importation Date
>>> Date.fromisoformat("2020-01-31")
datetime.date (2020, 1, 31)

Dans ce code, vous utilisez date.fromisoformat () créer un Date par exemple pour le 31 janvier 2020. Cette méthode est très utile car elle est basée sur la norme ISO 8601. Mais que faire si vous avez une chaîne qui représente une date et une heure mais qui n'est pas au format ISO 8601?

Heureusement, Python datetime fournit une méthode appelée .strptime () pour gérer cette situation. Cette méthode utilise un spécial mini-langue pour indiquer à Python quelles parties de la chaîne sont associées au datetime les attributs.

Pour construire un datetime à partir d'une chaîne en utilisant .strptime (), vous devez dire à Python ce que chacune des parties de la chaîne représente à l'aide des codes de mise en forme du mini-langage. Vous pouvez essayer cet exemple pour voir comment .strptime () travaux:

>>>

    1 >>> date_string = "31-01-2020 14:45:37"
    2 >>> format_string = "% m-%ré-% Y% H:% M:% S "

Sur ligne 1, tu crées date_string, qui représente la date et l'heure du 31 janvier 2020 à 14 h 45 min 37 s. Sur ligne 2, tu crées format_string, qui utilise le mini-langage pour spécifier comment les parties de date_string sera transformé en datetime les attributs.

Dans format_string, vous incluez plusieurs codes de mise en forme et tous les tirets (-), deux points (:) et les espaces tels qu'ils apparaissent dans date_string. Pour traiter la date et l'heure dans date_string, vous incluez les codes de mise en forme suivants:

Composant Code Valeur
Année (sous forme d'entier à quatre chiffres) % Y 2020
Mois (sous forme décimale complétée par zéro) % m 01
Date (sous forme décimale complétée par zéro) %ré 31
Heure (sous forme décimale à zéro avec horloge de 24 heures) % H 14
Minute (sous forme décimale complétée par zéro) % M 45
Deuxième (sous forme décimale complétée par zéro) % S 37

Une liste complète de toutes les options du mini-langage n'entre pas dans le cadre de ce didacticiel, mais vous pouvez trouver plusieurs bonnes références sur le Web, y compris dans la documentation de Python et sur un site Web appelé strftime.org.

Maintenant que date_string et format_string sont définis, vous pouvez les utiliser pour créer un datetime exemple. Voici un exemple de la façon dont .strptime () travaux:

>>>

    3 >>> de datetime importation datetime
    4 >>> datetime.strptime(date_string, format_string)
    5 datetime.datetime (2020, 1, 31, 14, 45, 37)

Dans ce code, vous importez datetime sur ligne 3 et utilise datetime.strptime () avec date_string et format_string sur ligne 4. Finalement, ligne 5 affiche les valeurs des attributs dans le datetime instance créée par .strptime (). Vous pouvez voir qu'ils correspondent aux valeurs indiquées dans le tableau ci-dessus.

Démarrage de votre compte à rebours PyCon

Maintenant, vous avez suffisamment d'informations pour commencer à travailler sur un compte à rebours pour PyCon US l'année prochaine! PyCon US 2021 débutera le 12 mai 2021 à Pittsburgh, en Pennsylvanie. L'événement 2020 ayant été annulé, de nombreux Pythonistes sont très excités pour le rassemblement de l'année prochaine. C'est un excellent moyen de savoir combien de temps vous devrez attendre et d'augmenter votre datetime compétences en même temps!

Pour commencer, créez un fichier appelé pyconcd.py et ajoutez ce code:

# pyconcd.py

de datetime importation datetime

PYCON_DATE = datetime(an=2021, mois=5, journée=12, heure=8)
compte à rebours = PYCON_DATE - datetime.maintenant()
impression(F"Compte à rebours pour PyCon US 2021: compte à rebours")

Dans ce code, vous importez datetime de datetime et définir une constante, PYCON_DATE, qui stocke la date de la prochaine PyCon US. Vous ne vous attendez pas à ce que la date de PyCon change, vous nommez donc la variable en majuscules pour indiquer qu'il s'agit d'une constante.

Ensuite, vous calculez la différence entre datetime.now (), qui est l'heure actuelle, et PYCON_DATE. Faire la différence entre deux datetime instances renvoie un datetime.timedelta exemple.

timedelta les instances représentent le changement de temps entre deux datetime instances. le delta dans le nom est une référence à la lettre grecque delta, qui est utilisée en science et en ingénierie pour signifier un changement. Vous en apprendrez plus tard sur la façon d'utiliser timedelta pour des opérations arithmétiques plus générales.

Enfin la sortie imprimée, au 9 avril 2020 à un peu avant 21h30 est:

Compte à rebours pour PyCon US 2021: 397 jours, 10: 35: 32.139350

Seulement 397 jours avant PyCon US 2021! Cette sortie est un peu maladroite. Par conséquent, vous verrez plus tard comment améliorer la mise en forme. Si vous exécutez ce script un autre jour, vous obtiendrez une sortie différente. Si vous exécutez le script après le 12 mai 2021 à 8h00, vous aurez un temps négatif restant!

Travailler avec des fuseaux horaires

Comme vous l'avez vu précédemment, le stockage du fuseau horaire dans lequel une date se produit est un aspect important pour s'assurer que votre code est correct. Python datetime fournit tzinfo, qui est une classe de base abstraite qui permet datetime.datetime et datetime.time pour inclure des informations de fuseau horaire, y compris une idée de l'heure d'été.

cependant, datetime ne fournit pas un moyen direct d'interagir avec la base de données de fuseau horaire IANA. Le Python datetime.tzinfo la documentation recommande d'utiliser un package tiers appelé dateutil. Vous pouvez installer dateutil avec pépin:

$ python -m pip install python-dateutil

Notez que le nom du package que vous installez à partir de PyPI, python-dateutil, est différent du nom que vous utilisez pour importer le package, qui est juste dateutil.

En utilisant dateutil ajouter des fuseaux horaires à Python datetime

Une raison pour laquelle dateutil est si utile qu'il inclut une interface avec la base de données des fuseaux horaires de l'IANA. Cela vous évite d'affecter des fuseaux horaires à votre datetime instances. Essayez cet exemple pour voir comment définir un datetime par exemple pour avoir votre fuseau horaire local:

>>>

>>> de dateutil importation tz
>>> de datetime importation datetime
>>> maintenant = datetime.maintenant(tz=tz.tzlocal())
>>> maintenant
datetime.datetime (2020, 1, 26, 0, 55, 3, 372824, tzinfo = tzlocal ())
>>> maintenant.tzname()
«Heure normale de l'Est»

Dans cet exemple, vous importez tz de dateutil et datetime de datetime. Vous créez ensuite un datetime instance définie sur l'heure actuelle à l'aide de .maintenant().

Vous passez également le tz mot-clé à .maintenant() Et mettre tz égal à tz.tzlocal (). Dans dateutil, tz.tzlocal () renvoie une instance concrète de datetime.tzinfo. Cela signifie qu'il peut représenter toutes les informations de décalage de fuseau horaire et d'heure d'été nécessaires datetime Besoins.

Vous imprimez également le nom du fuseau horaire en utilisant .tzname (), qui imprime «Heure normale de l'Est». Ceci est la sortie pour Windows, mais sur macOS ou Linux, votre sortie peut lire 'EST' si vous êtes dans le fuseau horaire de l'Est américain pendant l'hiver.

Vous pouvez également créer des fuseaux horaires différents du fuseau horaire signalé par votre ordinateur. Pour ce faire, vous utiliserez tz.gettz () et passez le nom officiel de l'IANA pour le fuseau horaire qui vous intéresse. Voici un exemple d'utilisation tz.gettz ():

>>>

>>> de dateutil importation tz
>>> de datetime importation datetime
>>> London_tz = tz.gettz("Europe / Londres")
>>> maintenant = datetime.maintenant(tz=London_tz)
>>> maintenant
datetime.datetime (2020, 1, 26, 6, 14, 53, 513460, tzinfo = tzfile ('GB-Eire'))
>>> maintenant.tzname()
'GMT'

Dans cet exemple, vous utilisez tz.gettz () pour récupérer les informations de fuseau horaire pour Londres, Royaume-Uni et les stocker dans London_tz. Vous récupérez ensuite l'heure actuelle en définissant le fuseau horaire sur London_tz.

Sous Windows, cela donne tzinfo attribuer la valeur tzfile («GB-Eire»). Sous macOS ou Linux, le tzinfo l'attribut ressemblera à quelque chose tzfile ('/ usr / share / zoneinfo / Europe / London), mais cela peut être légèrement différent selon l'endroit dateutil extrait les données de fuseau horaire.

Vous utilisez également tzname () pour imprimer le nom du fuseau horaire, qui est maintenant 'GMT', ce qui signifie Greenwich Mean Time. Cette sortie est la même sous Windows, macOS et Linux.

Dans une section précédente, vous avez appris que vous ne devriez pas utiliser .utcnow () créer un datetime par exemple à l'heure UTC actuelle. Vous savez maintenant utiliser dateutil.tz pour fournir un fuseau horaire au datetime exemple. Voici un exemple modifié à partir de la recommandation de la documentation Python:

>>>

>>> de dateutil importation tz
>>> de datetime importation datetime
>>> datetime.maintenant(tz=tz.UTC)
datetime.datetime (2020, 3, 14, 19, 1, 20, 228415, tzinfo = tzutc ())

Dans ce code, vous utilisez tz.UTC pour définir le fuseau horaire de datetime.now () au fuseau horaire UTC. Cette méthode est recommandée par rapport à l'utilisation utcnow () parce que utcnow () renvoie un naïve datetime par exemple, alors que la méthode illustrée ici renvoie un conscient datetime exemple.

Ensuite, vous ferez un petit détour pour en savoir plus sur naïve contre conscient datetime instances. Si vous savez déjà tout à ce sujet, vous pouvez passer à l'étape suivante pour améliorer votre compte à rebours PyCon avec les informations de fuseau horaire.

Comparaison de Python Naive et Aware datetime Instances

Python datetime les instances prennent en charge deux types d'opérations, naïves et conscientes. La différence fondamentale entre eux est que les instances naïves ne contiennent pas d'informations de fuseau horaire, contrairement aux instances conscientes. Plus formellement, pour citer la documentation Python:

Un objet conscient représente un moment précis dans le temps qui n'est pas ouvert à l'interprétation. Un objet naïf ne contient pas suffisamment d'informations pour se localiser sans ambiguïté par rapport à d'autres objets de date / heure. (La source)

Il s'agit d'une distinction importante pour travailler avec Python datetime. Une conscient datetime exemple peut se comparer sans ambiguïté à d'autres conscients datetime instances et renverra toujours l'intervalle de temps correct lorsqu'il est utilisé dans des opérations arithmétiques.

Naïve datetime les instances, en revanche, peuvent être ambiguës. Un exemple de cette ambiguïté concerne l'heure d'été. Les zones qui pratiquent l'heure d'été tournent les horloges d'une heure au printemps et d'une heure en arrière à l'automne. Cela se produit généralement à 2 h 00, heure locale. Au printemps, l'heure de 2h00 à 2h59 n'arrive jamais, et à l'automne, l'heure de 1 h 00 à 1 h 59 se produit deux fois!

En pratique, ce qui se passe, c'est que le décalage par rapport à l'UTC dans ces fuseaux horaires change tout au long de l'année. L'IANA suit ces changements et les catalogue dans les différents fichiers de base de données que votre ordinateur a installés. Utiliser une bibliothèque comme dateutil, qui utilise la base de données IANA sous le capot, est un excellent moyen de s'assurer que votre code gère correctement l'arithmétique avec le temps.

Cela ne signifie pas que vous devez toujours utiliser datetime instances. Mais les instances conscientes sont cruciales si vous comparez des temps entre eux, surtout si vous comparez des temps dans différentes parties du monde.

Améliorer votre compte à rebours PyCon

Maintenant que vous savez comment ajouter des informations de fuseau horaire à un Python datetime par exemple, vous pouvez améliorer votre code de compte à rebours PyCon. Plus tôt, vous avez utilisé la norme datetime constructeur pour passer l'année, le mois, le jour et l'heure de démarrage de PyCon. Vous pouvez mettre à jour votre code pour utiliser le dateutil.parser module, qui fournit une interface plus naturelle pour la création datetime instances:

# pyconcd.py

de dateutil importation analyseur, tz
de datetime importation datetime

PYCON_DATE = analyseur.analyser("12 mai 2021 8 h 00")
PYCON_DATE = PYCON_DATE.remplacer(tzinfo=tz.gettz("Amérique / New_York"))
maintenant = datetime.maintenant(tz=tz.tzlocal())

compte à rebours = PYCON_DATE - maintenant
impression(F"Compte à rebours pour PyCon US 2021: compte à rebours")

Dans ce code, vous importez analyseur et tz de dateutil et datetime de datetime. Ensuite, vous utilisez parser.parse () pour lire la date du prochain PyCon US à partir d'une chaîne. C'est beaucoup plus lisible que la plaine datetime constructeur.

parser.parse () renvoie un naïf datetime par exemple, vous utilisez donc .remplacer() pour changer le tzinfo à la Amérique / New_York fuseau horaire. PyCon US 2021 aura lieu à Pittsburgh, en Pennsylvanie, dans le fuseau horaire de l'Est américain. Le nom canonique de ce fuseau horaire est Amérique / New_York puisque New York est la plus grande ville du fuseau horaire.

PYCON_DATE est conscient datetime par exemple avec le fuseau horaire défini sur l'heure de l'Est américain. Le 12 mai étant après l'entrée en vigueur de l'heure d'été, le nom du fuseau horaire est 'EDT', ou «Heure avancée de l'Est».

Ensuite, vous créez maintenant pour représenter l'instant actuel et lui donner votre fuseau horaire local. Enfin, vous trouvez le timedelta entre PYCON_DATE et maintenant et imprimez le résultat. Si vous vous trouvez dans une région qui n'ajuste pas les horloges pour l'heure d'été, vous pouvez voir le nombre d'heures restantes jusqu'à ce que PyCon change d'une heure.

Faire de l'arithmétique avec Python datetime

Python datetime les instances prennent en charge plusieurs types d'arithmétique. Comme vous l'avez vu précédemment, cela repose sur l'utilisation timedelta instances pour représenter des intervalles de temps. timedelta est très utile car il est intégré à la bibliothèque standard Python. Voici un exemple de la façon de travailler avec timedelta:

>>>

>>> de datetime importation datetime, timedelta
>>> maintenant = datetime.maintenant()
>>> maintenant
datetime.datetime (2020, 1, 26, 9, 37, 46, 380905)
>>> demain = timedelta(journées= +1)
>>> maintenant + demain
datetime.datetime (2020, 1, 27, 9, 37, 46, 380905)

Dans ce code, vous créez maintenant, qui stocke l'heure actuelle, et demain, qui est un timedelta de +1 journées. Ensuite, vous ajoutez maintenant et demain pour produire un datetime par exemple un jour dans le futur. Notez que travailler avec naïf datetime comme vous êtes ici, signifie que le journée attribut de datetime incrémente d'une unité et ne tient pas compte des intervalles de temps répétés ou ignorés.

timedelta les instances prennent également en charge les valeurs négatives en entrée des arguments:

>>>

>>> hier = timedelta(journées= -1)
>>> maintenant + hier
datetime.datetime (2020, 1, 25, 9, 37, 46, 380905)

Dans cet exemple, vous fournissez -1 comme entrée timedelta, donc quand vous ajoutez maintenant et hier, le résultat est une diminution de un journées attribut.

timedelta les instances prennent en charge l'addition et la soustraction ainsi que les entiers positifs et négatifs pour tous les arguments. Vous pouvez même fournir un mélange d'arguments positifs et négatifs. Par exemple, vous souhaiterez peut-être ajouter trois jours et soustraire quatre heures:

>>>

>>> delta = timedelta(journées= +3, heures= -4)
>>> maintenant + delta
datetime.datetime (2020, 1, 29, 5, 37, 46, 380905)

Dans cet exemple, vous ajoutez trois jours et soustrayez quatre heures, de sorte que le nouveau datetime est au 29 janvier à 05h37. timedelta est très utile de cette façon, mais il est quelque peu limité car il ne peut pas ajouter ou soustraire des intervalles supérieurs à une journée, comme un mois ou une année. Heureusement, dateutil fournit un remplacement plus puissant appelé relativedelta.

La syntaxe de base de relativedelta est très similaire à timedelta. Vous pouvez fournir des arguments de mots clés qui produisent des modifications d'un nombre quelconque d'années, de mois, de jours, d'heures, de secondes ou de microsecondes. Vous pouvez reproduire le premier timedelta exemple avec ce code:

>>>

>>> de dateutil.relativedelta importation relativedelta
>>> demain = relativedelta(journées= +1)
>>> maintenant + demain
datetime.datetime (2020, 1, 27, 9, 37, 46, 380905)

Dans cet exemple, vous utilisez relativedelta au lieu de timedelta pour trouver le datetime correspondant à demain. Vous pouvez maintenant essayer d'ajouter cinq ans, un mois et trois jours maintenant en soustrayant quatre heures et trente minutes:

>>>

>>> delta = relativedelta(années= +5, mois= +1, journées= +3, heures= -4, minutes= -30)
>>> maintenant + delta
datetime.datetime (2025, 3, 1, 5, 7, 46, 380905)

Notez dans cet exemple que la date se termine le 1er mars 2025. En effet, l'ajout de trois jours à maintenant serait le 29 janvier, et l'ajout d'un mois serait le 29 février, qui n'existe que dans une année bissextile. Puisque 2025 n'est pas une année bissextile, la date est reportée au mois suivant.

Vous pouvez aussi utiliser relativedelta calculer la différence entre deux datetime instances. Plus tôt, vous avez utilisé l'opérateur de soustraction pour trouver la différence entre deux Python datetime instances, PYCON_DATE et maintenant. Avec relativedelta, au lieu d'utiliser l'opérateur de soustraction, vous devez passer les deux datetime instances comme arguments:

>>>

>>> maintenant
datetime.datetime (2020, 1, 26, 9, 37, 46, 380905)
>>> demain = datetime(2020, 1, 27, 9, 37, 46, 380905)
>>> relativedelta(maintenant, demain)
relativedelta (jours = -1)

Dans cet exemple, vous créez un nouveau datetime exemple pour demain en incrémentant le journées champ par un. Ensuite, vous utilisez relativedelta et passer maintenant et demain comme les deux arguments. dateutil prend ensuite la différence entre ces deux datetime instances et renvoie le résultat sous la forme relativedelta exemple. Dans ce cas, la différence est -1 jours, depuis maintenant arrive avant demain.

dateutil.relativedelta les objets ont d'innombrables autres utilisations. Vous pouvez les utiliser pour trouver des informations de calendrier complexes, telles que l'année suivante au cours de laquelle le 13 octobre tombe un vendredi ou quelle sera la date du dernier vendredi du mois en cours. Vous pouvez même les utiliser pour remplacer les attributs d'un datetime instance et créer, par exemple, un datetime une semaine dans le futur à 10h00. Vous pouvez tout lire sur ces autres utilisations dans le dateutil Documentation.

Fin de votre compte à rebours PyCon

Vous avez maintenant suffisamment d'outils dans votre ceinture pour terminer votre compte à rebours PyCon 2021 et fournir une interface agréable à utiliser également. Dans cette section, vous allez utiliser relativedelta pour calculer le temps restant jusqu'à PyCon, développer une fonction pour imprimer le temps restant dans un format sympa, et montrer la date de PyCon à l'utilisateur.

En utilisant relativedelta dans votre compte à rebours PyCon

Tout d'abord, remplacez l'opérateur de soustraction simple par relativedelta. Avec l'opérateur de soustraction, votre timedelta l'objet ne pouvait pas compter des intervalles de temps supérieurs à un jour. cependant, relativedelta vous permet d'afficher les années, les mois et les jours restants:

    1 # pyconcd.py
    2 
    3 de dateutil importation analyseur, tz
    4 de dateutil.relativedelta importation relativedelta
    5 de datetime importation datetime
    6 
    7 PYCON_DATE = analyseur.analyser("12 mai 2021 8 h 00")
    8 PYCON_DATE = PYCON_DATE.remplacer(tzinfo=tz.gettz("Amérique / New_York"))
    9 maintenant = datetime.maintenant(tz=tz.tzlocal())
dix 
11 compte à rebours = relativedelta(PYCON_DATE, maintenant)
12 impression(F"Compte à rebours pour PyCon US 2021: compte à rebours")

La seule modification que vous avez apportée à ce code a été de remplacer ligne 11 avec compte à rebours = relativedelta (PYCON_DATE, maintenant). La sortie de ce script devrait vous indiquer que PyCon US 2021 se produira dans environ un an et un mois, selon le moment où vous exécuterez le script.

Cependant, cette sortie n'est pas très jolie car elle ressemble à la signature de relativedelta (). Vous pouvez créer une sortie plus jolie en remplaçant ligne 11 dans le code précédent avec le code ci-dessous:

11 def time_amount(time_unit: str, compte à rebours: relativedelta) -> str:
12     t = getattr(compte à rebours, time_unit)
13     revenir F"t time_unit" si t ! = 0 autre ""
14 
15 compte à rebours = relativedelta(PYCON_DATE, maintenant)
16 unités_heure = [[[["années", "mois", "journées", "heures", "minutes", "secondes"]
17 production = (t pour tu dans unités_heure si (t := time_amount(tu, compte à rebours)))
18 impression("Compte à rebours pour PyCon US 2021:", ",".joindre(production))

Ce code nécessite Python 3.8 car il utilise le nouveau opérateur de morse. Vous pouvez faire fonctionner ce script sur les anciennes versions de Python en utilisant un traditionnel pour boucle à la place de ligne 17.

Dans ce code, vous définissez time_amount (), qui prend deux arguments, l'unité de temps et le relativedelta instance à partir de laquelle les unités de temps doivent être récupérées. Si la durée n'est pas égale à zéro, alors time_amount () renvoie une chaîne avec la quantité de temps et l'unité de temps. Sinon, il renvoie une chaîne vide.

Tu utilises time_amount() in the comprehension on line 17. That line creates a generator storing the non-empty strings returned from time_amount(). It uses the walrus operator to assign the return value of time_amount() à t and includes t only if it is Vrai.

Finally, line 18 prints the final output using .join() on the generator. Next, you’ll take a look at including the PyCon date in the output from your script.

Showing the PyCon Date in Your PyCon Countdown

Earlier, you learned about creating datetime instances using .strptime(). This method uses a special mini-language within Python to specify how the date string is formatted.

Python datetime has an additional method called .strftime() that allows you to format a datetime instance to a string. In a sense, it’s the reverse operation of parsing using .strptime(). You can differentiate between the two methods by remembering that the p in .strptime() stands for parse, et le F in .strftime() stands for format.

In your PyCon countdown, you can use .strftime() to print output to let the user know the date on which PyCon US will start. Remember, you can find the formatting codes that you want to use on strftime.org. Now add this code on line 18 of your PyCon countdown script:

18 pycon_date_str = PYCON_DATE.strftime("%A, %B %d, %Y at %H:%M %p %Z")
19 impression(F"PyCon US 2021 will start on:", pycon_date_str)
20 impression("Countdown to PyCon US 2021:", ",".joindre(output))

In this code, line 18 uses .strftime() to create a string representing the starting date of PyCon US 2021. The output includes the weekday, month, day, year, hour, minute, AM or PM, and time zone:

Wednesday, May 12, 2021 at 08:00 AM EDT

Sur line 19, you print this string for the user to see with some explanatory text. The last line prints the amount of time remaining until the PyCon start date. Next, you’ll finish your script to make it easier for other people to reuse.

Finalizing Your PyCon Countdown

The final step that you’ll want take is to follow Python best practices and put the code that produces output into a main() function. You can check out the full, final code after applying all these changes:

    1 # pyconcd.py
    2 
    3 de dateutil importation parser, tz
    4 de dateutil.relativedelta importation relativedelta
    5 de datetime importation datetime
    6 
    7 PYCON_DATE = parser.parse("May 12, 2021 8:00 AM")
    8 PYCON_DATE = PYCON_DATE.remplacer(tzinfo=tz.gettz("America/New_York"))
    9 
dix def time_amount(time_unit: str, countdown: relativedelta) -> str:
11     t = getattr(countdown, time_unit)
12     revenir F"t time_unit" if t != 0 autre ""
13 
14 def principale():
15     maintenant = datetime.maintenant(tz=tz.tzlocal())
16     countdown = relativedelta(PYCON_DATE, maintenant)
17     time_units = [[[["years", "months", "days", "hours", "minutes", "seconds"]
18     output = (t pour tu in time_units if (t := time_amount(tu, countdown)))
19     pycon_date_str = PYCON_DATE.strftime("%A, %B %d, %Y at %H:%M %p %Z")
20     impression(F"PyCon US 2021 will start on:", pycon_date_str)
21     impression("Countdown to PyCon US 2021:", ",".joindre(output))
22 
23 if __Nom__ == "__main__":
24     principale()

In this code, you move print() and the code used for the generator into main(). Sur line 23, you use the guard clause to make sure that main() only runs when this file is executed as a script. This allows other people to import your code and reuse PYCON_DATE, for instance, if they’d like.

Now you can modify this script as much as you want. One neat thing to do might be to allow the user to change the time zone associated with maintenant by passing a command-line argument. You could also change the PYCON_DATE to something closer to home, say PyCon Africa or EuroPython.

To get even more excited about PyCon, check out Real Python at PyCon US 2019 and How to Get the Most Out of PyCon!

Alternatives to Python datetime et dateutil

Python datetime et dateutil are a powerful combination of libraries when you’re working with dates and times. dateutil is even recommended in the Python documentation. However, there are many other libraries that you can use to work with dates and times in Python. Some of these rely on datetime et dateutil, while others are completely independent replacements:

  • pytz provides time zone information similar to dateutil. It uses a somewhat different interface than the standard datetime.tzinfo, so be aware of the potential problems if you decide to use it.
  • Arrow provides a drop-in replacement for datetime. It’s inspired by moment.js, so if you’re coming from web development, then this might be a more familiar interface.
  • Pendulum provides another drop-in replacement for datetime. It includes a time zone interface and an improved timedelta implementation.
  • Maya provides a similar interface as datetime. It relies on Pendulum for parts of the parsing library.
  • dateparser provides an interface to generate datetime instances from human-readable text. It’s flexible and supports many languages.

In addition, if you work heavily with NumPy, Pandas, or other data science packages, then there are a few options that might be useful to you:

  • NumPy provides a similar API to the built-in Python datetime library, but the NumPy version can be used in arrays.
  • Pandas provides support for time-series data in DataFrames, usually sequential values of time-based events, by using the NumPy datetime module.
  • cftime provides support for calendars other than the proleptic Gregorian calendar as well as other time units conforming to the Climate and Forecasting (CF) conventions. It’s used by the xarray package to provide time-series support.

Lectures complémentaires

Since programming with time can be so complicated, there are many resources on the web to help you learn more about it. Fortunately, this is a problem that many people who work in every programming language have thought about, so you can usually find information or tools to help with any problem you may have. Here’s a selected list of articles and videos that I found helpful in writing this tutorial:

In addition, Paul Ganssle is a core contributor to CPython and the current maintainer of dateutil. His articles and videos are a great resource for Python users:

Conclusion

In this tutorial, you learned about programming with dates and times and why it often leads to errors and confusion. You also learned about the Python datetime et dateutil modules as well as how to work with time zones in your code.

Now you can:

  • Store dates in a good, future-proof format in your programs
  • Créer Python datetime instances with formatted strings
  • Ajouter time zone information to datetime instances with dateutil
  • Effectuer arithmetic operations with datetime instances using relativedelta

In the end, you created a script that counts down the time remaining until the next PyCon US so you can get excited for the biggest Python gathering around. Dates and times can be tricky, but with these Python tools in your arsenal, you’re ready to tackle the toughest problems!