2010-03-27 13 views
22

Estoy trabajando con SQLAlchemy, y aún no estoy seguro de qué base de datos usaré debajo de él, por lo que quiero permanecer como DB-agnóstico como sea posible. ¿Cómo puedo almacenar un objeto datetime que tenga en cuenta la zona horaria en el DB sin vincularme a una base de datos específica? En este momento, me estoy asegurando de que las horas sean UTC antes de almacenarlas en la base de datos y convertirlas a localizadas en el momento de la visualización, pero eso se siente poco elegante y frágil. ¿Existe una forma DB-agnóstica de obtener un datetime con reconocimiento de zona horaria de SQLAlchemy en lugar de obtener objetos ingeniosos de datatime de la base de datos?¿Puede SQLAlchemy DateTime Objects Only Be Naive?

Respuesta

40

Hay un parámetro timezone en DateTime tiempo de columna, por lo que no hay ningún problema con el almacenamiento de objetos de timezone-aware datetime. Sin embargo, encontramos conveniente convertir almacenado datetime a UTC automáticamente con un simple decorador Tipo:

from sqlalchemy import types 
from dateutil.tz import tzutc 
from datetime import datetime 

class UTCDateTime(types.TypeDecorator): 

    impl = types.DateTime 

    def process_bind_param(self, value, engine): 
     if value is not None: 
      return value.astimezone(tzutc()) 

    def process_result_value(self, value, engine): 
     if value is not None: 
      return datetime(value.year, value.month, value.day, 
          value.hour, value.minute, value.second, 
          value.microsecond, tzinfo=tzutc()) 

Nota, es decir se comporta muy bien cuando se utiliza ingenua datetime por accidente (lo que significa que va a levantar una ValueError).

+0

Esto no funciona como está escrito, necesita un pequeño ajuste en 'process_bind_param':' def process_bind_param (self, value, engine): \ n si el valor no es None: \ n si value.tzinfo es None: \ n return value.replace (tzinfo = tzutc()) \ n else: \ n return value.astimezone (tzutc()) ' –

+9

@Jesse Dhillon: es intencional evitar el almacenamiento accidental de objetos navideños datetime, mientras que su receta interpreta incorrectamente cualquier fecha y hora con cualquier zona horaria como UTC. –

+6

@Dennis, entonces, si usa su tipo, se espera que cree y almacene solo objetos 'datetime' con timezone-aware? Ahora que lo entiendo, me gusta más su solución porque requiere que el usuario sea explícito sobre lo que están guardando. –