2013-03-09 5 views
61

Ich versuche, das aktuelle Datum und die Uhrzeit mit Datum und Uhrzeit in Modellen Operatoren Vergleich angegeben zu vergleichen:Kann nicht vergleichen naiv und bewusst datetime.now() <= challenge.datetime_end

if challenge.datetime_start <= datetime.now() <= challenge.datetime_end: 

Das Skript mit Fehlern aus:

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

Die Modelle sehen wie folgt aus:

class Fundraising_Challenge(models.Model): 
    name = models.CharField(max_length=100) 
    datetime_start = models.DateTimeField() 
    datetime_end = models.DateTimeField() 

I locale auch django haben mit Datum und Uhrzeit.

Was ich nicht finden konnte, ist das Format, das django für DateTimeField() verwendet. Ist es naiv oder bewusst? Und wie bekomme ich datetime.now() um locale datetime zu erkennen?

+2

http://stackoverflow.com/questions/10652819/django-1-4-cant-compare-offset-naive-and-offset-aware-datetimes – catherine

+2

möglich Duplikat [Kann nicht subtrahieren Offset- naive und Offset-bewusste Datumsangaben] (http://stackoverflow.com/questions/796008/cant-subtract-offset-na-ive-and-offset-aware-datetimes) – user1023979

Antwort

46

Standardmäßig ist das datetime Objekt naive in Python, so dass Sie beide entweder naiv oder bewusst datetime Objekte machen müssen. Dies kann mit Hilfe getan:

import datetime 
import pytz 

utc=pytz.UTC 

challenge.datetime_start = utc.localize(challenge.datetime_start) 
challenge.datetime_end = utc.localize(challenge.datetime_end) 
# now both the datetime objects are aware, and you can compare them 

Hinweis: Dies würde heben ein ValueError wenn tzinfo bereits gesetzt ist. Wenn Sie das nicht sicher sind, verwenden Sie einfach

start_time = challenge.datetime_start.replace(tzinfo=utc) 
end_time = challenge.datetime_end.replace(tzinfo=utc) 

BTW, Sie wie folgt

d = datetime.datetime.utcfromtimestamp(int(unix_timestamp)) 
d_with_tz = datetime.datetime(
    year=d.year, 
    month=d.month, 
    day=d.day, 
    hour=d.hour, 
    minute=d.minute, 
    second=d.second, 
    tzinfo=pytz.UTC) 
+0

Es sagt: ValueError: Nicht naive Datetime (tzinfo ist bereits gesetzt) wenn es versucht zu berechnen: datetimeStart = utc.localize (challenge.datetime_start) – Scott

+0

yep, es löst ValueError. –

+0

Ich habe die Antwort aktualisiert –

49

datetime.datetime.now einen UNIX-Zeitstempel in datetime.datetime Objekt mit Zeitzone Info-Format könnte, ist nicht bekannt, Zeitzone.

Django kommt mit einem Helfer dafür, die pytz

from django.utils import timezone 
now = timezone.now() 

Sie erfordert sollten now-challenge.datetime_start

+1

Wenn 'USE_TZ = True' ist, gibt' timezone.now() 'ein zeitzonenbewußtes Datetime-Objekt zurück, auch wenn' pytz' nicht installiert ist (obwohl es aus anderen Gründen empfehlenswert wäre, es zu installieren). – jfs

2

So ist die Art, wie ich dieses Problem lösen würde, ist um sicherzustellen, dass die beiden Datetimes vergleichen können sind in der richtigen Zeitzone.

Ich kann sehen, dass Sie datetime.now() verwenden, die die aktuelle Zeit des Systems zurückgibt, ohne TZinfo gesetzt.

tzinfo ist die Information, die an eine datetime angehängt wird, um sie darüber zu informieren, in welcher Zeitzone sie sich befindet. Wenn Sie naive datetime verwenden, müssen Sie konsistent sein. Ich würde nur sehr empfehlen datetime.utcnow()

Sehen Verwendung als irgendwo Ihre schaffen Datetime, die mit ihnen Tzinfo verknüpft haben, was Sie tun müssen, um sicherzustellen, diejenigen lokalisiert sind (hat Tzinfo verbunden sind) auf die richtige Zeitzone.

Werfen Sie einen Blick auf Delorean, es macht den Umgang mit dieser Art von Sache viel einfacher.

+3

Sie sehen dieses Problem auch mit utcnow. –

22

eine Zeile Code Lösung

if timezone_aware_var <= datetime.datetime.now(timezone_aware_var.tzinfo): 
    pass #some code 

erklärt Version:

# Timezone info of your timezone aware variable 
timezone = your_timezone_aware_variable.tzinfo 

# Current datetime for the timezone of your variable 
now_in_timezone = datetime.datetime.now(timezone) 

# Now you can do a fair comparison, both datetime variables have the same time zone 
if your_timezone_aware_variable <= now_in_timezone: 
    pass #some code 

Zusammenfassung:
Sie müssen die Zeitzone weitere Infos auf die now() Datumzeit hinzuzufügen.
Sie müssen jedoch die gleiche Zeitzone der Referenzvariablen hinzufügen; deshalb lese ich zuerst das tzinfo Attribut.

0

Zeitzone deaktivieren. Verwenden challenge.datetime_start.replace(tzinfo=None);

Sie können auch replace(tzinfo=None) für andere Datetime verwenden.

if challenge.datetime_start.replace(tzinfo=None) <= datetime.now().replace(tzinfo=None) <= challenge.datetime_end.replace(tzinfo=None): 
Verwandte Themen