时区使我发疯。每次我想通了,都会有人改变时钟,我会遇到很多错误。我认为我终于到了要存储正确值的地步。我的时间是timestamp with time zone
,在保存时区之前,我不会删除时区。
TIME_ZONE = 'Europe/London'
USE_I18N = USE_L10N = USE_TZ = True
从Postgres到dbshell,这是一个特定值:
=> 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>)
这些时间可以在template / admin / etc中进行 fine 的工作,但是当我生成PDF和电子表格报告时,这一切都出错了,我突然不得不手动重新定位时间。我不明白为什么我必须这样做。数据已本地化。在查询数据库和获取数据之间发生了什么?
我经常碰到这些问题,所以我对这里的我自己完全没有信心-对于高级开发人员来说很不舒服-因此我将自己放在了你的脚下。我应该做什么?
答案 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:如果要在不同时区中运行服务器,则实际上可能最终会节省时间戳记在不同的时区。它们仍然都是正确的(绝对时间戳),并且可以转换为任何其他时区。因此,基本上,用于保存的时区是没有意义的。