详解Django 中是否使用时区的区别
起步
在Django的模型中新加了一个日期的字段:
importdatetime classInstance(models.Model): ... start_time=models.DateTimeField(default=datetime.datetime.now)
同步到数据库时Django报出了一个警告:
django/db/models/fields/__init__.py:1423:RuntimeWarning:DateTimeFieldInstance.start_timereceivedanaivedatetime(2018-06-1408:59:54.761510)whiletimezonesupportisactive.
这个意思是应用中开启了时区功能,而字段中却使用了naivedatetime。我看了配置文件确实启用的时区的功能:
TIME_ZONE='Asia/Shanghai' USE_TZ=True
如果设置了使用时区,那么Django在数据库中以UTC存储日期时间信息。
要想知道时区的Django中的作用,我们要先了解时间有时区的没有时区的区别。
带时区与不带时区
日期时间存在两个概念:naivetime和awaretime。naivetime就是不带时区的时间,awaretime则是带时区的时间。比方说,datatime.datetime.utcnow()与datatime.datetime.now(),前者是UCT时间,后者会取机器上的本地时间,这两者呢,对于django来说,都是不带时区的时间(下一段会讲原因);而使用django.utils.timezone.now()才是带时区的时间(awaretime)。
datetime.datetime.now()输出永远都是本地时间,与配置没有任何关系。datatime.datetime.utcnow()则是当前的UTC日期和时间,datetime模块是python的标准库,尽管datetime.datetime对象有一个tzinfo属性可以用来存储时区信息。除非该对象设置了tzinfo属性,否则统统会被django认为是naivetime。判断可以通过is_naive()来判断:
importdatetime fromdjango.utilsimporttimezone print(timezone.is_naive(datetime.datetime.now()))#False print(timezone.is_naive(datetime.datetime.utcnow()))#False
显然now()和utcnow()都是没有设置tzinfo的。
django判断日期对象是否是原生的唯一标准就是该对象是否设置了tzinfo
datetime与timezone
datetime是标准库的模块,timezone是django提供的时区的工具,timezone其实是在datetime基础上进行的整合的,比方django中的now函数:
[timezone.py] defnow(): """ Returnanawareornaivedatetime.datetime,dependingonsettings.USE_TZ. """ ifsettings.USE_TZ: #timeitshowsthatdatetime.now(tz=utc)is24%slower returndatetime.utcnow().replace(tzinfo=utc) else: returndatetime.now()
返回的其实也是一个datetime对象。
设置了USE_TZ=True之后
设置了USE_TZ=True之后,model里面认为DateTimeField使用的是UTC时间(带时区的时间),这时用datetime.datetime.now()获取的时间是不带时区的就会报最开始说的那个警告。
并且呢,所有的存储和内部处理,全部都是UTC时间,包括timezone.now(),存储也就是指数据库中存储的是UTC时间,也就只有在表单输入或模板渲染输出的时候,才会执行UTC到时区的转换。基本对于开发者而言,基本不用考虑本地时间的存在,所有的使用都是UTC时间,这也能避免手残的手动转换,尽量使用Django系统代劳。
若USE_TZ=False则所有关于时间和时区的问题都有开发人员自己把控。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。