zoukankan      html  css  js  c++  java
  • 48.python&&django时区转化

    1.python时区转换:

    最近工作中遇到了一个问题:我的server和client不是在一个时区,server时区是EDT,即美国东部时区,client,就是我自己的电脑,时区是中国标准时区,东八区。处于测试需要,我需要向server发送一个时间,使得server在这个时间戳去执行一些动作。这个时间戳通常是当前时间加2分钟或者几分钟。
    
    通常美东在夏令时时,和我们相差12小时,所以直接减掉这12小时,然后再加两分钟,可以实现发送基于server的时间戳,但是只有一半时间是夏令时,所以考虑还是基于时区来做。百度了一下,Python有一个模块pytz是时区相关的,但不是builtin方法,所以需要安装一下。
    
    1. 首先安装pytz,pip install pytz.
    
    2. 试了一下水,打印出美国的时区:
        import pytz
        print(pytz.country_timezones('us'))  # 太长了自己打印
        
        
    3.下一步,打印出美东的current time。
    	import pytz
        import time
        import datetime
        tz = pytz.timezone('America/New_York')
        a = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
        print(a)
    
        #2016-08-18 02:26:53
        
    4. 将时间转换为秒,加上120秒,然后再转换回标准格式:
        import pytz
        import time
        import datetime
    
        print(pytz.country_timezones('us'))
        tz = pytz.timezone('America/New_York')
        a = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
        print(a)
        b=time.mktime(time.strptime(a,'%Y-%m-%d %H:%M:%S'))+int(2)*60
        print(time.strftime("%Y-%m-%d %H:%M",time.localtime(b)))
    
    

    2.django时区问题:

    Django时间时区问题(received a naive datetime while time zone support is active)
    在django1.4以后,存在两个概念
    naive time(不带时区的时间)与 active time(带逝去的时间)。 timer.tzinfo查看所带时区,或者 import timezone , timzone.is_aware(timer) 带了返回true,不带返回false
    
    举例来说,使用datetime.datetime.utcnow()、datetime.datetime.now()输出的类似2015-05-11 09:10:33.080451就是不带时区的时间(naive time),
    
    而使用django.util.timezone.now()输出的类似2015-05-11 09:05:19.936835+00:00的时间就是带时区的时间(Active time),其中+00:00表示的就是时区相对性。
    
    另外一个概念UTC时间,UTC时间表示的是格林尼治平均时即可,即零区时间。而北京时间表示的是东八区时间,即UTC+8。
    
    下面列出了几个常见的时区问题
    问题一:三个时间datetime.datetime.now()、datetime.datetime.utcnow()与django.util.timezone.now()的区别
    
    datetime.datetime.now():输出的永远是本地时间(naive time)与配置无任任何关系。
    datetime.datetime.utcnow():如果setting中配置USE_TZ=True则输出的是UTC时间(naive time),如果setting中配置USE_TZ=False,则该输出时间与datetime.datetime.now()完全相同。
    django.util.timezone.now():如果setting中配置USE_TZ=True则输出的是UTC时间(active time),如果配置USE_TZ=False,则与datetime.datetime.now()完全相同。
    
    问题二:django存储到数据库的时间比本地时间小8个小时?
    
    首先要明确的一点,Django1.4版本之前,对时区毫无概概念,对时间的存取、展示不做任何处理,数据库里存储的通常是本地时间,当然都是naive time。
    Django在1.4版本之后存储如果设置了USE_TZ=True,则存储到数据库中的时间永远是UTC时间。这时如果settings里面设置了USE_TZ=True与TIME_ZONE = 'UTC',用datetime.datetime.now()获取的时间django会把这个时间当成UTC时间存储到数据库中去。如果修改设置为USE_TZ=True与TIME_ZONE = 'Asia/Shanghai',用datetime.datetime.now()获取的时间由于不带时区,django会把这个时间当成Asia/Shanghai时间,即东八区时间,然后django会把这个时间转成带时区UTC时间存储到数据库中去,而读的时候直接按UTC时间读出来,这就是网上很多人遇到的存储到数据库中的时间比本地时间会小8个小时的原因。
    
    问题三:DateTimeField role_cost_history.cost_time received a naive datetime (2015-05-12 19:59:01.259517) while time zone support is active?
    
    这个问题是因为如果设置了USE_TZ=True之后,model里面认为DateTimeField使用UTC时间(带时区的时间),这时用datetime.datetime.now()获取的时间是不带时区的就会报这个问题。
    
    问题四:django.util.timezone.now()输出时间比本地时间小8个小时
    
    只要设置了USE_TZ=True,django.util.timezone.now()输出地永远是UTC时间,不管你设置的TIME_ZONE是什么。如果USE_TZ=False,则django.util.timezone.now()输出等同于datetime.datetime.now(),也不管TIME_ZONE设置的是什么。
    
    问题五:模板显示时间
    
    在设置了USE_TZ=True之后,如果设置了TIME_ZONE = 'Asia/Shanghai',尽管数据库中存储的是UTC时间,但在模板显示的时候,会转成TIME_ZONE所示的本地时间进行显示。
    
    建议:为了统一时间,在django开发时,尽量使用UTC时间,即设置USE_TZ=True,TIME_ZONE = 'Asia/Shanghai',并且在获取时间的时候使用django.util.timezone.now()。因为后台程序使用时间时UTC时间就能满足,也能保证证模板时间的正确显示。
    
    问题六:django时区问题解决 ***** 
        在Django的配置文件settings.py中,有两个配置参数是跟时间与时区有关的,分别是TIME_ZONE和USE_TZ.
        1.如果USE_TZ设置为True时,Django会使用系统默认设置的时区,即America/Chicago,此时的TIME_ZONE不管有没有设置都不起作用。
    
    	2.如果USE_TZ 设置为False,而TIME_ZONE设置为None,则Django还是会使用默认的America/Chicago时间。
    
    	3.如果TIME_ZONE设置为其它时区的话,则还要分情况,如果是Windows系统,则TIME_ZONE设置是没用的,Django会使用本机的时间。如果为其他系统,则使用该时区的时间,如设置USE_TZ = False, TIME_ZONE = 'Asia/Shanghai', 则使用上海的UTC时间。
    
        
    根据上面的留个问题?
    	我感觉直接设置为USE_TZ=True,是数据库存取都是用utc时间,TIME_ZONE使用UTC这样你存入数据库的时间和拿出来的时间都是utc,但是这个utc使用的却是你的本地时间.也就是说数据库存的是本地时间的UTC格式(可以理解为这个utc时间是假的,存的就是你本地时间,只不过因为你的TIME_ZONE设置的是UTC)
            TIME_ZONE = 'Asia/Shanghai'  # django中存入数据库(就是通过django Model建表字段中的的data相关的字段在生成时间时的时区auto_now 以及auto_now_add等)前获取时间过程使用时区(生成时)
            USE_TZ = True  # 存入数据库时的时候是否将存入的时间转换为utc时间(存之前)
    	将经过TIME_ZONE生成的时间,存入数据库之前是否使用USE_TZ转换,True转化为UTC时间,False不转换
    
    """
    	1.获取时间
            utc_time = datetime.utcnow()    # utcnow()获取世界标准时间。
            print(f'1、UTC时间为:{utc_time}')
         
            local_time = datetime.now()     # now() 获取本地时间。
            print(f'1、本地时间为:{local_time}')
        2.定义时区对象
            利用 timezone() 可以设置时区对象,里面参数可由 和 timedelta() 提供。
            timedelta() 是用来实现对日期的加减。参数如下:
            timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]]) 
            从构造函数的定义中可以看出,所有参数都是可选的,并且默认都是0。
            from datetime import timezone, timedelta
            beijing = timezone(timedelta(hours=8))
            print(f'1、北京时区为:{beijing}')
            
            Tokyo = timezone(timedelta(hours=9))
            print(f'2、东京时区为:{Tokyo}')
             
            New_York = timezone(timedelta(hours=-4))
            print(f'3、纽约时区为:{New_York}')
             
            utc = timezone.utc
            print(f'4、世界标准时区为:{utc}'
        
    """
    import datetime
    import pytz
    from django.utils import timezone
    
    max = datetime.datetime.max.replace(tzinfo=datetime.timezone.utc)
    
    
    def now():
        return datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
    
    
    def astimezone(dt: datetime.datetime, tzinfo: pytz.tzinfo.DstTzInfo):
        """如果带时区就转换"""
        assert timezone.is_aware(dt)
        return tzinfo.normalize(dt.astimezone(tzinfo))
    
    
    def as_cn_cst(dt: datetime.datetime):
        """转换为上海时区"""
        return astimezone(dt, pytz.timezone('Asia/Shanghai'))
    
    
    def as_current_tz(dt: datetime.datetime):
        """转换为本地时区"""
        return astimezone(dt, timezone.get_current_timezone())
    
    
    def expires_hence(**delta):
        """时间的加减"""
        return now() + datetime.timedelta(**delta)
    
    
    if __name__ == '__main__':
        import os, django
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'InfosecTestPlatform.settings')
        django.setup()
        tz = pytz.timezone("Asia/Shanghai")
        t1 = datetime.datetime.utcnow().replace(tzinfo=tz)
        t2 = datetime.datetime.utcnow().replace(tzinfo=timezone.utc)
        print(as_cn_cst(t1))
        print(as_cn_cst(t2))
        print(as_current_tz(t1))
        print(as_current_tz(t2))
        """
        3. astimezone修改时区操作
            2020-06-02 02:18:46.063493+08:00   # 会发现我给t1进行绑定初始时区为上海时间,然后再使用as_cn_cst转换的时候,他认为我的的时间本来就是上海时间,这个时候就不进+8操作
            2020-06-02 10:24:46.063493+08:00   # 而t2这个我将时区设置为utc时间,这是时候我和上海时间的差别是8小时,他自动给加上了
            2020-06-01 18:18:46.063493+00:00   # 这个函数是将时间转化为utc时间,我给t1设置的是上海时间,他给我减到了8小时之前
            2020-06-02 02:24:46.063493+00:00   # 这个时区我设置的就是utc所以没有进行转换
        总结:
            使用astimezone进行时区转化的时候,需要将你的时间有时区,同时建议统一的时区使用utc,方便之后转换,否则各种时区,搞乱之后,估计你也不知道使用的是哪个了.
            同时不建议使用astimezone进行时区修改,建议在数据库统一使用一个时区的时间,之后展示使用replace直接替换为你的本地时区
        """
    

    参考:
    https://www.cnblogs.com/nurruden/p/5783839.html

  • 相关阅读:
    最后一次不用看脸的日子
    经典算法_指针
    #include <process.h>
    经典算法_文件
    stdin、stdout、stderr
    经典算法_位运算
    经典算法_结构体
    经典算法_字符串
    #include <string.h>
    #include <stdio.h>
  • 原文地址:https://www.cnblogs.com/liuzhanghao/p/12987082.html
Copyright © 2011-2022 走看看