
最近在做项目时发现存储的时间比本地时间慢了八小时,查了很多文章,感觉都没有讲的很明白,本文根据自己的理解和如何解决的详细的记录下来,但也参考了一些文章和官网介绍。
datetime.now()datetime.now() 永远获取的是你本地的时间,和你配置无任何关系,并且是不带时区属性的。
from datetime import datetime >>> datetime.now() datetime.datetime(2021, 11, 11, 15, 20, 50, 742399)datetime.utcnow()
datetime.utcnow() 获取的标准时间,即 UTC 时间。
from datetime import datetime >>> datetime.utcnow() datetime.datetime(2021, 11, 11, 7, 58, 32, 919602)timezone.now()
timezone.now() 如果 settings.py 中的 USE_TZ 为 True 则获取的时间是 UTC 时间,False 就是本地时间和 datetime.now() 完全相同。
from django.utils import timezone >>> USE_TZ=True >>> timezone.now() datetime.datetime(2021, 11, 11, 8, 2, 14, 825261, tzinfo=django 储存到数据库的时间比本地慢八小时) USE_TZ=Fasle >>> timezone.now() datetime.datetime(2021, 11, 11, 16, 19, 20, 426752)
如果 settings.py 中的 USE_TZ 为 True 则存储的永远是 UTC 时间,这也是合理的,在 django 1.4 之前对时区是不做处理的,通常都是本地时间,都是 naive time,即不带时区的时间,但是这样会带来一个问题,如果用户居住在多个时区时,时间就会很乱,所以在django 1.4 之后启用了时区支持,全部统一使用 UTC存储日期信息,在内部使用一些感知对象去转换时间。这样即便用户在多个时区也不会有时间问题。
Naive 日期对象与 Aware 日期对象上述提到 django 内部使用一些方法去感知用户时区对象,在 datetime 对象中有一个 tzinfo 属性,它用来存储时区信息,表示为 datetime.tzinfo 子类的实例,当 USE_TZ 为 True 时日期对象就是 Aware 的,否则就是 Naive 的。
from django.utils import timezone >>> USE_TZ=True >>> timezone.now() datetime.datetime(2021, 11, 11, 8, 2, 14, 825261, tzinfo=is_aware() 和 is_naive()) // 带时区:Aware USE_TZ=Fasle >>> timezone.now() datetime.datetime(2021, 11, 11, 16, 19, 20, 426752) // 不带时区:Naive
怎么知道当前时间是否带时区和不带时区,你可以使用 is_aware() 和 is_naive() 来决定日期是 aware 还是 naive 的。
from django.utils import timezone >>> timezone.now() datetime.datetime(2021, 11, 11, 8, 35, 11, 360384, tzinfo=make_aware() 和 make_naive()) >>> now = timezone.now() >>> timezone.is_aware(now) True >>> timezone.is_naive(now) False
make_aware():返回一个本地化的时间,根据 TIME_ZONE 参数。
make_naive():返回一个不带时区的时间,根据 TIME_ZONE 的值作为时间,否则就是当前时区。
>>> from django.utils import timezone >>> now = timezone.now() >>> timezone.is_aware(now) // 判断是否带时区 True >>> now datetime.datetime(2021, 11, 11, 8, 51, 26, 327845, tzinfo=) >>> timezone.make_naive(now) // 去除时区,根据 tzinfo 中的时区属性使用 pytz 进行时区定义 datetime.datetime(2021, 11, 11, 16, 51, 26, 327845) >>> sh = timezone.make_naive(now) >>> sh datetime.datetime(2021, 11, 11, 16, 51, 26, 327845) >>> t = timezone.make_aware(sh) // 增加时区,转换成设置的 TIME_ZONE 时区的时间 >>> t datetime.datetime(2021, 11, 11, 16, 51, 26, 327845, tzinfo= )
LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_TZ = True总结
- django 默认全部储存为 utc 时间,是为了兼容各国时区问题,内部使用 is_aware() 和 is_naive() 去感知时间对象。
- 只要设置了USE_TZ=True 输出的永远是UTC时间,反之就是 datetime.now(),也不管 timezone 设置的是什么。
- 在 django 开发时,尽量使用 utc 时间,即设置USE_TZ=True,TIME_ZONE = ‘Asia/Shanghai’,并且在获取时间的时候使用django.util.timezone 中提供的方法去感知时间,从而来确定是否转换当前时间还是继续使用 utc 时间。
pytz: http://pytz.sourceforge.net/
is_aware、is_naive、make_aware、make_naive: https://docs.djangoproject.com/en/3.2/ref/utils/#django.utils.timezone.is_aware
django 时区官网:https://docs.djangoproject.com/en/3.2/topics/i18n/timezones/
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)