2011-11-12 12 views
5

Pensé que Django creó columnas de fecha y hora que eran independientes de la zona horaria, pero cuando miré en mi tabla de Postgres, vi que los valores registrados allí tenían información de zona horaria.¿Por qué Django crea columnas de marca de hora Postgres con zonas horarias?

Yendo más lejos, encontré que el backend de Postgres ordena a Django crear columnas que usen zonas horarias.

De Django/db/backend/PostgreSQL/creation.py:

data_types = { 
     ... 
     'DateTimeField':  'timestamp with time zone', 
     ... 

El esquema muestra que la columna creada se especifica como "marca de tiempo con la zona horaria".

CREATE TABLE notification_notice 
(
    ... 
    created timestamp with time zone NOT NULL, 
    ... 

El registro de Postgres muestra la declaración de actualización que se envió. Django construyó una declaración de SQL que usaba UTC como la zona horaria según lo ordenado por mi archivo de configuración de Django.

UPDATE "notification_notice" SET "sender_id" = 1, "group_id" = NULL, "notice_type_id" = 1, "content_type_id" = 21, "object_id" = 3, "created" = E'2011-11-11 22:31:08.022148' WHERE "notification_notice"."id" = 14 

Así es como se ve mi mesa. La columna creada tiene un timestame que tiene "-08" para su zona horaria. Postgres debe inspeccionar el huso horario del reloj de mi sistema para encontrar la zona horaria.

my_db=# select * from notification_notice limit 1; 
id | sender_id | group_id | notice_type_id | content_type_id | object_id |   created   | last_interaction_time 
----+-----------+----------+----------------+-----------------+-----------+------------------------------+----------------------- 
    1 |   |  3 |    21 |    53 |   6 | 2011-11-11 14:31:02.98882-08 | 
(1 row) 

Preguntas:
no Django tener una política de manos fuera de las zonas de tiempo?
¿Por qué el back-end de Postgres usa zonas horarias para los modelos.DateTimeField? ¿Esto es requerido por Postgres?
¿Hay alguna manera de forzar a Django a crear columnas de indicación de fecha y hora en Postgres que no utilizan la zona horaria?

+0

Posible respuesta: [aquí] (http://stackoverflow.com/questions/1869419/django-datetime-field-to-generate-timestamp-fields-without-timezone/1869568#1869568) – unutbu

Respuesta

16

La mala noticia es que la raíz del problema está en la implementación datetime de Python.

La buena noticia es que Django tiene an open ticket en este problema.

La mala noticia es que el billete se abrió en 2006.

La buena noticia es que un recent proposal es la lectura más útil y parece estar en desarrollo. El hilo que contiene la propuesta es largo, pero muy informativo.

La mala noticia es que la propuesta se reduce a "esto es un verdadero desastre". (Sin embargo, es en el desarrollo.)

Yendo más lejos me encontré con que el backend Postgres dirige a Django crear columnas que utilizan zonas horarias.

No, esa es una decisión de diseño de Django. PostgreSQL almacena solo UTC; no almacena la zona horaria y no almacena el desplazamiento. La zona horaria es conceptualmente como una variable ambiental que se aplica a las marcas de tiempo a medida que se insertan o se seleccionan para su recuperación.

Desde django developer's mail archive. . .

Ante la falta de apoyo real de zona horaria en la base de datos, cualquier acción tomada por Django va a molestar a alguien, y es probable que no sean compatibles con el uso no django de la misma base de datos.

Ese es un gran problema, una solución que podría hacer que la base de datos sea incompatible con otros lenguajes o marcos. Esa es una parada absoluta donde trabajo; muchos lenguajes de programación y marcos acceden a la base de datos.

SQLite, Microsoft Access y MySQL (tipo de datos datetime, no timestamp) se citan en ese hilo como falta soporte de zona horaria en la base de datos.

+0

Sí, entiendo que es una desción de diseño de Django. En "back-end de Postgres", me refería al back-end de Postgres de Django ORM. – hekevintran

+0

Si la zona horaria es como una variable ambiental, ¿significa eso que simplemente tengo que establecer la zona horaria (a UTC, por ejemplo) en mi conexión a la base de datos? – hekevintran

+2

@hekevintran: Todavía estoy leyendo (una vez más) esas referencias que publiqué. Cuando trabajo con zonas horarias y aplicaciones múltiples, de repente mi nombre es "Alice", y estoy en el hoyo del conejo: ya no estoy seguro de lo que sé y de lo que no sé. Voy a decir "No", porque tu aplicación Django aún tendrá que normalizar cada una de tus marcas de tiempo a UTC antes de almacenarlas. Cada uno de ellos, por siempre. También voy a decir: "No", porque estoy bastante seguro de que hay algunos puntos sutiles que me estoy perdiendo. Tal vez estoy cansado. –

0

El hecho de que Postgresql sea capaz de almacenar marcas de tiempo con la zona horaria es algo bueno. Se supone que una marca de tiempo representa un punto en el tiempo. Si lees "2013-03-15 14:38:00", ¿es suficiente saber exactamente qué punto del tiempo está representado? ¡No! Podrían ser las 14:38 en Nueva York o las 14:38 en Berlín, y estos son dos momentos diferentes en el tiempo. Por lo tanto, nunca debería haber marcas de tiempo sin zonas horarias (se les llama fechas de programación "ingenuas"), a menos que esté implícita una zona horaria específica (por ejemplo, UTC).

El hecho de que Django cree una marca de tiempo con zona horaria es por lo tanto una buena cosa , en mi opinión. Puede anular ese comportamiento predeterminado al writing your own DatetimeField, pero no lo recomendaría, a menos que tenga una muy buena razón para deshacerse de las zonas horarias en la base de datos (porque rompe algún otro programa heredado, por ejemplo).

Si usa Django < 1.4, el código del cliente postgresql supone que todas las fechas están en la zona horaria de su sistema. Entonces, si la zona horaria de su servidor django es Berlín, entonces "2013-03-15 14:38:00" se interpretará como 14:38 en la zona horaria de Berlín, y toda esa información se almacenará en la base de datos. Si elimina la información de la zona horaria, entonces tendrá problemas en DST cambios de hora. Por ejemplo, "2013-10-26 02:30:00" es ambiguo: ¿es la primera o segunda ocurrencia de las 2:30 am? Si sigue esa ruta, debe convertir todas las fechas a/desde UTC en su código Django y almacenar las fechas y horas UTC en la base de datos.

Si usa Django> = 1.4, entonces de manera predeterminada es consciente de la zona horaria y espera que cada fecha y hora tenga una zona horaria. Dado que python datetimes desafortunadamente no tiene tiene zonas horarias de forma predeterminada, debe usar pytz package para asegurarse de que cada fecha que manipule tenga en cuenta la zona horaria.

El Django documentation about timezones es una muy buena lectura.

1

Creo que tiene una suposición incorrecta. PostgreSQL does not store time zone information:

Para timestamp with time zone, la valor almacenado internamente está siempre en UTC (Tiempo Universal Coordinado, tradicionalmente conocido como Greenwich Mean Time, GMT). Un valor de entrada que tiene una zona horaria explícita especificada se convierte a UTC utilizando la compensación adecuada para esa zona horaria. Si no se indica zona horaria en la cadena de entrada, se supone que está en la zona horaria indicada por el parámetro TimeZone del sistema, y ​​se convierte a UTC utilizando la compensación para la zona de zona horaria.

De hecho, la información de la zona horaria se ha perdido. Pero el instante de tiempo se conserva.

Lo que significa que cuando obtiene la información de la marca de tiempo, cualquiera sea la zona horaria que usted o su servidor sean actualmente, siempre será correcta. Para la mayoría de las aplicaciones, esto es exactamente lo que desea.

Cuestiones relacionadas