No soy un gurú de Python o Django, así que quizás alguien pueda responder mejor que yo. Pero lo adivinaré de todos modos.
Dijiste que lo estabas almacenando en Django DateTimeField
, que según los documentos a los que hizo referencia
, lo almacena como Python datetime
.
Mirando los documentos para datetime
, creo que la clave es comprender la diferencia entre los valores "ingenuo" y "consciente".
Y luego investigando más, encontré esta excelente referencia
. Asegúrese de leer la segunda sección, "Objetos de fecha y hora ingenuos y conscientes". Eso da un poco de contexto a cuánto de esto está siendo controlado por Django. Básicamente, configurando USE_TZ = true
, le estás pidiendo a Django que use aware datetimes en lugar de ingenuo unos.
Entonces volví a mirar tu pregunta. Dijiste que estabas haciendo lo siguiente:
dt = datetime.fromtimestamp(secs)
dt = dt.replace(tzinfo=utc)
Mirando el fromtimestamp documentación de la función, encontré este fragmento de texto:
Así que creo que podrías hacer esto:
dt = datetime.fromtimestamp(secs, tz=utc)
Por otra parte, justo debajo de esa función, los documentos muestran utcfromtimestamp
función, así que tal vez debería ser:
dt = datetime.utcfromtimestamp(secs)
No sé lo suficiente sobre python para saber si son equivalentes o no, pero podrías probar y ver si alguno marca la diferencia.
Esperemos que uno de estos haga la diferencia. Si no es así, por favor hágamelo saber. Estoy íntimamente familiarizado con la fecha/hora en JavaScript y en .Net, pero siempre estoy interesado en cómo estos matices se desarrollan de manera diferente en otras plataformas, como Python.
Actualizar
Con respecto a la parte de MySQL de la pregunta, eche un vistazo a este violín .
CREATE TABLE foo (`date` DATETIME);
INSERT INTO foo (`date`) VALUES (FROM_UNIXTIME(1371131402));
SET TIME_ZONE="+00:00";
select `date`, UNIX_TIMESTAMP(`date`) from foo;
SET TIME_ZONE="+01:00";
select `date`, UNIX_TIMESTAMP(`date`) from foo;
Resultados:
DATE UNIX_TIMESTAMP(`DATE`)
June, 13 2013 13:50:02+0000 1371131402
June, 13 2013 13:50:02+0000 1371127802
Parecería que el comportamiento de UNIX_TIMESTAMP
la función se ve afectada por MySQL TIME_ZONE
ajuste. Eso no es tan sorprendente, ya que está en la documentación. Lo sorprendente es que la cadena de salida de datetime
tiene el mismo valor UTC independientemente de la configuración.
Esto es lo que creo que está sucediendo. En los documentos de UNIX_TIMESTAMP
función, dice:
Tenga en cuenta que no dice que puede ser un DATETIME
- dice que puede ser un DATETIME
cadena . Así que creo que el valor real se convierte implícitamente en una cadena antes de pasar a la función.
Así que ahora mira este violín actualizado que convierte explícitamente.
SET TIME_ZONE="+00:00";
select `date`, convert(`date`, char), UNIX_TIMESTAMP(convert(`date`, char)) from foo;
SET TIME_ZONE="+01:00";
select `date`, convert(`date`, char), UNIX_TIMESTAMP(convert(`date`, char)) from foo;
Resultados:
DATE CONVERT(`DATE`, CHAR) UNIX_TIMESTAMP(CONVERT(`DATE`, CHAR))
June, 13 2013 13:50:02+0000 2013-06-13 13:50:02 1371131402
June, 13 2013 13:50:02+0000 2013-06-13 13:50:02 1371127802
Puede ver que cuando se convierte en datos de caracteres, elimina el desplazamiento. Por supuesto, ahora tiene sentido que cuando UNIX_TIMESTAMP
toma este valor como entrada, asume la configuración de la zona horaria local y, por lo tanto, obtiene una marca de tiempo UTC diferente.
No estoy seguro si esto te ayudará o no. Necesita profundizar más en exactamente cómo Django está llamando a MySQL tanto para la lectura como para la escritura. ¿Realmente usa el UNIX_TIMESTAMP
¿función? ¿O fue eso lo que hiciste en las pruebas?