让我们用这个模型创建一个小的Django应用程序:
class Thing(models.Model):
timestamp = models.DateTimeField(auto_now_add=True)
现在让我们尝试获取此日期的截断版本:
Thing.objects.create()
print Thing.objects.annotate(
truncstamp=TruncDay('timestamp')
).values('truncstamp')
如果我们只是在Django中运行查询集,我们会得到一个可能解释的错误:
ValueError: Database returned an invalid datetime value. Are time zone definitions for your database and pytz installed?
但是我安装了pytz,并且我已经在我的数据库中加载了时区。我的意思是,这个查询有效:
SELECT CONVERT_TZ(NOW(), 'SYSTEM', 'UTC');
让我们看看它试图运行的查询:
print Thing.objects.annotate(
truncstamp=TruncDay('timestamp')
).values('truncstamp').query
这会产生查询:
SELECT CAST(DATE_FORMAT(CONVERT_TZ(`stuff_thing`.`timestamp`, 'UTC', UTC), '%Y-%m-%d 00:00:00') AS DATETIME) AS `truncstamp` FROM `stuff_thing`
如果我尝试在MySQL中运行此查询,则无效。
ERROR 1054 (42S22): Unknown column 'UTC' in 'field list'
以下是仍然提供相同错误的查询的最小子集:
SELECT CONVERT_TZ(timestamp, 'UTC', UTC) from stuff_thing;
我们在这做什么?从UTC转换为UTC?为什么没有引用第二个UTC? Django发出无效的SQL吗?即使你引用了第二个'UTC',你从转换得到的只是NULL。为什么它甚至试图从UTC转换为UTC?我们不能跳过这一步吗?
这是一个新生成的应用程序,默认设置。我注意到如果我注释掉这个默认设置,查询将运行:
# TIME_ZONE = 'UTC'
现在结果以美国/芝加哥时区回归。
答案 0 :(得分:0)
喔。精彩。我猜MySQL会缓存查询,缓存区分大小写。看到这种疯狂:
mysql> SELECT CAST(DATE_FORMAT(CONVERT_TZ(`stuff_thing`.`timestamp`, 'UTC', 'UTC'), '%Y-%m-%d 00:00:00') AS DATETIME) AS `truncstamp` FROM `stuff_thing` LIMIT 21;
+------------+
| truncstamp |
+------------+
| NULL |
| NULL |
+------------+
2 rows in set (0.00 sec)
mysql> SELECT CAST(DATE_FORMAT(CONVERT_TZ(`stuff_thing`.`timestamp`, 'UTC', 'UTC'), '%Y-%m-%d 00:00:00') AS DATETIME) as `truncstamp` FROM `stuff_thing` LIMIT 21;
+---------------------+
| truncstamp |
+---------------------+
| 2016-11-15 00:00:00 |
| 2016-11-15 00:00:00 |
+---------------------+
2 rows in set (0.00 sec)
我重新启动了mysql,现在两个查询都有效。我想它已被破坏,因为我导入时区而没有重新启动它。