2010-01-18 10 views
23

¿Cómo configuro la zona horaria de una instancia de fecha y hora que acaba de salir del almacén de datos?El atributo 'tzinfo' de los objetos 'datetime.datetime' no se puede escribir

Cuando sale por primera vez, está en UTC. Quiero cambiarlo a EST.

que estoy tratando, por ejemplo:

class Book(db.Model): 
    creationTime = db.DateTimeProperty() 

Cuando un libro se recupera, quiero fijar su tzinfo inmediato:

book.creationTime.tzinfo = EST 

Dónde I use this example para mi objeto EST

Sin embargo, obtengo:

 
attribute 'tzinfo' of 'datetime.datetime' objects is not writable 

He visto una serie de respuestas que recomiendan pytz y python-dateutil, pero realmente quiero una respuesta a esta pregunta.

Respuesta

38

datetime 's objetos son inmutables, por lo que nunca cambiar cualquiera de sus atributos - realiza una nueva objeto con algunos atributos de la misma, y ​​algunos diferente, y asignarlo a lo que sea necesario para asignarlo a.

es decir, en su caso, en lugar de

book.creationTime.tzinfo = EST 

usted tiene que codificar

book.creationTime = book.creationTime.replace(tzinfo=EST) 
+0

nota: no convierte de UTC a EST timezone (* "primero sale, está en UTC. Quiero cambiarlo a EST." *). El tiempo permanece igual. Para convertir, se puede usar 'book.creationTime.astimezone (EST)'. – jfs

0

Lo que quiere está ahí en el docs.

from datetime import tzinfo, timedelta, datetime 

ZERO = timedelta(0) 
HOUR = timedelta(hours=1) 
DSTSTART = datetime(1, 4, 1, 2) 
DSTEND = datetime(1, 10, 25, 1) 

def first_sunday_on_or_after(dt): 
    days_to_go = 6 - dt.weekday() 
    if days_to_go: 
     dt += timedelta(days_to_go) 
    return dt 

class USTimeZone(tzinfo): 

    def __init__(self, hours, reprname, stdname, dstname): 
     self.stdoffset = timedelta(hours=hours) 
     self.reprname = reprname 
     self.stdname = stdname 
     self.dstname = dstname 

    def __repr__(self): 
     return self.reprname 

    def tzname(self, dt): 
     if self.dst(dt): 
      return self.dstname 
     else: 
      return self.stdname 

    def utcoffset(self, dt): 
     return self.stdoffset + self.dst(dt) 

    def dst(self, dt): 
     if dt is None or dt.tzinfo is None: 
      # An exception may be sensible here, in one or both cases. 
      # It depends on how you want to treat them. The default 
      # fromutc() implementation (called by the default astimezone() 
      # implementation) passes a datetime with dt.tzinfo is self. 
      return ZERO 
     assert dt.tzinfo is self 

     # Find first Sunday in April & the last in October. 
     start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year)) 
     end = first_sunday_on_or_after(DSTEND.replace(year=dt.year)) 

     # Can't compare naive to aware objects, so strip the timezone from 
     # dt first. 
     if start <= dt.replace(tzinfo=None) < end: 
      return HOUR 
     else: 
      return ZERO 

now = datetime.now() 
print now 
print now.tzinfo 

Eastern = USTimeZone(-5, 'Eastern', 'EST', 'EDT') 
now_tz_aware = now.replace(tzinfo=Eastern) 
print now_tz_aware 

de salida:

2010-01-18 17:08:02.741482 
None 
2010-01-18 17:08:02.741482-05:00 
+2

Eso no es muy informativo. Usted podría haber explicado tanto al decir que use datetime.replace (tzinfo = ...) - pero no ha explicado cómo se supone que debe OBTENER el tzinfo que quiere, simplemente ha codificado una zona horaria EST/EDT. – Auspex

5

Si está recibiendo una fecha y hora que es en EST, pero no tiene su campo de juego tzinfo, utilice dt.replace(tzinfo=tz) asignar un tzinfo sin modificar el tiempo. (Su base de datos debería estar haciendo esto por usted).

Si recibe una fecha y hora en UDT, y la quiere en EST, entonces necesita astimezone. http://docs.python.org/library/datetime.html#datetime.datetime.astimezone

En la gran mayoría de los casos, su base de datos debe almacenar y devolver datos en UDT, y no debería necesitar reemplazar (excepto posiblemente asignar un UDT tzinfo).

+1

Por 'UDT' quiere decir 'UTC', ¿correcto? – Will

Cuestiones relacionadas