Python datetime 如何处理时区信息
在Python常用日期处理--内置模块datetime探讨了Python如何使用datetime,如果是一个跨时区的应用(Web应用都是),就不能只存储一个时间而不带时区,如此,全球用户将会看到一个相同的时间字符串,白天黑夜就错乱了。比说用户信息的更新时间存储为2020-07-0713:46:08,上海的用户和芝加哥的用户看到的是同一个时间字符串,实质上却相差好多个小时。
我们可以这么做,在服务端只存储一个Timestamp长整型值或UTC时间,Timestamp是无关乎时区的,它总是相对于一个UTC时间的偏移值;然后由客户端根据本地时区来显示当地时间。不过在服务端存储为Timestamp或UTC可读性就不强了,打开文件看到Timestamp整形值,大脑是无法直接转换为日期,UTC时间略好一些。
另一种做法可在服务端存储为开发者便于理解的带时区的时间,如2020-07-07T13:46:08.342+08:00,客户获得该时间,因为带有时区信息也就能转换为客户端本地时间。
客户端请求时还可以把本地的时区信息传送给服务端,由服务端转换为相应的本地时间发送给客户端,但HTTP头信息默认不带时区信息,客户端必须主动发送它。
本人倾向于在服务端存为带时区的时间,2020-07-07T13:46:08.342+08:00是一个标准的存储格式(ISO_OFFSET_DATE_TIME),客户端收到它再转换本地时间,JavaScript一个很好的组件moment处理时间。
探索Python对时区的处理
Python内置组件不能像Java的ZoneId.of("Asia/Shanghai")直接以时区名获得Zone,而需要知道与标准时区的偏移,如上海是东八区,在Python中要用timezone(timedelta(hours=+8)).
那么来看Python中输出带时区信息,以下是一些应用Pytho时区timezone的例子
fromdatetimeimportdatetime,timezone,timedelta tz=timezone(timedelta(hours=+8)) fmt='%Y-%m-%dT%H:%M:%S.%f%z' zoned_time1=datetime.today().astimezone(tz) print(1,zoned_time1.strftime(fmt))#2020-07-08T04:30:26.221450+0800 zoned_time2=datetime.now(tz) print(2,zoned_time2.strftime(fmt))#2020-07-08T04:30:26.221543+0800 zoned_time3=datetime.utcnow() print(3,zoned_time3.isoformat())#2020-07-07T20:30:26.221848 print(4,zoned_time2.strftime('%Y-%m-%dT%H:%M:%S.%f%Z'))#2020-07-08T04:30:26.221543UTC+08:00 timestamp=datetime.today().timestamp() print(5,timestamp)#1594153826.221895 print(6,datetime.fromtimestamp(timestamp,tz=tz))#2020-07-0804:30:26.221895+08:00 zoned_time4=datetime(2020,7,8,4,23,53,112,tzinfo=tz) print(7,zoned_time4.isoformat())#2020-07-08T04:23:53.000112+08:00 print(8,zoned_time2.isoformat())#2020-07-08T04:30:26.221543+08:00
输出为,已加到上面源代码中
12020-07-08T04:30:26.221450+0800
22020-07-08T04:30:26.221543+0800
32020-07-07T20:30:26.221848
42020-07-08T04:30:26.221543UTC+08:00
51594153826.221895
62020-07-0804:30:26.221895+08:00
72020-07-08T04:23:53.000112+08:00
82020-07-08T04:30:26.221543+08:00
时间字符串中要带有时区信息,首先时间要转换为带时区的,如用
datetime.astimezone(tz)#已有时间转换为带时区的 datetime.fromtimestamp(timestamp,tz=tz)#从timestamp构建datetime时加上时区
找到Python输出标准格式的方法
从上面的输出结果看第8行2020-07-08T04:30:26.221543+08:00接近于Java的ISO_OFFSET_DATE_TIME格式,只是毫秒段Python用了6位数字,参考strftime-strptime-behavior的Pythondatetime格式字符串定义找不到如何把毫秒段收缩为3位。
不过注意到datetime.isoformat()方法还有一个timespec可用,执行下面的代码
fromdatetimeimportdatetime,timezone,timedelta tz=timezone(timedelta(hours=+8)) now=datetime.now(tz) print(now.isoformat(timespec='milliseconds'))
输出为
2020-07-08T04:41:10.793+08:00
这正式我们想要的。还不仅仅是,继续往下读,我们还需要让Python支持夏令时,否则对于芝加哥时间夏天和冬天看到的都是-5,那是不对的。
pytz组件构建时区
Python也有一个通过时区名称获得timezone的组件,那就是pytz-PythonTimeZone
$pipinstallpytz
测试pytz
fromdatetimeimportdatetime frompytzimporttimezone tz_shanghai=timezone('Asia/Shanghai') tz_chicago=timezone('America/Chicago') print(datetime.now(tz=tz_shanghai).isoformat(timespec='milliseconds')) print(datetime.now(tz=tz_chicago).isoformat(timespec='milliseconds'))
输出为
2020-07-08T04:55:29.699+08:00
2020-07-07T15:55:29.699-05:00
关于夏令时与冬令时
国内实行夏令时制还是很多年前的事了,80后初期生人或许还有些印象,就是下午放了学走到街上就能看到《新闻联播》。为了达成一切形式的统一,我们不再实行夏令时制了,避免了造成可能的分裂。但其他国家仍然有下令时,这会造成同一个地方在一年中产生两个时区。
例如芝加哥,在夏季时timezone是-05:00,冬季时是-06:00.
现在就来看一下Python是否能正确的处理夏令时(DateSavingTime)与冬令时(NightSavingTime)。回看上面代码是在7月份执行的结果,此时如果把本地时间改为12月份,再看输出
2020-12-08T06:10:27.862+08:00
2020-12-07T16:10:27.862-06:00
上海的时区仍然为+08:00,而芝加哥的时区变成了-06:00
Python本身不支持对时令的支持,Python只知道与UTC标准时区的偏移,timezone(timedelta(hours=-5),夏天冬天它的偏移都是-5,实现夏令冬令时是由pytz达成的,同样的tz=timezone('America/Chiago')
夏天的结果是Python的timezone(timedelta(hours=-5))
冬天的结果是Python的timezone(timedelta(hours=-6))
对比Java对时区的处理
不妨看下隔壁Java是如何对时区处理的,分别测试了新旧时间API
Datetoday=newDate(); System.out.println(newSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").format(today)); ZonedDateTimenow=ZonedDateTime.now(ZoneId.of("Asia/Shanghai")); System.out.println(now.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
2020-07-07T14:53:55.017-05:00
2020-07-08T03:53:55.031+08:00
小结一下
时间用Timestamp(长整形值)或统一的UTC时间存储和传输,在显示时转换为本地时间,但存储介质上可读性差
用timezone(timedelta(hours=-5))应用时区来存储,可读性增强,但会有夏/冬令时间误差问题
用pytz的timezone('America/Chicago')由时区名来构造timezone很好的解决了时区和夏/冬令时的问题
以上就是Pythondatetime如何处理时区信息的详细内容,更多关于Pythondatetime处理时区信息的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。