368 votes

On ne peut pas soustraire les dates qui ne tiennent pas compte du décalage et celles qui tiennent compte du décalage.

J'ai une conscience du fuseau horaire timestamptz dans PostgreSQL. Lorsque je tire des données de la table, je veux ensuite soustraire l'heure actuelle pour obtenir l'âge.

Le problème que j'ai est que les deux datetime.datetime.now() y datetime.datetime.utcnow() semblent renvoyer des timestamps sans fuseau horaire, ce qui entraîne cette erreur :

TypeError: can't subtract offset-naive and offset-aware datetimes 

Existe-t-il un moyen d'éviter cela (de préférence sans utiliser de module tiers) ?

EDIT : Merci pour les suggestions, cependant essayer d'ajuster le fuseau horaire semble me donner des erreurs donc je vais juste utiliser des timestamps sans fuseau horaire dans PG et toujours insérer en utilisant :

NOW() AT TIME ZONE 'UTC'

De cette façon, tous mes timestamps sont UTC par défaut (même si c'est plus ennuyeux de le faire).

9voto

Ashok Joshi Points 379

J'ai également rencontré le même problème. J'ai ensuite trouvé une solution après de nombreuses recherches.

Le problème est que lorsque nous obtenons l'objet datetime à partir du modèle ou du formulaire, il est conscient du décalage et si nous obtenons l'heure par système, c'est décalage naïf .

Donc ce que j'ai fait c'est que j'ai obtenu l'heure actuelle en utilisant timezone.now() et importez le fuseau horaire par from django.utils import timezone et mettre le USE_TZ = Vrai dans le fichier de paramètres de votre projet.

6voto

erjiang Points 14724

Le module psycopg2 a ses propres définitions de fuseaux horaires, donc j'ai fini par écrire mon propre wrapper autour de utcnow :

def pg_utcnow():
    import psycopg2
    return datetime.utcnow().replace(
        tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=0, name=None))

et utiliser simplement pg_utcnow chaque fois que vous avez besoin de l'heure actuelle pour la comparer à une valeur de référence PostgreSQL. timestamptz

0 votes

Tout objet tzinfo qui renvoie un offset utc nul fera l'affaire, par exemple .

5voto

John L. Stanley Points 51

J'ai trouvé une solution ultra-simple :

import datetime

def calcEpochSec(dt):
    epochZero = datetime.datetime(1970,1,1,tzinfo = dt.tzinfo)
    return (dt - epochZero).total_seconds()

Il fonctionne aussi bien avec des valeurs de date tenant compte du fuseau horaire qu'avec des valeurs de date ne tenant pas compte du fuseau horaire. Et aucune bibliothèque supplémentaire ou solution de contournement de base de données n'est requise.

2voto

user654914 Points 91

J'ai trouvé timezone.make_aware(datetime.datetime.now()) est utile dans django (je suis sur 1.9.1). Malheureusement, vous ne pouvez pas simplement faire un datetime l'objet est sensible au décalage, alors timetz() il. Vous devez faire un datetime et faire des comparaisons sur cette base.

2voto

Dave Points 891

La réponse la plus directe à la question posée dans le titre semble manquer :

naive_date.replace(tzinfo=aware_date.tzinfo) - aware_date

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