Ce que je dois faire
J'ai un objet datetime sans fuseau horaire, auquel je dois ajouter un fuseau horaire afin de pouvoir le comparer avec d'autres objets datetime avec fuseau horaire. Je ne veux pas convertir l'ensemble de mon application en application sans fuseau horaire pour ce seul cas particulier.
Ce que j'ai essayé
Tout d'abord, pour démontrer 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
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 vraiment surprenant que cette opération échoue, puisqu'il s'agit en fait d'une tentative de conversion. Remplacer semblait être un meilleur choix (conformément à Python : Comment obtenir une valeur de datetime.today() qui soit "timezone aware" ? ) :
>>> 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, replace semble définir le tzinfo, mais ne rend pas l'objet conscient. Je suis sur le point de revenir à la modification de la chaîne d'entrée pour avoir un fuseau horaire avant de l'analyser (j'utilise dateutil pour l'analyse, si cela a de l'importance), mais cela semble incroyablement maladroit.
De plus, j'ai essayé ceci à la fois dans python 2.6 et python 2.7, avec les mêmes résultats.
Contexte
J'écris un analyseur syntaxique pour certains fichiers de données. Je dois prendre en charge un ancien format dans lequel la chaîne de date ne comporte pas d'indicateur de fuseau horaire. J'ai déjà corrigé la source de données, mais je dois encore prendre en charge l'ancien format de données. Une conversion unique des anciennes données n'est pas envisageable pour diverses raisons liées à la BS. 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, cela semble être la meilleure option. Je sais avec une confiance raisonnable que toutes les données anciennes en question sont en UTC, je suis donc prêt à accepter le risque d'utiliser ce fuseau par défaut dans ce cas.
2 votes
unaware.replace()
rendraitNone
s'il modifiaitunaware
en place. Le REPL montre que.replace()
renvoie un nouveaudatetime
objet ici.3 votes
Ce dont j'avais besoin quand je suis venu ici :
import datetime; datetime.datetime.now(datetime.timezone.utc)
4 votes
@MartinThoma J'utiliserais le nom de l'entreprise.
tz
arg pour être plus lisible :datetime.datetime.now(tz=datetime.timezone.utc)
1 votes
astimezone()
peut maintenant (à partir de 3.6) être appelé sur un objet naïf, et son paramètre peut (à partir de 3.3) être omis, de sorte que la solution est aussi simple queunaware.astimezone()