Django datetimefield 时区感知 CET

Posted

技术标签:

【中文标题】Django datetimefield 时区感知 CET【英文标题】:Django datetimefield timezone aware CET 【发布时间】:2016-05-07 04:00:44 【问题描述】:

我看到了这篇帖子Is Django corrupting timezone-aware DateTimeField when saving it to the Database?,但它专门使用了 pytz 和 mysql,而在我不使用 pytz 并使用 SQLite 的地方(以防它可能会产生影响)。

我有以下型号

class ScheduleItem(models.Model):
    work_date = models.DateTimeField('Work date')

我插入数据如下:

from isoweek import Week
from dateutil import parser
from django.utils import timezone

def foo()
    year = 2016 #hardcoded for example purpose
    wknr = 2 #hardcoded for example purpose
    dateObj = parser.parse(Week(year, wknr).day(0).isoformat() + " 00:00:00")
    print(dateObj) # 2016-01-11 00:00:00 as expected
    final = timezone.make_aware(dateObj)
    print(final) # 2016-01-11 00:00:00+01:00 as expected
    return final


workdate = foo()
si = ScheduleItem(work_date=workdate)
si.save()

打印语句为我提供了正确的输出,但是一旦我查看数据库 (SQLite),我就会看到 2016-01-10 23:00:00

我的 django 设置说

TIME_ZONE = 'CET'
USE_TZ = True

检索我得到的数据:

datetime.datetime(2016, 1, 10, 23, 0, tzinfo=<UTC>)

为什么它以另一种格式存储数据,然后我指定,为什么如果 Django 设置为时区感知,我会得到一个 UTC 时区吗?我的意思是在插入日期时间对象之前说:datetime.datetime(2016, 1, 11, 0, 0, tzinfo=&lt;DstTzInfo 'CET' CET+1:00:00 STD&gt;)

更新 -

与此同时,我通过在数据库上设置 TIME_ZONE 找到了解决方法,如 Django 文档 here 中所述。这为我提供了数据库中正确的时区/日期,但根据该文档,我不需要它,因为我的数据库 is 由 Django 管理

这允许与以本地时间而不是 UTC 存储日期时间的第三方数据库进行交互。为避免与 DST 更改相关的问题,您不应为 Django 管理的数据库设置此选项。

我仍然不清楚为什么 Django 确实在将具有 CET 时区的日期时间对象存储在数据库中时将其转换为 UTC,但在检索时却不够聪明以将其转换回 CET .

【问题讨论】:

【参考方案1】:

Django 在内部使用 UTC 时间。 TIME_ZONE 将用于“您的视图和模型”(https://docs.djangoproject.com/en/1.9/ref/settings/#std:setting-TIME_ZONE)

您从2016-01-11 00:00 CET 开始,即2016-01-10 23:00 UTC!您的日期时间已正确保存到数据库并稍后恢复,因此一切正常。

【讨论】:

我现在可以理解并接受 Django 的 ORM 负责根据 USE_TZTIME_ZONE 的组合在数据库中转换和存储 UTC 格式的日期时间。但是,从同一部分“您的所有视图和模型将在此时区自动运行”这并没有发生。通过 Model/ORM 检索日期时间时,我得到的是 UTC,而不是我的设置中指示的 CET 版本。当然,我可以使用 Django 的timezone.localtime() 来转换我检索到的内容,但这不是重点。它只完成了所需操作的一半。 该部分可能更清楚一点:在显示面向用户的信息时使用 TIME_ZONE。使用humanize模板标签试试,相信你会看到CET时间显示。 我选择授予您赏金/答案,因为它至少回答了问题的一部分并让我了解了部分内部情况。为什么它不恢复我知道的 datetime 对象可能是 Django 设计选择,并且可能被认为超出了问题的范围。 我相信这是唯一的选择 - 数据库存储 UTC,因此时区信息丢失。要恢复到 CET,您可以将时区保留为单独的模型字段,并根据需要规范化到该时区。

以上是关于Django datetimefield 时区感知 CET的主要内容,如果未能解决你的问题,请参考以下文章

Django 日期时间查询

Django:RunTimeWarning:DateTimeField 在时区支持处于活动状态时收到了一个天真的日期时间

查询 Django 模型时,如何将 Django 中的 DateTimeField 从 UTC 转换为最终用户的时区(通常是 PST)?

如何在 django 中获取时区感知日期?

将日期时间字符串解析为 Django DateTimeField

在 Jinja2 模板中使用 DateTimeFields 显示本地时间 - Django