zoukankan      html  css  js  c++  java
  • Django中的时区

    Django的settings配置中有一个USE_TZ项,默认值为True。很多人不太清楚这个配置项具体是干什么的,只知道和时区有关。下面我们就来详细聊聊它。

    首先,我们要了解一下什么是offset-awareoffset-navie

    offset-aware与offset-navie

    在Python中,有一个datetime模块,相信大家都很熟悉。但是很少有人知道这个模块的时间还可以分下面两种类型:

    • offset-naive:不含时区的类型
    • offset-aware:有时区的类型

    并且,这两种类型的时间是不可以直接比较的,比如做减法、加法、时间对比等,会抛出下面的异常:

    TypeError: can't compare offset-naive and offset-aware datetimes
    

    根本的原因在于两者一个有时区信息,一个没有。

    我们可以通过查看datetime对象的tzinfo属性,来判断具体是两者中的哪种:

    >>> import datetime
    >>> now = datetime.datetime.now()
    >>> now
    datetime.datetime(2020, 5, 26, 18, 36, 59, 811729)
    >>> now.tzinfo
    >>> now.tzinfo==None
    True
    

    可以很清楚的看到,datetime.datetime.now()是一个offset-naive类型,不含时区信息的时间对象。

    我们可以借助pytz模块,将一个offset-naive类型的时间对象转换为一个offset-aware类型的时间对象。

    先安装pytz模块:

    pip install pytz
    

    来测试一下:

    >>> import pytz
    >>> now = now.replace(tzinfo=pytz.timezone('UTC'))
    >>> now
    datetime.datetime(2020, 5, 26, 18, 36, 59, 811729, tzinfo=<UTC>)
    >>> now.tzinfo
    <UTC>
    

    反过来,也可以将一个offset-aware型转换为offset-naive型:

    >>> now = now.replace(tzinfo=None)
    >>> now
    datetime.datetime(2020, 5, 26, 18, 36, 59, 811729)
    >>> now.tzinfo == None
    True
    

    USE_TZ配置

    回到Django种来。我们知道,在安装Django的同时,默认会安装一个pytz模块,然后在django.utils下就会有一个timezone模块,其实它就是pytz.timezone

    首先,我们要清楚一件事。Django的settings配置中的USE_TZ默认值为True,也就是说,默认情况下Django数据库里面存储的日期数据是带时区信息的,也就是offset-aware类型。

    这就导致了我们有些时候,进行时间对比或者加减的操作,会抛出前面说的异常。

    TypeError: can't compare offset-naive and offset-aware datetimes
    

    那怎么办呢?

    最原始朴素的方法,自然是对时间类型进行转换,采用上面的例子中的方法,统一起来,就可以进行比较了。

    还有一种更简单的方法,那就是将USE_TZ设置为False。此时,数据库里保存的时间对象就不在包含时区信息了,和原生的datetime.datetime是一种类型,都是offset-naive类型,自然不会发生冲突。

    Tips:应该在项目开始之初,创建数据表之前就设置USE_TZ为False,否则先前保存的时间数据可能依然带有时区信息。

    其实,还有一种更适用的方法,就是USE_TZ依然保持为True,但是不再使用datetime库了,而是使用timezone来获取now时间:

    from django.utils import timezone  
      
    now = timezone.now()
    

    这样,大家都带有时区信息,自然也是可以比较的。

  • 相关阅读:
    C# 中常用数据类型与控件类型的命名规则
    通过方法名字符串调用方法
    AutoCAD.Net/C#.Net QQ群:193522571 VS2013与cad调试时的问题
    87位随机字符串
    C#访问剪切板
    AutoCAD.Net/C#.Net QQ群:193522571 c#链接到网址
    AutoCAD.Net/C#.Net QQ群:193522571 WINFORM获取计算机名、域名、用户名和当前Mac地址
    AutoCAD.Net/C#.Net QQ群:193522571 AutoCAD向命令栏发送命令
    AutoCAD.Net/C#.Net QQ群:193522571 AutoCAD中状态栏
    AutoCAD.Net/C#.Net QQ群:193522571 AutoCAD中写状态栏status bar
  • 原文地址:https://www.cnblogs.com/django-dev/p/12968403.html
Copyright © 2011-2022 走看看