详解Django 中是否使用时区的区别

作者:栖迟于一丘 时间:2023-08-28 04:29:48 

起步

在 Django 的模型中新加了一个日期的字段:


import datetime
class Instance(models.Model):
 ...
 start_time = models.DateTimeField(default=datetime.datetime.now)

同步到数据库时 Django 报出了一个警告:

django/db/models/fields/__init__.py:1423: RuntimeWarning: DateTimeField Instance.start_time received a naive datetime (2018-06-14 08:59:54.761510) while time zone support is active.

这个意思是应用中开启了时区功能,而字段中却使用了 naive datetime 。我看了配置文件确实启用的时区的功能:


TIME_ZONE = 'Asia/Shanghai'
USE_TZ = True

如果设置了使用时区,那么Django在数据库中以 UTC 存储日期时间信息。

要想知道时区的 Django 中的作用,我们要先了解时间有时区的没有时区的区别。

带时区与不带时区

日期时间存在两个概念: naive time 和 aware time 。 naive time 就是不带时区的时间, aware time 则是带时区的时间。比方说, datatime.datetime.utcnow() datatime.datetime.now() ,前者是 UCT 时间,后者会取机器上的本地时间,这两者呢,对于 django 来说,都是不带时区的时间(下一段会讲原因);而使用 django.utils.timezone.now() 才是带时区的时间(aware time)。

datetime.datetime.now() 输出永远都是本地时间,与配置没有任何关系。 datatime.datetime.utcnow() 则是当前的UTC日期和时间, datetime 模块是 python 的标准库,尽管 datetime.datetime 对象有一个 tzinfo 属性可以用来存储时区信息。除非该对象设置了 tzinfo 属性,否则统统会被 django 认为是 naive time 。判断可以通过 is_naive() 来判断:


import datetime
from django.utils import timezone

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]
def now():
 """
 Return an aware or naive datetime.datetime, depending on settings.USE_TZ.
 """
 if settings.USE_TZ:
   # timeit shows that datetime.now(tz=utc) is 24% slower
   return datetime.utcnow().replace(tzinfo=utc)
 else:
   return datetime.now()

返回的其实也是一个 datetime 对象。

设置了 USE_TZ=True 之后

设置了 USE_TZ=True 之后,model 里面认为 DateTimeField 使用的是UTC时间(带时区的时间),这时用 datetime.datetime.now() 获取的时间是不带时区的就会报最开始说的那个警告。

并且呢, 所有的存储和内部处理,全部都是 UTC 时间 ,包括 timezone.now() ,存储也就是指数据库中存储的是UTC时间,也就只有在表单输入或模板渲染输出的时候,才会执行 UTC 到时区的转换。基本对于开发者而言,基本不用考虑本地时间的存在,所有的使用都是 UTC 时间,这也能避免手残的手动转换,尽量使用 Django 系统代劳。

USE_TZ=False 则所有关于时间和时区的问题都有开发人员自己把控。

来源:http://www.hongweipeng.com/index.php/archives/1531/

标签:Django,时区
0
投稿

猜你喜欢

  • PHP 接入微信扫码支付总结(总结篇)

    2024-05-13 09:53:31
  • python扫描proxy并获取可用代理ip的实例

    2023-07-29 16:42:50
  • 费明红:什么样的404页面才是正确的?

    2009-05-21 17:47:00
  • ASP代码中的容错机制

    2008-10-19 17:30:00
  • Python 网络编程之TCP客户端/服务端功能示例【基于socket套接字】

    2023-12-12 07:25:21
  • ADO.NET数据连接池剖析

    2023-06-27 17:23:29
  • Python列表和集合的效率大比拼

    2021-09-04 14:10:16
  • 微信小程序的部署方法步骤

    2024-04-10 10:39:53
  • 利用 PyCharm 实现本地代码和远端的实时同步功能

    2022-03-05 08:54:10
  • 列举PHP的Yii 2框架的开发优势

    2024-05-11 10:11:23
  • SQL Server数据库复制失败的原因及解决方法

    2024-01-17 20:35:50
  • python字典get()方法用法分析

    2023-04-01 23:50:41
  • Anaconda下配置python+opencv+contribx的实例讲解

    2021-04-10 21:28:33
  • 实例讲解如何利用crontab定时备份MySQL

    2009-01-04 13:06:00
  • 基于js实现抽红包并分配代码实例

    2024-04-16 09:30:58
  • python检测lvs real server状态

    2021-12-12 21:21:36
  • Python存取XML的常见方法实例分析

    2023-07-30 07:36:38
  • 解决Win7 x64安装解压版mysql 5.7.18 winx64出现服务无法启动问题

    2024-01-22 07:57:39
  • Python用内置模块来构建REST服务与RPC服务实战

    2023-05-09 19:32:16
  • 详解Python+OpenCV实现图像二值化

    2022-01-02 13:08:07
  • asp之家 网络编程 m.aspxhome.com