发布
社区首页 >问答首页 >为什么Django要创建带有时区的Postgres时间戳列?

为什么Django要创建带有时区的Postgres时间戳列?
EN

Stack Overflow用户
提问于 2011-11-12 00:27:43
回答 3查看 10.6K关注 0票数 5

我认为Django创建了与时区无关的datetime列,但是当我查看Postgres表时,我发现那里记录的值包含时区信息。

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

从django/db/后端/postgresql/creation.py:

代码语言:javascript
代码运行次数:0
复制
data_types = {
        ...
        'DateTimeField':     'timestamp with time zone',
        ...

架构显示所创建的列被指定为“带时区的时间戳”。

代码语言:javascript
代码运行次数:0
复制
CREATE TABLE notification_notice
(
  ...
  created timestamp with time zone NOT NULL,
  ...

Postgres日志显示发送的update语句。Django构造了一个SQL语句,该语句使用UTC作为时区,由我的Django设置文件指导。

代码语言:javascript
代码运行次数:0
复制
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必须检查系统时钟的时区。

代码语言:javascript
代码运行次数:0
复制
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中创建不使用时区的时间戳列?

EN

回答 3

Stack Overflow用户

发布于 2011-11-12 01:59:28

坏消息是,问题的根源在于Python的datetime实现。

好消息是Django在这个问题上有公开的票

坏消息是这张票是在2006年开的。

好消息是,最近的提案更有用,而且似乎正在开发中。包含提案的内容很长,但内容非常丰富。

坏消息是,这一提议归结为“这是一个真正的混乱”。(尽管如此,它仍在开发中。)

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

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

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

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

这是一个大问题--一个可能使数据库与其他语言或框架不兼容的修复方法。在我工作的地方,这是一个绝对的停止;许多编程语言和框架访问数据库。

该线程中引用了SQLite、Microsoft和MySQL (日期时间数据类型,而不是时间戳),因为数据库中缺乏时区支持。

票数 16
EN

Stack Overflow用户

发布于 2017-11-05 08:13:56

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

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

因此,实际上,时区信息丢失了。但是时间的瞬间被保存下来了,

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

票数 4
EN

Stack Overflow用户

发布于 2013-03-15 14:06:12

Postgresql能够用时区存储时间戳这一事实是一件好事。时间戳应该表示一个时间点。如果你读了"2013-03-15 14:38:00",知道具体代表了什么时间点就足够了吗?不是的!纽约可能是14:38,柏林可能是14:38,这是两个不同的时间点。因此,如果不包含特定的时区(例如UTC),就不应该有没有时区的时间戳(它们被称为“朴素”日期时间)。

在我看来,Django创建带有时区的时间戳是一件好事。您可以通过编写自己的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封装来确保您操作的每个日期时间都是时区感知的。

Django关于时区的文档是一个非常好的读物。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8101506

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档