Comment faire un pas au courant datetime fuseau horaire courant en python
Ce que je dois faire
J'ai un fuseau horaire n'est pas au courant objet datetime, pour lequel j'ai besoin d'ajouter un fuseau horaire afin d'être en mesure de le comparer avec d'autres fuseau horaire-conscient datetime objets. Je ne veux pas convertir la totalité de mon application à ignorer le fuseau horaire pour ce un héritage de cas.
Ce que j'ai Essayé
Tout d'abord, pour illustrer le problème:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> unaware = datetime.datetime(2011,8,15,8,15,12,0)
>>> unaware
datetime.datetime(2011, 8, 15, 8, 15, 12)
>>> aware = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)
>>> aware
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> aware == unaware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
Tout d'abord, j'ai essayé astimezone:
>>> unaware.astimezone(pytz.UTC)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime
>>>
Il n'est pas très surprenant, cela a échoué, car c'est en fait essayer de faire une conversion. Remplacer semblait être un meilleur choix (comme par Python: Comment faire pour obtenir une valeur de type datetime.aujourd'hui() qui est "timezone conscient"?):
>>> unaware.replace(tzinfo=pytz.UTC)
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> unaware == aware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
>>>
Mais comme vous pouvez le voir, remplacez semble définir la tzinfo, mais de ne pas faire l'objet courant. Je suis prêt à tomber en arrière en raclant la chaîne d'entrée pour avoir un fuseau horaire avant l'analyse (je suis en utilisant dateutil pour l'analyse, si ce qui compte), mais qui semble incroyablement encombrants.
Aussi, j'ai essayé cette fois de la version 2.6 de python et python 2.7, avec les mêmes résultats.
Contexte
Je suis en train d'écrire un analyseur syntaxique pour certains fichiers de données. Il y a un vieux format que j'ai besoin de soutien, où la date chaîne de ne pas avoir un fuseau horaire indicateur. J'ai déjà corrigé la source de données, mais j'ai encore besoin à l'appui de l'héritage de format de données. Un temps de conversion de l'héritage de données n'est pas une option pour diverses affaires BS raisons. Bien qu'en général, je n'aime pas l'idée de coder en dur un fuseau horaire par défaut, dans ce cas, il semble que la meilleure option. Je sais avec une certitude raisonnable que tous les anciens de données en question est en UTC, donc je suis prêt à accepter le risque de défaut dans ce cas.
unaware.replace()
serait de retourNone
si c'était la modification deunaware
objet en place. Le REPL montre que.replace()
retourne une nouvelledatetime
objet ici.- Ce que j'ai besoin quand je suis venu ici:
import datetime; datetime.datetime.now(datetime.timezone.utc)
- Je voudrais utiliser le nommé
tz
arg pour être plus lisible:datetime.datetime.now(tz=datetime.timezone.utc)
Vous devez vous connecter pour publier un commentaire.
En général, pour faire un naïf datetime fuseau horaire-courant, utilisez la localiser méthode:
Pour le fuseau horaire UTC, il n'est pas vraiment nécessaire d'utiliser
localize
car il n'y a pas de passage à l'heure avancée calcul de la poignée:œuvres. (
.replace
renvoie un nouvel objet de type datetime; elle ne modifie pasunaware
.)aware = datetime(..., tz)
, utilisez.localize()
à la place.tz.localize(..., is_dst=None)
affirme qu'il ne l'est pas .localize
appelle simplement.replace(tzinfo= ... )
à condition que vous l'a appelé sur son ignorancedatetime
; autre chose déclenche une exception. Je ne vois pas de quoi pour faire des calculs.pytz.utc.localize
, mais certains des autres fuseaux horaires d'effectuer des calculs.DstTzInfo
,localize
est défini comme ceci.unaware = aware.tzinfo.localize(unaware)
. Cela implique cependant que la connaissance de l'objet a pytz fuseau horaire de l'objet.replace()
et tout simplement la mise enunaware.tzinfo = datetime.timezone.utc
?Tous ces exemples utilisent un module externe, mais vous pouvez obtenir le même résultat en utilisant simplement le module datetime, comme présenté dans cette SORTE de réponse:
Moins de dépendance et ne pytz questions.
REMARQUE: Si vous souhaitez utiliser ce avec python3 et python2, vous pouvez l'utiliser aussi bien pour le fuseau horaire à l'importation (codé en dur pour UTC):
pytz
questions, je suis heureux, je défile vers le bas un peu! N'a pas envie de s'attaquer avecpytz
sur mes serveurs distants en effet 🙂from datetime import timezone
travaille dans py3 mais pas py2.7.dt.replace(tzinfo=timezone.utc)
renvoie un nouvel objet de type datetime, elle ne modifie pasdt
en place. (Je vais modifier pour afficher ce).from datetime import tzinfo
lors de la définition deutc
à l'exception de chemin.replace()
permettrait de compenser la date / heure par qui, et pas le décalage actuel de "01:00". résultant dans la folie comme>>> tz.normalize(datetime.strptime('2019-02-12', '%Y-%m-%d').replace(tzinfo=tz)).isoformat() '2019-02-12T23:55:00+01:00'
une meilleure utilisation de localiser:>>> tz.localize(datetime.datetime.strptime('2019-02-12', '%Y-%m-%d')).isoformat() '2019-02-12T00:00:00+01:00'
tz = pytz.timezone('America/Chicago')
J'avais utilisation de dt_aware à dt_unaware
et dt_unware à dt_aware
mais la réponse avant est également une bonne solution.
localtz.localize(dt_unware, is_dst=None)
de lever une exception sidt_unware
représente non-existant ou ambiguë, heure locale (note: il n'y avait pas ce problème avec la version précédente de votre réponse oùlocaltz
est UTC parce que l'heure UTC n'a pas de transitions d'heure d'étéJe utiliser cette instruction dans Django pour convertir un ignorant le temps, à une connaissance:
Je suis d'accord avec les réponses précédentes, et est très bien si vous êtes ok pour démarrer en UTC. Mais je pense que c'est aussi un scénario commun pour les gens à travailler avec un tz conscient de la valeur qu'a un datetime qui a un non UTC fuseau horaire local.
Si vous deviez juste aller par le nom, on ne serait probablement en déduire replace() sera applicable et de produire le droit datetime connaissance de l'objet. Ce n'est pas le cas.
le remplacer( tzinfo=... ) semble être aléatoire, dans son comportement. Il est par conséquent inutile. Ne pas utiliser ce!
localiser correcte est la fonction à utiliser. Exemple:
Ou un exemple plus complet:
me donne un fuseau horaire courant valeur de type datetime de l'heure locale actuelle:
replace(tzinfo=...)
sur un fuseau horaire autre que l'UTC va encrasser votre datetime. J'ai eu-07:53
au lieu de-08:00
par exemple. Voir stackoverflow.com/a/13994611/1224827Ce codifie @Sérgio et @unutbu de réponses. Il "fonctionne" avec une
pytz.timezone
objet ou un IANA fuseau Horaire chaîne.Cela semble être ce que
datetime.localize()
(ou.inform()
ou.awarify()
) faut le faire, accepter les deux chaînes et le fuseau horaire des objets pour le tz argument et par défaut à l'UTC si pas de temps horaire est spécifié.Afin d'ajouter de fuseau horaire local; (à l'aide de dateutil)
.replace(tzinfo=dateutil.tz.UTC)
deux méthode je sais purement
ou
bien sûr,vous pouvez utiliser n'importe quel fuseau horaire à la place de l'UTC,
code naive = datetime.now() LOCAL_TZ = pytz.timezone('Europe/Paris') aware1 = naive.replace(tzinfo=LOCAL_TZ) # naive+00:09 aware2 = LOCAL_TZ.localize(naive) # naive+01:00
Basé sur le suivant article j'ai choisi d'aller avec la deuxième date.Dans le format de unutbu de réponse; j'ai fait un module d'utilitaire qui gère ce genre de choses, avec plus intuitive de la syntaxe. Peut être installé avec le pip.