Eu não sou nenhum guru de python ou Django, então talvez alguém possa responder melhor do que eu. Mas vou arriscar mesmo assim.
Você disse que estava armazenando em um Django
DateTimeField
, que de acordo com os documentos que você fez referência
, armazena-o como um Python datetime
. Examinando os documentos para
datetime
, acho que a chave é entender a diferença entre os valores "ingênuos" e "conscientes". E pesquisando mais, encontrei esta excelente referência . Certifique-se de ler a segunda seção, "Objetos de data e hora ingênuos e cientes". Isso dá um pouco de contexto de quanto disso está sendo controlado pelo Django. Basicamente, definindo
USE_TZ = true
, você está pedindo ao Django para usar aware datetimes em vez de ingênuo uns. Então eu olhei de volta para sua pergunta. Você disse que estava fazendo o seguinte:
dt = datetime.fromtimestamp(secs)
dt = dt.replace(tzinfo=utc)
Examinando o fromtimestamp documentação da função, encontrei este pedaço de texto:
Então eu acho que você poderia fazer isso:
dt = datetime.fromtimestamp(secs, tz=utc)
Então, novamente, logo abaixo dessa função, os documentos mostram
utcfromtimestamp
função, então talvez deva ser:dt = datetime.utcfromtimestamp(secs)
Eu não sei o suficiente sobre python para saber se eles são equivalentes ou não, mas você pode tentar ver se faz alguma diferença.
Esperemos que um destes vai fazer a diferença. Se não, por favor me avise. Estou intimamente familiarizado com data/hora em JavaScript e em .Net, mas estou sempre interessado em saber como essas nuances se comportam de maneira diferente em outras plataformas, como Python.
Atualizar
Em relação à parte MySQL da pergunta, dê uma olhada este violino .
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
Parece que o comportamento de
UNIX_TIMESTAMP
função é realmente afetada pelo MySQL TIME_ZONE
contexto. Isso não é tão surpreendente, já que está na documentação. O que é surpreendente é que a saída de string do datetime
tem o mesmo valor UTC independentemente da configuração. Aqui está o que eu acho que está acontecendo. Nos documentos do
UNIX_TIMESTAMP
função, diz:Observe que não diz que pode ser um
DATETIME
- diz que pode ser um DATETIME
sequência . Então, acho que o valor real está sendo convertido implicitamente em uma string antes de ser passado para a função. Então agora veja este violino atualizado que converte explicitamente.
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
Você pode ver que, quando converte em dados de caracteres, remove o deslocamento. Então, é claro, agora faz sentido que quando
UNIX_TIMESTAMP
recebe esse valor como entrada, está assumindo a configuração do fuso horário local e, assim, obtendo um carimbo de data/hora UTC diferente. Não tenho certeza se isso vai te ajudar ou não. Você precisa se aprofundar em exatamente como o Django está chamando o MySQL tanto para leitura quanto para gravação. Ele realmente usa o
UNIX_TIMESTAMP
função? Ou foi só isso que você fez nos testes?