2012-05-18 19 views
77

Estoy en el proceso de migrar una aplicación de django 1.2 a 1.4.django 1.4 - no puedo comparar offset-ingenuo y offset date-datet

Tengo un objeto de tarea diaria que contiene una hora del día en que la tarea debe ser completada:

class DailyTask(models.Model): 
    time = models.TimeField() 
    last_completed = models.DateTimeField() 
    name = models.CharField(max_length=100) 
    description = models.CharField(max_length=1000) 
    weekends = models.BooleanField() 

    def __unicode__(self): 
     return '%s' % (self.name) 

    class Meta: 
     db_table = u'dailytask' 
     ordering = ['name'] 

Con el fin de comprobar si sigue siendo necesaria una tarea a realizar hoy, tengo el siguiente código:

def getDueDailyTasks(): 
    dueDailyTasks=[] 
    now = datetime.datetime.now() 
    try: 
     dailyTasks = DailyTask.objects.all() 
    except dailyTask.DoesNotExist: 
     return None 
    for dailyTask in dailyTasks: 
     timeDue = datetime.datetime(now.year,now.month,now.day,dailyTask.time.hour,dailyTask.time.minute,dailyTask.time.second) 
     if timeDue<now and timeDue>dailyTask.last_completed: 
      if dailyTask.weekends==False and now.weekday()>4: 
       pass 
      else: 
       dueDailyTasks.append({'id':dailyTask.id, 
          'due':timeDue, 
          'name': dailyTask.name, 
          'description':dailyTask.description}) 
    return dueDailyTasks 

Esto funcionó muy bien debajo de 1.2, pero en el punto 1.4 me sale el error:

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

debido a la línea

if timeDue<now and timeDue>dailyTask.last_completed 

y ambas cláusulas de comparación emiten este error.

He intentado hacer timeDue timezone consciente agregando pytz.UTC como argumento, pero esto aún provoca el mismo error.

He leído algunos de los documentos sobre husos horarios pero estoy confundido acerca de si solo tengo que hacer timeDue timezone aware, o si necesito hacer un cambio fundamental en mi db y los datos existentes.

Respuesta

153

Compruebe the thorough document para obtener información detallada.

Normalmente, utilizar django.utils.timezone.now para hacer una fecha y hora actuales offset conscientes

>>> from django.utils import timezone 
>>> timezone.now() 
datetime.datetime(2012, 5, 18, 13, 0, 49, 803031, tzinfo=<UTC>) 

Y django.utils.timezone.make_aware para hacer una fecha y hora offset conscientes

>>> timezone.make_aware(datetime.datetime.now(), timezone.get_default_timezone()) 
datetime.datetime(2012, 5, 18, 21, 5, 53, 266396, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>) 

A continuación, puede comparar ambos datetimes-offset conscientes w/o problema

Además, podría convertir datetime compensado-ahorrado a offset-naive datetime quitando información de la zona horaria, entonces podría ser comparado con normal datetime.datetime.now(), bajo utc.

>>> t = timezone.now() # offset-awared datetime 
>>> t.astimezone(timezone.utc).replace(tzinfo=None) 
datetime.datetime(2012, 5, 18, 13, 11, 30, 705324) 

USE_TZ es True 'por defecto' (en realidad es False por defecto, pero el archivo settings.py generada por django-admin.py startproject puso a True), entonces si su base de datos compatible con los tiempos de zona horaria para notificaciones, valores del modelo relacionado con el tiempo los campos serían conscientes de la zona horaria. puede desactivarlo configurando USE_TZ=False (o simplemente elimine USE_TZ=True) en la configuración.

+4

Django no almacena tiempos de alerta para TimeField, solo lo hace para DateTimeField. Es realmente molesto, ya que el objeto python datetime.time admite TZINFO como los objetos datetime.datetime. Me pregunto si lo arreglarían en el próximo lanzamiento. Por cierto lo he probado en el servidor de base de datos Postres 9.1. – tejinderss

+0

@tejinderss: 'datetime.time' es incorrecto. No tiene sentido almacenar la zona horaria ''Asia/Shanghai'' si no conoce la fecha (el desplazamiento utc puede ser diferente para el mismo tiempo pero en diferentes fechas). – jfs

+0

@okm: 'make_aware (datetime.now(), get_default_timezone())' falla si 'get_default_timezone()' difiere de su zona horaria local (debe ser, pero no es confiable). Simplemente use 'timezone.now()' en su lugar (es consciente de la zona horaria si 'USE_TZ' es' True'). – jfs

Cuestiones relacionadas