注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

郁夫的博客

我爱你们,只是你们不知道!

 
 
 

日志

 
 
 
 

Django 启用 USE_TZ = True 的善后工作 - - 转  

2013-03-22 11:00:52|  分类: Django |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

以前写过一篇关于 Django 时区的 blog

Django 1.4 之后,时区的问题总算解决了。虽然 pytz 库 是可选的,但 pytz 可以帮助 Django 识别 TIME_ZONE = 'Asia/Shanghai' 对应的时区是 UTC+8 时间,因此建议启用 USE_TZ = True 的同时也安装 pytz。

1.4 之前,Django 对时区毫无概念,对时间的存取、展示不做任何处理,数据库里存储的通常是本地时间(local time)。1.4 之后,在 settings 里面设置 USE_TZ = True 即让 Django 内部把时间全部当成 UTC 时间(北京时间为 UTC+8 )对待。

但这么做还没完,还有一些琐碎的善后工作要做 -- 数据和老代码的迁移,不然时间的存取、展示都会有差错。

迁移数据库

如果之前设置了 TIME_ZONE = 'Asia/Shanghai',那么实际存储在数据库中的是 UTC+8 的时间。启用USE_TZ = True 我们要把数据库中所有的时间戳(timestamp)字段全部转换成 UTC 时间。

转换到 UTC 时间有两个方法(注:PostgreSQL 有专门的方法):

  1. 使用 manage.py shell 进入 Django shell 环境,用 Model.objects.all() 循环遍历包含DateTimeField 字段的模型,减去 timedelta(hours=8)
  2. 使用数据库 UPDATE 语句;

第一个方法不推荐使用,因为 ORM 的 save() 方法会触发 post_save signal,可能会产生不希望看到的副作用。

第二个方法是安全的(注意备份数据库),MySQL 下可以用如下 SQL 语句更新时间戳:

UPDATE `your_model` SET `last_modified` = DATE_SUB(`last_modified`, INTERVAL 8 HOUR) WHERE 1;

PostgreSQL 的时间字段原生支持时区,所以处理方法不太一样,详见 Django 官方文档 Time zones

迁移代码

启用 USE_TZ = True 后,处理时间方面,有两条 “黄金法则”:

  1. 保证存储到数据库中的是 UTC 时间;
  2. 在函数之间传递时间参数时,确保时间已经转换成 UTC 时间;

比如,通常获取当前时间用的是:

import datetime

now = datetime.datetime.now()

启用 USE_TZ = True 后,需要写成:

import datetime
from django.utils.timezone import utc

now = datetime.datetime.utcnow().replace(tzinfo=utc)

保证 now 变量存放的是 UTC 时间。

再如 fromtimestamp() 这个函数,启用 USE_TZ = True 后应使用 utcfromtimestamp() 函数替代。

模板

除非应用支持用户设置自己所在的时区,通常我们不需要关心模板的时区问题。模板在展示时间的时候,会使用 settings.TIME_ZONE 中的设置自动把 UTC 时间转成 settings.TIME_ZONE 所在时区的时间渲染。

如果确实需要支持用户设置时区,参考 Django 官方文档 Time zones

  评论这张
 
阅读(481)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017