Django时区详解

引言

相信使用Django的各位开发者在存储时间的时候经常会遇到这样子的错误:

RuntimeWarning: DateTimeField received a naive datetime while time zone support is active. 

这个错误到底是什么意思呢?什么是naive datetime object?什么又是aware datetime object?

在Django配置中如果将settings.TIME_ZONE设置为中国时区(Asia/Shanghai),为什么以下时间函数会得到时间相差较大的结果?

# settings.py
TIME_ZONE = 'Asia/Shanghai'

# python manage.py shell
>>> from datetime import datetime
>>> datetime.now()
datetime.datetime(2016, 12, 7, 12, 41, 22, 729326)
>>> from django.utils import timezone
>>> timezone.now()
datetime.datetime(2016, 12, 7, 4, 41, 36, 685921, tzinfo=<UTC>)

接下来笔者将详细揭秘在Django中关于时区的种种内幕,如有不对,敬请指教。

准备

UTC与DST

UTC可以视为一个世界统一的时间,以原子时为基础,其他时区的时间都是在这个基础上增加或减少的,比如中国的时区就为UTC+8。
DST(夏时制)则是为了充分利用夏天日照长的特点,充分利用光照节约能源而人为调整时间的一种机制。通过在夏天将时间向前加一小时,使人们早睡早起节约能源。虽然很多西方国家都采用了DST,但是中国不采用DST。(资料来源:DST 百度百科

naive datetime object vs aware datetime object

当使用datetime.now()得到一个datetime对象的时候,此时该datetime对象没有任何关于时区的信息,即datetime对象的tzinfo属性为None(tzinfo属性被用于存储datetime object关于时区的信息),该datetime对象就被称为naive datetime object。

>>> import datetime
>>> naive = datetime.datetime.now()
>>> naive.tzinfo
>>>

既然naive datetime object没有关于时区的信息存储,相对的aware datetime object就是指存储了时区信息的datetime object。
在使用now函数的时候,可以指定时区,但该时区参数必须是datetime.tzinfo的子类。(tzinfo是一个抽象类,必须有一个具体的子类才能使用,笔者在这里使用了pytz.utc,在Django中的timezone源码中也实现了一个UTC类以防没有pytz库的时候timezone功能能正常使用)

>>> import datetime
>>> import pytz
>>> aware = datetime.datetime.now(pytz.utc)
>>> aware
datetime.datetime(2016, 12, 7, 8, 32, 7, 864077, tzinfo=<UTC>)
>>> aware.tzinfo
<UTC>

在Django中提供了几个简单的函数如is_aware, is_naive, make_aware和make_naive用于辨别和转换naive datetime object和aware datetime object。

datetime.now简析

在调用datetime.now()的时候时间是如何返回的呢?在官方文档里只是简单地说明了now函数返回当前的具体时间,以及可以�指定时区参数,并没有具体的说明now函数的实现。

classmethod datetime.now(tz=None)
Return the current local date and time. If optional argument tz is None or not specified, this is like today(), but, if possible, supplies more precision than can be gotten from going through a time.time() timestamp (for example, this may be possible on platforms supplying the C gettimeofday() function).

If tz is not None, it must be an instance of a tzinfo subclass, and the current date and time are converted to tz’s time zone. In this case the result is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)). See also today(), ut

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值