web-dev-qa-db-fra.com

Pourquoi datetime.datetime.utcnow () ne contient-il pas les informations de fuseau horaire?

datetime.datetime.utcnow()

Pourquoi cette datetime n'a-t-elle aucune information de fuseau horaire étant donné qu'il s'agit explicitement d'une UV datetime?

Je pense que cela contiendrait tzinfo.

205
Vitaly Babiy

Cela signifie que le fuseau horaire est naïf, vous ne pouvez donc pas l'utiliser avec datetime.astimezone

vous pouvez lui donner un fuseau horaire comme celui-ci

import pytz  # 3rd party: $ pip install pytz

u = datetime.utcnow()
u = u.replace(tzinfo=pytz.utc) #NOTE: it works only with a fixed utc offset

maintenant vous pouvez changer les fuseaux horaires

print(u.astimezone(pytz.timezone("America/New_York")))

Pour obtenir l'heure actuelle dans un fuseau horaire donné, vous pouvez passer tzinfo à datetime.now() directement:

#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz

print(datetime.now(pytz.timezone("America/New_York")))

Cela fonctionne pour tous les fuseaux horaires, y compris ceux qui respectent l'heure d'été, c'est-à-dire qu'ils fonctionnent avec des fuseaux horaires pouvant avoir différents décalages UTC à différents moments (décalage UTC non fixe). N'utilisez pas tz.localize(datetime.now()) - il peut échouer pendant la transition de fin DST lorsque l'heure locale est ambiguë.

163
John La Rooy

Notez que depuis Python 3.2, le module datetime contient datetime.timezone . La documentation de datetime.utcnow() dit:

Vous pouvez obtenir une date/heure UTC actuelle au courant en appelant datetime.now(timezone.utc).

Alors tu peux faire:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)
85
Craig McQueen

Les bibliothèques Python standard n'incluent aucune classe tzinfo (mais voir pep 431 ). Je ne peux que deviner les raisons. Personnellement, j’ai pensé que c’était une erreur de ne pas inclure de classe tzinfo pour UTC, parce que celle-ci est suffisamment controversée pour avoir une implémentation standard.

Edit: Bien qu'il n'y ait pas d'implémentation dans la bibliothèque, il y en a une donnée à titre d'exemple dans la documentation tzinfo .

from datetime import timedelta, tzinfo

ZERO = timedelta(0)

# A UTC class.

class UTC(tzinfo):
    """UTC"""

    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

Pour l'utiliser, pour obtenir l'heure actuelle en tant qu'objet date-heure conscient:

from datetime import datetime 

now = datetime.now(utc)

Il y a datetime.timezone.utc dans Python 3.2+:

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)
66
Mark Ransom

Le module pytz est une option. Il existe un autre python-dateutil, qui est également un package tiers, mais il est peut-être déjà disponible en fonction de vos autres dépendances et de votre système d'exploitation.

Je voulais juste inclure cette méthodologie à titre de référence. Si vous avez déjà installé python-dateutil à d'autres fins, vous pouvez utiliser sa tzinfo au lieu de la dupliquer avec pytz

import datetime
import dateutil.tz

# Get the UTC time with datetime.now:
utcdt = datetime.datetime.now(dateutil.tz.tzutc())

# Get the UTC time with datetime.utcnow:
utcdt = datetime.datetime.utcnow()
utcdt = utcdt.replace(tzinfo=dateutil.tz.tzutc())

# For fun- get the local time
localdt = datetime.datetime.now(dateutil.tz.tzlocal())

J'ai tendance à être d'accord pour dire que les appels à utcnow devraient inclure les informations de fuseau horaire UTC. Je soupçonne que cela n’est pas inclus car la bibliothèque de date/heure native utilise par défaut des dates/heures naïves pour assurer la compatibilité croisée. 

18
bbengfort

Julien Danjou a écrit un bon article expliquant pourquoi vous ne devriez jamais traiter avec les fuseaux horaires . Un extrait:

En effet, l'API Python datetime renvoie toujours des objets datetime non conscients, ce qui est très regrettable. En effet, dès que vous en aurez un objet, il n’ya aucun moyen de savoir quel est le fuseau horaire, donc ceux-ci les objets sont plutôt "inutiles" par eux-mêmes.

Hélas, même si vous pouvez utiliser utcnow(), vous ne verrez toujours pas les informations de fuseau horaire, comme vous l'avez découvert.

Recommandations:

  • Utilisez toujours des objets datetime, c’est-à-dire avec des informations de fuseau horaire. Cette s'assure que vous pouvez les comparer directement (les objets datetime conscients et non conscients ne sont pas comparables) et les renverra correctement aux utilisateurs . Utilisez pytz pour créer des objets de fuseau horaire. 

  • Utilisez ISO 8601 comme entrée et format de chaîne de sortie. Utilisez datetime.datetime.isoformat() pour retourner timestamps sous forme de chaîne formatée à l'aide de ce format, qui inclut le informations de fuseau horaire.

  • Si vous devez analyser des chaînes contenant des horodatages au format ISO 8601, vous pouvez compter sur iso8601, qui renvoie les horodatages avec le correct informations de fuseau horaire. Cela rend les horodatages directement comparables.

9
Joe D'Andrea

Pour ajouter des informations timezone dans Python 3.2+

import datetime

>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'
0
nordborn