我不是 python 或 Django 大师,所以也许有人可以比我回答得更好。但无论如何我都会猜测一下。
您说您将它存储在 DjangoDateTimeField
中,根据您引用的文档,它会将其存储为 Python datetime
。
查看文档datetime
,我认为关键是理解“天真”和“有意识”值之间的区别。
然后进一步研究,我遇到了这个优秀的参考资料。请务必阅读第二部分“朴素且有意识的日期时间对象”。这为 Django 控制了多少提供了一些背景信息。基本上,通过设置USE_TZ = true
,您要求 Django 使用有意识的日期时间而不是天真的日期时间。
所以我回头看了你的问题。您说您正在执行以下操作:
dt = datetime.fromtimestamp(secs)
dt = dt.replace(tzinfo=utc)
查看fromtimestamp函数文档,我发现了这段文字:
如果指定或未指定可选参数,则将其转换为平台的本地日期和时间,并且返回的tz
对象是朴素的。None
timestamp
datetime
所以我认为你可以这样做:
dt = datetime.fromtimestamp(secs, tz=utc)
再说一次,在该函数的正下方,文档显示utcfromtimestamp
函数,所以它可能应该是:
dt = datetime.utcfromtimestamp(secs)
我对 python 的了解还不够,无法知道它们是否等效,但是您可以尝试看看两者是否有所不同。
希望其中之一会有所作为。如果没有,请告诉我。我非常熟悉 JavaScript 和 .Net 中的日期/时间,但我总是对这些细微差别如何在其他平台(例如 Python)中以不同方式发挥作用感兴趣。
更新
关于问题的 MySQL 部分,看看这个 fiddle。
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;
结果:
DATE UNIX_TIMESTAMP(`DATE`)
June, 13 2013 13:50:02+0000 1371131402
June, 13 2013 13:50:02+0000 1371127802
似乎UNIX_TIMESTAMP
函数的行为确实受到 MySQLTIME_ZONE
设置的影响。这并不奇怪,因为它在文档中。令人惊讶的是,datetime
无论设置如何, 的字符串输出都具有相同的 UTC 值。
这就是我认为正在发生的事情。在该UNIX_TIMESTAMP
函数的文档中,它说:
date
可以是DATE
字符串、DATETIME
字符串、aTIMESTAMP
或格式为YYMMDD
or的数字YYYYMMDD
。
请注意,它并没有说它可以是DATETIME
- 它说它可以是DATETIME
string。所以我认为实际值在传递给函数之前被隐式转换为字符串。
所以现在看看这个明确转换的更新小提琴。
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;
结果:
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
您可以看到,当它转换为字符数据时,它会去除偏移量。UNIX_TIMESTAMP
因此,当然,现在当将此值作为输入时,它假设本地时区设置并因此获得不同的 UTC 时间戳是有意义的。
不确定这是否对您有帮助。您需要更深入地了解 Django 是如何调用 MySQL 进行读取和写入的。它真的使用这个UNIX_TIMESTAMP
功能吗?或者这正是你在测试中所做的?