403 votes

Pourquoi la fonction datetime.datetime.utcnow() ne contient-elle pas d'informations sur le fuseau horaire ?

datetime.datetime.utcnow()

Pourquoi est-ce que datetime n'a pas d'information sur le fuseau horaire, étant donné qu'il s'agit explicitement d'un système UTC. datetime ?

Je m'attendrais à ce qu'il contienne tzinfo .

0 votes

Comment convertir un champ date au format iso normal qui est de type string en format utc ?

281voto

Craig McQueen Points 13194

Notez qu'à partir de Python 3.2, la fonction datetime Le module contient datetime.timezone . La documentation pour datetime.utcnow() dit :

Une date UTC actuelle connue peut être obtenue en appelant datetime.now(timezone.utc) .

Donc, datetime.utcnow() ne fixe pas tzinfo pour indiquer qu'il s'agit d'une UTC, mais datetime.now(datetime.timezone.utc) renvoie l'heure UTC avec tzinfo set.

Donc vous pouvez le faire :

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

2 votes

Laquelle est préférée ? datetime.now(timezone.utc) o datetime.utcnow(timezone.utc) ?

13 votes

datetime.utcnow() ne prend aucun argument. Il faudrait donc que ce soit datetime.now(timezone.utc) .

1 votes

datetime.now() retournera l'heure de la machine mais datetime.utcnow() retournera l'heure UTC actuelle.

241voto

gnibbler Points 103484

Cela signifie qu'il ne tient pas compte du fuseau horaire, et que vous ne pouvez pas l'utiliser avec datetime.astimezone

vous pouvez lui donner un fuseau horaire comme ceci

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

vous pouvez maintenant changer de fuseau horaire

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")))

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

277 votes

Mais il n'y a aucune raison pour que ce soit un fuseau horaire naïf - il est spécifié que c'est UTC. Pourquoi faut-il chercher une bibliothèque tierce pour que cela fonctionne correctement ?

0 votes

Je pense que c'est peut-être une question de licence, donc pytz ne peut pas être inclus dans la stdlib.

5 votes

Je suis d'accord ; pour moi, les temps "naïfs" sont complètement inutiles. Il y a une discussion sur la liste python en ce moment à propos de l'ajout de pytz à la stdlib ; le problème n'est pas la licence mais le fait que les données de fuseau horaire sont mises à jour si souvent (ce que Python lui-même ne peut pas faire). De plus, pytz n'implémente pas l'interface tzinfo de la manière attendue et vous pouvez obtenir des erreurs si vous essayez d'utiliser certains des fuseaux horaires des villes dans astimezone . Ainsi, non seulement datetime n'a pas de fuseaux horaires natifs, mais la seule implémentation largement disponible de tzinfo n'est pas conforme à la norme supposée.

82voto

Mark Ransom Points 132545

Les bibliothèques Python standard n'ont pas inclus de classes tzinfo avant Python 3.2. Je ne peux que deviner les raisons. Personnellement, je pense que c'était une erreur de ne pas inclure une classe tzinfo pour UTC, car celle-ci est assez peu controversée pour avoir une implémentation standard. Bien qu'il n'y ait pas d'implémentation dans la bibliothèque, il y en a une qui est donnée en exemple dans le fichier tzinfo documentation .

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()

Une fois que vous avez un UTC tzinfo vous ne pouvez toujours pas l'utiliser avec l'objet utcnow . Pour obtenir l'heure actuelle sous la forme d'un objet datetime conscient :

from datetime import datetime 

now = datetime.now(utc)

Dans Python 3.2, ils ont finalement mis en place une UTC tzinfo dans la bibliothèque :

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)

Dans Python 3.9, ils ont créé tzinfo des classes pour tous les autres fuseaux horaires. Voir PEP 615 -- Support de la base de données des fuseaux horaires de l'IANA dans la bibliothèque standard pour tous les détails.

8 votes

Allez comprendre pourquoi cette classe n'a pas été fournie en premier lieu (et, plus important encore, pourquoi elle a servi à datetime les objets créés par utcnow() )...

20 votes

L'objet fuseau horaire timezone.utc a finalement été ajouté à Python 3.2. Pour la rétrocompatibilité, utcnow() renvoie toujours un objet temps sans fuseau horaire, mais vous pouvez obtenir ce que vous voulez en appelant now(timezone.utc) .

5 votes

@rgove, c'est le genre de redressement des torts qui était censé être juste pour Python 3. Ils n'auraient pas dû s'inquiéter de la rétrocompatibilité. Il y a un autre exemple que j'ai lu au cours des derniers jours - l' struct effectuerait des conversions automatiques d'Unicode à bytestring, et la décision finale a été de rompre la compatibilité avec les versions antérieures de Python 3 pour éviter qu'une mauvaise décision ne soit prise.

21voto

bbengfort Points 451

Le site pytz Le module est une option, et il y en a une autre python-dateutil qui, bien qu'il s'agisse également d'un paquet tiers, peut déjà être disponible en fonction de vos autres dépendances et de votre système d'exploitation.

Je voulais juste inclure cette méthodologie pour référence- si vous avez déjà installé python-dateutil à d'autres fins, vous pouvez utiliser son tzinfo au lieu de 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())

Je suis plutôt d'accord pour dire que les appels à utcnow devrait inclure les informations sur le fuseau horaire UTC. Je soupçonne que ces informations ne sont pas incluses parce que la bibliothèque native datetime utilise par défaut des dates naïves pour des raisons de compatibilité croisée.

1 votes

NameError : le nom 'dt' n'est pas défini.

0 votes

J'utilisais l'appel datetime.datetime.utcfromtimestamp(), et j'avais besoin d'ajouter tzinfo, La deuxième solution a fonctionné pour moi : utcdt = datetime.datetime.utcfromtimestamp(1234567890).replace(dateu‌​til.tz.tzutc())

1 votes

Note : contrairement à datetime.now(pytz_tz) qui fonctionne toujours ; datetime.now(dateutil.tz.tzlocal()) peut échouer pendant les transitions DST . PEP 495 -- Désambiguïsation de l'heure locale pourrait améliorer dateutil à l'avenir.

-6voto

from datetime import datetime 
from dateutil.relativedelta import relativedelta
d = datetime.now()
date = datetime.isoformat(d).split('.')[0]
d_month = datetime.today() + relativedelta(months=1)
next_month = datetime.isoformat(d_month).split('.')[0]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X