Python datetime如何处理时区信息

  

在Python常用日期处理,内置模块datetime探讨了Python如何使用datetime,如果是一个跨时区的应用(Web应用都是),就不能只存储一个时间而不带时区,如此,全球用户将会看到一个相同的时间字符串,白天黑夜就错乱了。比说用户信息的更新时间存储为2020-07-07 13:46:08,上海的用户和芝加哥的用户看到的是同一个时间字符串,实质上却相差好多个小时。

  

我们可以这么做,在服务端只存储一个时间戳长整型值或UTC时间,时间戳是无关乎时区的,它总是相对于一个UTC时间的偏移值;然后由客户端根据本地时区来显示当地时间。不过在服务端存储为UTC时间戳或可读性就不强了,打开文件看到时间戳整形值,大脑是无法直接转换为日期,UTC时间略好一些。

  

另一种做法可在服务端存储为开发者便于理解的带时区的时间,如2020 - 07年- 07 - t13:46:08.342 +喂饲,客户获得该时间,因为带有时区信息也就能转换为客户端本地时间。

  

客户端请求时还可以把本地的时区信息传送给服务端,由服务端转换为相应的本地时间发送给客户端,但HTTP头信息默认不带时区信息,客户端必须主动发送它。

  

本人倾向于在服务端存为带时区的时间,2020 - 07年- 07 - t13:46:08.342 +喂饲是一个标准的存储格式(ISO_OFFSET_DATE_TIME),客户端收到它再转换本地时间,JavaScript的一个很好的组件时刻处理时间。

  

<强>探索Python对时区的处理

  

Python内置组件不能像Java的<代码> ZoneId.of(“亚洲/上海”)直接以时区名获得区,而需要知道与标准时区的偏移,如上海是东八区,在Python中要用<代码>时区(timedelta(小时=+ 8))>   

那么来看Python中输出带时区信息,以下是一些应用Pytho时区时区的例子

        从进口datetime datetime,时区,timedelta      tz=时区(timedelta(小时=+ 8))      fmt=' % Y - % m - H % dT %: % m: % s % f % z '   zoned_time1=datetime.today () .astimezone (tz)   打印(zoned_time1.strftime (fmt)) # 2020 - 07 - 08 - t04:30:26.221450 + 0800      zoned_time2=datetime.now (tz)   打印(zoned_time2.strftime (fmt)) # 2020 - 07 - 08 - t04:30:26.221543 + 0800      zoned_time3=datetime.utcnow ()   打印(zoned_time3.isoformat()) # 2020 - 07年- 07 - t20:30:26.221848      打印(4 zoned_time2.strftime (' % Y - % - % dT % H: % m: % s % f % Z ')) # 2020 - 07 - 08 - t04:30:26.221543utc +喂饲      时间戳=datetime.today () .timestamp ()   打印(5,时间戳)# 1594153826.221895   打印(datetime.fromtimestamp(时间戳,tz=tz)) # 2020-07-08 04:30:26.221895 +喂饲      zoned_time4=datetime(2020年,7、8、4、23日,53岁,112年,tzinfo=tz)   打印(7,zoned_time4.isoformat ()) # 2020 - 07 - 08 - t04:23:53.000112 +喂饲      打印(8,zoned_time2.isoformat ()) # 2020 - 07 - 08 - t04:30:26.221543 +喂饲      

输出为,已加到上面源代码中

  
  

1 2020 - 07 - 08 - t04:30:26.221450 + 0800
  2 2020 - 07 - 08 - t04:30:26.221543 + 0800
  3 2020 - 07年- 07 - t20:30:26.221848
  4 2020 - 07 - 08 - t04:30:26.221543utc +喂饲
  5 1594153826.221895
  6 2020-07-08 04:30:26.221895 +喂饲
  7 2020 - 07 - 08 - t04:23:53.000112 +喂饲
  8 2020 - 07 - 08 - t04:30:26.221543 +喂饲

     

时间字符串中要带有时区信息,首先时间要转换为带时区的,如用

        datetime.astimezone (tz) #已有时间转换为带时区的   datetime.fromtimestamp(时间戳,tz=tz) #从时间戳构建datetime时加上时区      

<强>找到Python输出标准格式的方法

  

从上面的输出结果看第8行2020 - 07 - 08 - t04:30:26.221543 +喂饲接近于Java的ISO_OFFSET_DATE_TIME格式,只是毫秒段Python用了6位数字,参考strftime-strptime-behavior的Python datetime格式字符串定义找不到如何把毫秒段收缩为3位。

  

不过注意到datetime.isoformat()方法还有一个timespec可用,执行下面的代码

        从进口datetime datetime,时区,timedelta      tz=时区(timedelta(小时=+ 8))   现在=datetime.now (tz)   print (now.isoformat (timespec=毫秒))      

输出为   

  

2020 - 07 - 08 - t04:41:10.793 +喂饲

     

这正式我们想要的。还不仅仅是,继续往下读,我们还需要让Python支持夏令时,否则对于芝加哥时间夏天和冬天看到的都是5,那是不对的。

  

<强> pytz组件构建时区

Python datetime如何处理时区信息