在 Python 常用日期处理 -- 内置模块 datetime 探讨了 Python 如何使用 datetime, 如果是一个跨时区的应用(Web 应用都是),就不能只存储一个时间而不带时区,如此,全球用户将会看到一个相同的时间字符串,白天黑夜就错乱了。比说用户信息的更新时间存储为 2020-07-07 13: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 的例子

from datetime import datetime, 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-08 04: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

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

1 2020-07-08T04:30:26.221450+0800

2 2020-07-08T04:30:26.221543+0800

3 2020-07-07T20:30:26.221848

4 2020-07-08T04:30:26.221543UTC+08:00

5 1594153826.221895

6 2020-07-08 04:30:26.221895+08:00

7 2020-07-08T04:23:53.000112+08:00

8 2020-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 的 Python datetime 格式字符串定义找不到如何把毫秒段收缩为 3 位。

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

from datetime import datetime, 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 - Python TimeZone

$ pip install pytz

测试 pytz

from datetime import datetime

from pytz import timezone

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 是否能正确的处理夏令时(Date Saving Time)与冬令时(Night Saving Time)。回看上面代码是在 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

Date today = new Date();

System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").format(today));

ZonedDateTime now = 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 很好的解决了时区和夏/冬令时的问题

以上就是Python datetime 如何处理时区信息的详细内容,更多关于Python datetime 处理时区信息的资料请关注我们其它相关文章!

本文标题: Python datetime 如何处理时区信息

本文地址: http://www.cppcns.com/jiaoben/python/341156.html

python datetime 时区_Python datetime 如何处理时区信息相关推荐

  1. python中的datetime函数_Python datetime函数常见用法总结

    Python datetime使用指导:操作时间.日期和时间区间 在 Python 中处理日期和时间是一个很麻烦的问题.幸运的是,Python 提供了内置方法来简化这种操作:Python Dateti ...

  2. python datetime库_python datetime库使用代码详解

    python 如何将字符串转化为datetime.date心总是在最痛时,复苏:爱总是在最深时,落下帷幕. 比较省事的办法是用time模块的strptime方法来解析日期字符串成为时间对象,然后再把年 ...

  3. python的datetime举例_Python datetime库计算两个时间点之间的分钟(秒、天)数

    计算两个时间点之间的分钟数 import datetime def minNums(startTime, endTime): '''计算两个时间点之间的分钟数''' # 处理格式,加上秒位 start ...

  4. python 日期 间隔_Python datetime time 等时间 日期 之间的计算和相互转化

    from datetime importdatetime, date, timedelta, timezonefrom time importtime, ctime, localtime, strft ...

  5. python strftime模块_python datetime模块用strftime 格式化时间

    datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") datetime.datetime.now().strftime(&qu ...

  6. python datetime用法_python datetime用法学习笔记

    一.主要思路:1.把表示时间的str转换为datetime对象 2.操作datetime对象输出期望的时间格式 二.把表示时间的str转换为datetime对象语法:datetime.strptime ...

  7. python的datetime举例_Python datetime.timedelta()用法及代码示例

    Python timedelta()函数存在于datetime库中,该函数通常用于计算日期差,也可以用于Python中的日期操作.这是执行日期操作的最简单方法之一. 用法: datetime.time ...

  8. python的datetime举例_Python datetime模块的使用示例

    1.获取当前年月日时分秒 # -*- encoding=utf-8 -*- import datetime now = datetime.datetime.now() print("now: ...

  9. python时间计算_python datetime库使用和时间加减计算

    datetime库使用 一.操作当前时间 1.获取当前时间 >>> importdatetime>>> printdatetime.datetime.now()20 ...

最新文章

  1. C#中获取程序当前路径的集中方法
  2. 技术图文:Matlab向量 VS. Python列表
  3. ReSIProcate源码目录下功能说明
  4. django 学习笔记
  5. java线程唤醒线程_Java中如何唤醒“指定的“某个线程
  6. 博为峰JavaEE技术文章 ——MyBatis 简介(2)
  7. JAVA每个初学者都应该搞懂的问题 还可以比较基础
  8. 就地链表反转_链表常见问题总结(一)
  9. android 分析boot.img,Android 系统准备知识-bootimg文件的结构
  10. 原来,这就叫“不值得定律”
  11. 树状数组--前n项和;
  12. 山峰Mac动态桌面壁纸
  13. 计算机专业电脑内存,电脑内存大小是否和速度有关?
  14. 爬取虾米音乐flac高品质下载
  15. Mysql如何保证原子性,一致性,持久性
  16. ViewPager(六)让ViewPager用起来更顺滑——设置间距与添加转场动画
  17. The Little Match Girl,摘自iOS应用Snow White and more stories
  18. DirectX12_API流程入门篇
  19. 2022年全球与中国汽车毫米波雷达市场现状及未来发展趋势报告
  20. 数字图像处理第四版胡学龙著课后习题

热门文章

  1. 2022年天梯赛题目解析
  2. ACM-ICPC 2017 Asia QingDao:喜,抑或是悲?幸运,抑或是倒霉?退役!!!
  3. 简易验收管理系统的设计(php)
  4. manjar强制关闭应用
  5. [NC1105B]下雨天
  6. 一生只为寻找欢笑——读Linux之父林纳斯自传
  7. python3基础知识复习 --TKinter GUI的终极选择(2)
  8. PCB线路板表面处理工艺的优缺点合集
  9. docker container(容器)的使用方法
  10. 3D标签云的简单实现