Django系统时区设置与用户个别时区的对比
Django在处理每个用户不同的时区方面表现得怎么样呢?理想情况下,我希望服务器运行在UTC时区(比如在settings.py
里设置TIME_ZONE="UTC"
),这样所有的日期时间都会以UTC格式存储在数据库里。像这样的事情让我有点担心,所以我更喜欢在各处都使用UTC。
但是,存储每个用户的时区会有多难呢?我还能继续使用Django的标准日期时间格式和模型表单吗?我是不是得到处写代码,把日期转换成用户的时区,然后再转换回UTC呢?
我现在还在学习Django的教程,但我知道在一些其他框架中处理用户时区是多么麻烦,因为那些框架到处都假设使用系统时区,所以我想现在就问问。
目前我的研究主要是查阅Django的文档,但只找到了一条关于时区的参考资料。
补充:
- 关于Django和时区处理,有一些提交的bug。
- Babel有一些针对Django的贡献代码,似乎可以处理本地的时区格式。
7 个回答
Django其实并不处理时区的问题,主要是因为Python也没有处理。Python的创始人(Guido)目前决定不支持时区,因为虽然时区是现实世界的一部分,但这更多是个政治问题,而不是理性的选择,并且没有一个标准适合所有应用。
对于大多数人来说,最好的办法是先别担心这个问题,依赖Django在settings.py文件中默认提供的设置 TIME_ZONE = 'America/Los_Angeles'
,这样后面会更方便。
根据你的情况,使用pytz是个不错的选择(之前也提到过)。你可以通过 easy_install
来安装它。我建议在服务器上实时将时间转换为UTC(协调世界时),然后在客户端将这些UTC时间转换为用户的本地时区(可以通过浏览器中的Javascript或者手机操作系统来实现)。
将数据库中存储的 America/Los_Angeles
时区的时间转换为UTC的服务器代码如下:
>>> # Get a datetime from the database somehow and store into "x"
>>> x = ...
>>>
>>> # Create an instance of the Los_Angeles timezone
>>> la_tz = pytz.timezone(settings.TIME_ZONE)
>>>
>>> # Attach timezone information to the datetime from the database
>>> x_localized = la_tz.localize(x)
>>>
>>> # Finally, convert the localized time to UTC
>>> x_utc = x_localized.astimezone(pytz.utc)
如果你把 x_utc
发送到网页上,Javascript可以将其转换为用户操作系统的时区。如果你把 x_utc
发送到iPhone上,iOS也可以做到这一点,等等。希望这些信息对你有帮助。
在Django中编写支持时区的代码其实并不难:
我写了一个简单的Django应用,帮助处理Django项目中的时区问题:https://github.com/paluh/django-tz。这个项目是基于Brosner(django-timezone)的代码,但采用了不同的方法来解决问题——我觉得它实现了类似于你和FernandoEscher的提议。
所有的日期时间值都存储在数据库中,使用一个时区(根据TIME_ZONE设置),然后在模板和表单中转换为用户的时区(有一个日期时间字段的表单小部件,里面包含一个额外的时区小部件)。每次日期时间的转换都是明确的——没有什么魔法。
另外,还有一个每个线程的缓存,可以简化这些日期时间的转换(这个实现是基于Django的国际化翻译机制)。
当你想记住用户的时区时,你应该在用户资料模型中添加一个时区字段,并编写一个简单的中间件(可以参考文档中的示例)。
更新,2013年1月:Django 1.4 现在支持 时区 了!!
旧的回答,出于历史原因:
我自己也会在我的应用程序中处理这个问题。我解决这个问题的第一步是参考 Django 核心开发者 Malcom Tredinnick 在 这篇 Django 用户的帖子 中的建议。你可能需要把用户的时区设置存储在他们的个人资料里。
我还强烈建议你看看 pytz 模块,它能让处理时区变得简单很多。为了前端,我创建了一个“时区选择器”,这个选择器基于 pytz 中常见的时区。我有一个下拉框用于选择地区,另一个下拉框用于选择具体位置(比如 US/Central 会用两个下拉框来显示)。这样选择时区比从400多个选项中找要方便一些。