停止Django将时间转换为UTC

时间:2019-04-09 16:46:04

标签: django postgresql django-postgresql django-timezone

时区使我发疯。每次我想通了,都会有人改变时钟,我会遇到很多错误。我认为我终于到了要存储正确值的地步。我的时间是timestamp with time zone,在保存时区之前,我不会删除时区。

TIME_ZONE = 'Europe/London'
USE_I18N = USE_L10N = USE_TZ = True

从Postgres到dbshel​​l,这是一个特定值:

=> select start from bookings_booking where id = 280825;
2019-04-09 11:50:00+01

但这是通过shell_plus的相同记录

Booking.objects.get(pk=280825).start
datetime.datetime(2019, 4, 9, 10, 50, tzinfo=<UTC>)

DAMMIT DJANGO,现在不是世界时间!

这些时间可以在template / admin / etc中进行 fine 的工作,但是当我生成PDF和电子表格报告时,这一切都出错了,我突然不得不手动重新定位时间。我不明白为什么我必须这样做。数据已本地化。在查询数据库和获取数据之间发生了什么?

我经常碰到这些问题,所以我对这里的我自己完全没有信心-对于高级开发人员来说很不舒服-因此我将自己放在了你的脚下。我应该做什么?

1 个答案:

答案 0 :(得分:2)

您误解了这一点。数据库大部分时间存储UTC时间。如果使用PostgreSQL,数据库可以存储带有时区信息的时间,但是出于实用目的(*),最简单的做法是认为数据库中的时间存储为UTC(即可以转换为任何时间的绝对时间)区域)USE_TZ = True时。它始终代表一个正确的时间点,您无需记住或假定任何时区。据我所知,Django将始终将时间存储为UTC时区中的时间。

因此,当您在 psql 中使用select获取时间对象时,您将获得计算机本地时区(运行时所在的时区)中的时间。 psql)。如果“ America / New_York”中的某人将运行相同的选择查询,则她将看到-04时间戳。如果日期为2019-03-20,您会看到2019-03-20 10:50:00+00,因为在该日期,欧洲/伦敦和UTC相同。

当将DateTimeField的值作为python datetime.datetime对象获取时,Django始终会获取UTC值,因为:

  

处理有意识的日期时间对象并不总是很直观。对于   实例,标准datetime构造函数的tzinfo参数   在具有DST的时区不能正常工作。通常使用UTC   安全;如果您使用的是其他时区,则应查看pytz   仔细记录文档。

这使在Python代码中使用这些datetime对象更加容易:它们始终是UTC时间。

如果要在PDF中打印这些值,请使用Django用于模板渲染的相同方法:

from django.utils import timezone
print(timezone.template_localtime(Booking.objects.get(pk=280825).start))

这将在默认时区(或者如果您activate()在其他时区,在当前时区中)显示日期时间。

(*)注意:为什么您不应该对保存在数据库中的时区赋予任何意义,而只是将其视为所有UTC:如果要在不同时区中运行服务器,则实际上可能最终会节省时间戳记在不同的时区。它们仍然都是正确的(绝对时间戳),并且可以转换为任何其他时区。因此,基本上,用于保存的时区是没有意义的。