2011-11-12 51 views
5

我认为Django创建了时区不可知的日期时间列,但是当我查看Postgres表时,我看到那里记录的值有时区信息。为什么Django使用时区创建Postgres时间戳列?

走得更远我发现Postgres后端指示Django创建使用时区的列。

从django的/分贝/后端/ PostgreSQL的/ creation.py:

data_types = { 
     ... 
     'DateTimeField':  'timestamp with time zone', 
     ... 

架构表明创建的列被指定为 “时间戳与时区”。

CREATE TABLE notification_notice 
(
    ... 
    created timestamp with time zone NOT NULL, 
    ... 

Postgres日志显示发送的更新语句。 Django根据我的Django设置文件的指示构建了一个使用UTC作为时区的SQL语句。

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 

这就是我的表的样子。创建的列的时区具有“-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) 

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

+0

可能的答案:[here](http://stackoverflow.com/questions/1869419/django-datetime-field-to-generate-timestamp-fields-without-timezone/1869568#1869568) – unutbu

回答

16

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

好消息是Django在这个问题上有an open ticket

的坏消息是,门票于2006年

开好消息是,recent proposal是比较有用的阅读,似乎是在发展的。包含提案的主题很长,但内容非常丰富。

坏消息是,提案归结为“这是一个真正的混乱”。 (仍然在开发中)

我进一步发现Postgres后端指向Django创建使用时区的列 。

不,这是一个Django设计决定。 PostgreSQL只存储UTC;它不存储时区,也不存储偏移量。时区在概念上就像一个环境变量,在插入或选择检索时应用于时间戳。

来自django developer's mail archive。 。 。

在数据库中没有实际的时区支持,Django在采取的任何行动 是要别人带来不便,并可能会 不能与非Django中使用同一个数据库的兼容。

这是一个很大的问题 - 一个可能使数据库与其他语言或框架不兼容的问题。在我工作的地方,这是一个绝对的展示器。许多编程语言和框架访问数据库。在该线程中引用了SQLite,Microsoft Access和MySQL(日期时间数据类型,不是时间戳),因为数据库中缺少时区支持。

+0

是的我明白它是一个Django设计说明。通过“Postgres后端”,我指的是Django ORM的Postgres后端。 – hekevintran

+0

如果时区就像一个环境变量,那么这是否意味着我只需要在我的数据库连接中设置时区(例如UTC)? – hekevintran

+2

@hekevintran:我仍然在阅读(再次)我发布的那些引用。当我与时区和多个应用程序一起工作时,突然我的名字是“Alice”,我陷入了兔子洞:我不再确定我所知道的和我不知道的。我会说,“不”,因为你的Django应用程序在存储它们之前仍然需要将你的每一个时间戳标准化为UTC。每一个,永远。我也会说,“不”,因为我很确定有一些微妙的点,我错过了。也许我只是累了。 –

0

Postgresql能够将时区与时区一起存储的事实是一件好事。时间戳应该表示一个时间点。如果你阅读“2013-03-15 14:38:00”,是否足以确切地知道代表什么时间点?没有!它可能在纽约14:38或在柏林14:38,这是两个不同的时间点。所以,除非特定的时区被隐含(例如UTC),否则不应该有没有时区的时间戳(它们被称为“天真”日期时间)。

Django创建带时区的时间戳因此是好的在我看来。您可以覆盖writing your own DatetimeField的默认行为,但我不会推荐它,除非您有很好的理由摆脱数据库中的时区(例如,因为它打破了其他传统程序)。

如果您使用Django < 1.4,那么postgresql客户端代码将假定所有日期时间都在您系统的时区中。因此,如果您的django服务器的时区是柏林,那么“2013-03-15 14:38:00”将在柏林时区解释为14:38,并且所有信息将存储在数据库中。如果您删除时区信息,则在DST时间更改时您将遇到问题。例如,“2013-10-26 02:30:00”含糊不清:是凌晨2:30的第一次还是第二次?如果你走这条路线,你必须在你的Django代码中将所有日期时间转换为UTC,并将UTC日期时间存储在数据库中。

如果您使用Django> = 1.4,那么默认情况下它是时区感知的,并且期望每个日期时间都有一个时区。由于Python日期时间不幸的是而不是默认情况下有时区,所以您应该使用pytz package来确保您操作的每个日期时间都是可识别时区的。

Django documentation about timezones是一个很好的阅读。

1

我认为你有一个不正确的假设。 PostgreSQL does not store time zone information

对于timestamp with time zone,在内部存储的数值总是UTC(协调世界时,习惯上称为格林威治标准时间,GMT)。使用该时区的适当偏移量将具有指定明确时区的输入值转换为UTC。如果输入字符串中没有规定时区,则假定它位于系统的TimeZone参数指示的时区中,并使用时区区域的偏移量转换为UTC。

因此实际上,时区信息丢失。但时间瞬间保留

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

相关问题