为什么Django会创建带时区的Postgres时间戳列?

hek*_*ran 5 python django postgresql timezone datetime

我认为Django创建了与时区无关的日期时间列,但是当我查看我的Postgres表时,我看到记录的值有时区信息.

更进一步,我发现Postgres后端指示Django创建使用时区的列.

来自django/db/backends/postgresql/creation.py:

data_types = {
        ...
        'DateTimeField':     'timestamp with time zone',
        ...
Run Code Online (Sandbox Code Playgroud)

架构显示已创建的列被指定为"带时区的时间戳".

CREATE TABLE notification_notice
(
  ...
  created timestamp with time zone NOT NULL,
  ...
Run Code Online (Sandbox Code Playgroud)

Postgres日志显示已发送的更新语句.Django构造了一个SQL语句,它使用UTC作为我的Django设置文件指示的时区.

UPDATE "notification_notice" SET "sender_id" = 1, "group_id" = NULL, "notice_type_id" = 1, "content_type_id" = 21, "object_id" = 3, "created" = E'2011-11-11 22:31:08.022148' WHERE "notification_notice"."id" = 14
Run Code Online (Sandbox Code Playgroud)

这就是我的表格.创建的列的时区对其时区具有"-08".Postgres必须检查系统时钟的时区以找到时区.

my_db=# select * from notification_notice limit 1;
 id | sender_id | group_id | notice_type_id | content_type_id | object_id |           created            | last_interaction_time 
----+-----------+----------+----------------+-----------------+-----------+------------------------------+-----------------------
  1 |           |        3 |             21 |              53 |         6 | 2011-11-11 14:31:02.98882-08 | 
(1 row)
Run Code Online (Sandbox Code Playgroud)

问题:
Django不会对时区提供免提政策吗?
为什么Postgres后端为models.DateTimeField使用时区?这是Postgres要求的吗?
有没有办法强制Django在Postgres中创建不使用时区的时间戳列?

Mik*_*ll' 16

坏消息是问题的根源在于Python的日期时间实现.

好消息是Django有一个关于这个问题的开放票.

坏消息是该票在2006年开业.

好消息是,最近的提案更有用,并且似乎正在开发中.包含提案的主题很长,但信息很丰富.

坏消息是该提案归结为"这真是一团糟".(仍在进行中.)

更进一步,我发现Postgres后端指示Django创建使用时区的列.

不,那是Django的设计决定.PostgreSQL仅存储UTC; 它不存储时区,也不存储偏移量.时区在概念上类似于环境变量,它在插入或选择用于检索时应用于时间戳.

来自django开发人员的邮件存档...

在数据库中没有实际时区支持的情况下,django采取的任何操作都会给某些人带来不便,并且可能与非django使用相同的数据库不兼容.

这是一个大问题 - 可能使数据库与其他语言或框架不兼容的修复.那是我工作的绝对表演者; 许多编程语言和框架访问数据库.

SQLite,Microsoft Access和MySQL(日期时间数据类型,而不是时间戳)在该线程中被引用为缺少数据库中的时区支持.

  • @hekevintran:我还在(再次)阅读我发布的那些参考文献.当我使用时区和多个应用程序时,突然我的名字是"爱丽丝",我在兔子洞里:我不再确定我所知道的和我不知道的.我要说"不",因为你的Django应用程序仍然需要在存储它们之前将每个时间戳标准化为UTC.他们每一个人,永远.我也会说,"不",因为我很确定有一些微妙的点,我错过了.也许我只是累了. (2认同)

Hen*_*wan 5

我认为你的假设是错误的。PostgreSQL存储时区信息

对于timestamp with time zone内部存储的值始终采用 UTC(通用协调时间,传统上称为格林威治标准时间,GMT)。指定了显式时区的输入值将使用该时区的适当偏移量转换为 UTC。如果输入字符串中未指定时区,则假定其处于系统 TimeZone 参数指示的时区,并使用时区的偏移量将其转换为 UTC。

所以实际上时区信息丢失了。但那一瞬间的时间却被保留了下来

这意味着当您获取时间戳信息时,无论您或您的服务器当前位于哪个时区,都将始终是正确的。对于大多数应用程序来说,这正是您想要的。