102 votes

Comment vérifier si un objet datetime est localisé avec pytz ?

Je veux stocker un objet datetime avec un fuseau horaire UTC localisé. La méthode qui stocke l'objet datetime peut recevoir un objet datetime (naïf) non localisé ou un objet qui a déjà été localisé. Comment puis-je déterminer si la localisation est nécessaire ?

Code avec condition if manquante :

class MyClass:
  def set_date(self, d):
    # what do i check here?
    # if(d.tzinfo):
      self.date = d.astimezone(pytz.utc)
    # else:
      self.date = pytz.utc.localize(d)

177voto

J.F. Sebastian Points 102961

Comment déterminer si une localisation est nécessaire ?

De datetime docs :

  • un objet date-heure d est conscient si :

    d.tzinfo is not None and d.tzinfo.utcoffset(d) is not None
  • d est naïf si :

    d.tzinfo is None or d.tzinfo.utcoffset(d) is None

Bien que si d est un objet datetime représentant le temps dans le fuseau horaire UTC, vous pouvez l'utiliser dans les deux cas :

self.date = d.replace(tzinfo=pytz.utc)

Cela fonctionne indépendamment d est sensible au fuseau horaire ou naïf.

Note : n'utilisez pas datetime.replace() méthode avec un fuseau horaire avec un décalage utc non fixe (il est possible de l'utiliser avec le fuseau horaire UTC, mais sinon vous devriez utiliser tz.localize() méthode).

0 votes

Je sais que c'est ce que dit la documentation, mais dans quel scénario peut-on avoir un objet tzinfo qui ne spécifie pas vraiment de fuseau horaire et donc d.tzinfo.utcoffset(d) is None est nécessaire ?

1 votes

@Geekfish : aucune idée. Toutes les implémentations saines devraient soit retourner une valeur différente de None, soit lever une exception.

3 votes

Depuis Python 3.6 astimezone peut être appelé sur des instances naïves et il suppose le fuseau horaire du système.

26voto

Cédric Julien Points 24177

Si vous voulez vérifier si un objet datetime 'd' est localisé, vérifiez le d.tzinfo, si c'est None, pas de localisation.

0 votes

Mais que faire s'il a un objet tzinfo qui n'est pas de pytz ?

10 votes

Note : il ne suffit pas de vérifier si d.tzinfo is not None . Aussi, d.tzinfo.utcoffset(d) ne devrait pas être None para d pour être appelé un objet datetime conscient .

3 votes

Cette réponse n'est pas vraie, voici la définition de quand il est naïf ou conscient, de datetime docs officiels : "Un objet de type time ou datetime peut être naïf ou aware. Un objet datetime d est aware si d.tzinfo n'est pas None et si d.tzinfo.utcoffset(d) ne retourne pas None. Si d.tzinfo est None, ou si d.tzinfo n'est pas None mais que d.tzinfo.utcoffset(d) renvoie None, d est naïf. Un objet temporel t est conscient si t.tzinfo n'est pas None et que t.tzinfo.utcoffset(None) ne renvoie pas None. Sinon, t est naïf".

14voto

Derek R. Points 21

Voici une fonction qui résume la première réponse.

def tz_aware(dt):
    return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None

2 votes

Et retour None le reste du temps ?

1 votes

Il suffit de dire return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None

3voto

eiTan LaVi Points 1084

Voici une fonction plus complète pour convertir ou contraindre un timestamp obj en utc. Si elle atteint l'exception, cela signifie que le timestamp n'est pas localisé. Puisque c'est une bonne pratique de toujours travailler en UTC dans le code, cette fonction est très utile au niveau d'entrée de la persistance.

def convert_or_coerce_timestamp_to_utc(timeobj):
        out = timeobj
        try:
            out = timeobj.astimezone(pytz.utc) # aware object can be in any timezone
        except (ValueError,TypeError) as exc: # naive
            out = timeobj.replace(tzinfo=pytz.utc)
        return out

Le petit ajout par rapport au "try catch" de la réponse de J.F. Sebastian est la condition supplémentaire "catch", sans laquelle tous les cas naïfs ne seront pas pris en compte par la fonction.

0 votes

Pourquoi attrapez-vous TypeError également ? Je ne vois pas cela mentionné dans les autres réponses.

0 votes

Comme je l'ai écrit, sans la prise supplémentaire, tous les cas naïfs ne seront pas pris en compte. Il s'agit simplement d'un ajout basé sur une expérience directe. A l'origine, j'avais travaillé avec la première capture seule, et certains timestamps naïfs sont passés au travers :)

0 votes

La réponse pourrait être améliorée si vous montriez un exemple spécifique d'un objet naïf qui jette TypeError ici.

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