web-dev-qa-db-fra.com

Python datetime strptime () et strftime (): comment conserver les informations du fuseau horaire

Voir le code suivant:

import datetime
import pytz

fmt = '%Y-%m-%d %H:%M:%S %Z'

d = datetime.datetime.now(pytz.timezone("America/New_York"))
d_string = d.strftime(fmt)
d2 = datetime.datetime.strptime(d_string, fmt)
print d_string 
print d2.strftime(fmt)

la sortie est

2013-02-07 17:42:31 EST
2013-02-07 17:42:31 

Les informations de fuseau horaire se sont tout simplement perdues dans la traduction.

Si je bascule '% Z' en '% z', je reçois

ValueError: 'z' is a bad directive in format '%Y-%m-%d %H:%M:%S %z'

Je sais que je peux utiliser python-dateutil, mais je viens juste de constater que c’est grave que je ne puisse pas obtenir cette fonctionnalité simple dans datetime et que je devrais introduire plus de dépendance?

49
CodeNoob

Une partie du problème ici est que les chaînes habituellement utilisées pour représenter les fuseaux horaires ne sont pas uniques. "EST" signifie uniquement "Amérique/New_York" pour les Nord-Américains. C’est une limitation de l’API d’heure C et la solution Python permet… d’ajouter des fonctionnalités tz complètes dans une version future à tout moment maintenant, si quelqu'un souhaite écrire le PEP.

Vous pouvez formater et analyser un fuseau horaire comme décalage, mais cela perd les informations de l'heure d'été/heure d'été (par exemple, vous ne pouvez pas distinguer "America/Phoenix" de "America/Los_Angeles" en été) . Vous pouvez formater un fuseau horaire sous forme d'abréviation de 3 lettres, mais vous ne pouvez pas le réanalyser à partir de cela.

Si vous voulez quelque chose de flou et d’ambiguïté mais que vous voulez en général, vous avez besoin d’une bibliothèque tierce comme dateutil.

Si vous voulez quelque chose qui soit sans ambiguïté, ajoutez simplement vous-même le nom de tz à la chaîne de date/heure locale et séparez-le à l'autre bout:

d = datetime.datetime.now(pytz.timezone("America/New_York"))
dtz_string = d.strftime(fmt) + ' ' + "America/New_York"

d_string, tz_string = dtz_string.rsplit(' ', 1)
d2 = datetime.datetime.strptime(d_string, fmt)
tz2 = pytz.timezone(tz_string)

print dtz_string 
print d2.strftime(fmt) + ' ' + tz_string

Ou… à mi-chemin, vous utilisez déjà la bibliothèque pytz, qui peut analyser (selon certaines règles de désambiguïsation arbitraires mais bien définies) des formats tels que "EST". Donc, si vous voulez vraiment, vous pouvez laisser le %Z Du côté de la mise en forme, puis le retirer et l’analyser avec pytz.timezone() avant de passer le reste à strptime .

31
abarnert

Malheureusement, strptime() ne peut gérer que le fuseau horaire configuré par votre système d'exploitation, puis uniquement comme un décalage temporel. De la documentation :

La prise en charge de la directive %Z Est basée sur les valeurs contenues dans tzname et sur le fait que daylight soit vrai. Pour cette raison, il est spécifique à la plate-forme, à l'exception de la reconnaissance des heures UTC et GMT qui sont toujours connues (et considérées comme des fuseaux horaires ne respectant pas l'heure d'été).

strftime() ne supporte pas officiellement %z.

J'ai bien peur que vous soyez bloqué avec python-dateutil Afin de prendre en charge l'analyse du fuseau horaire.

11
Martijn Pieters

Voici ma réponse dans Python 2.7

Imprimer l'heure actuelle avec le fuseau horaire

from datetime import datetime
import tzlocal  # pip install tzlocal

print datetime.now(tzlocal.get_localzone()).strftime("%Y-%m-%d %H:%M:%S %z")

Imprimer l'heure actuelle avec un fuseau horaire spécifique

from datetime import datetime
import pytz # pip install pytz

print datetime.now(pytz.timezone('Asia/Taipei')).strftime("%Y-%m-%d %H:%M:%S %z")

Il va imprimer quelque chose comme

2017-08-10 20:46:24 +0800
1
Johnny