datetime.replace(tzinfo=pytz.timezone('Asia/Shanghai’) 后时间戳变小
【现象描述】
python 的 datetime replace timezone 为 ‘Asia/Shanghai' 和 ’PRC‘,然后取得的时间戳不正确。
print(datetime.now().replace(tzinfo=pytz.timezone('PRC')).timestamp())print(datetime.now().replace(tzinfo=pytz.timezone('Asia/Shanghai')).timestamp())
print(datetime.now().timestamp())
前两个值一致;比第三个值小了几百秒;
【正确性】
第三个值是正确的。
【问题】
- 为什么?
- <font color="red">如果系统环境时区不是 UTC+8 的话,而输入的“日期时间字符串”是北京时间,那么怎么求正确的时间戳???</font>
回答:
亚洲/上海 or 中华人民共和国(PRC)的 pytz.timezone 和 「北京时间」有 6 分钟偏移。
原因有历史原因,可以搜索到!
所以在处理“北京时间”的时候,需要掌握一定的知识。
以下内容都默认输入的时间(字符串等)都是北京时间,而且不带时区后缀
- 使用 Python 的 datetime.datetime(<北京时间>).timestamp() 得到的是正确的时间戳(timestamp);除非你电脑的系统时区不是中国的。
也就是说,datetime.datetime 没有指定时区的话,得到的 datetime.datetime 实例使用的时区(默认时区)就是 Python 运行环境的时区(一般就是操作系统设定的时区)。
所以,如果你在中国使用电脑,电脑设定的时区是中国,你创建的 datetime.datetime 实例中的时间是北京时间,那么:instance.timestamp() # instance: <datetime.datetime>
得到的就是正确的时间戳。 作为一名软件工程师,应当要考虑到自己写的代码不止在一处电脑运行;所以不能绝对保证 Python 的运行环境时区就是中国的(生产环境上,这一点应该有运维保证)。
那么,对于不含有指定时区的「日期时间」输入,但我们要将这个输入作为【北京时间】处理的时候,就应该多敲几个字符 ensure 得到的 datetime.datetime 实例上的时区信息是 UTC+8:00 的,怎么做到这一点?
看如下代码:>>> import datetime as dt
>>> import pytz
>>> pytz.timezone('Asia/Shanghai').localize(
... dt.datetime(2020, 9, 25, 18, 12, 23)
... ).timestamp() # correct way
1601028743.0
>>>
>>> dt.datetime(2020, 9, 25, 18, 12, 23).replace(
... tzinfo=pytz.timezone('Asia/Shanghai')
... ).timestamp() # 00:06 offset
1601028383.0
这段代码直接 .timestamp() 取了时间戳
各位也可以去掉 .timestamp() 看出来pytz.timezone(<时区>).localize(<datetime.datetime>)
和datetime.datetime.replace(tzinfo=pytz.timezone(<时区>))
得到的 datetime.datetime 实例结果中,tzinfo 的不同(自己试一下)。即,使用 .localize 的方式才是处理【北京时间】的正确方式!
- “ensure 得到的 datetime.datetime 实例上的时区信息是 UTC+8:00”
之所以这么做,是因为这个帖子,原本的问题是得到 Unix timestamp【时间戳】的问题;
在 Python 中,【过去日期时间】的时间戳使用借由 datetime.datetime 获得是很合理的方式!
获取时间戳的方式就是instance.timestamp() # instance: <datetime.datetime>
但是这么获取时间戳的时候,python 需要知道这个 datetime.datetime 的 instance 是哪个时区的,才能计算时间戳;默认时区的方式我在 1. 中已经说了,如果没理解请回到 1. 点再看一下。
但是如果我们考虑默认时区不是 UTC+8:00 的话,那么从 datetime.datetime 实例计算时间戳就会有问题;所以我们可以通过 2. 中的两种方式(.replace
,.localize
) 来得到含有【中国时区】(tzinfo)的 datetime.datetime 实例,然后由这个实例计算时间戳就是正确的了。
而因为历史原因,所以.replace
的解决方案会有 6 分钟的 offset,所以,实际上我们处理【北京时间】的正确方式应当是.localize
的方式。
最后,即使不是求【时间戳】,我们可能需要处理一个【日期时间】字符串为 Python 的 datetime.datetime 实例,那么也应该使用 .localize
为其添加上 tzinfo 信息(UTC+8:00)
除了 pytz 还有其它库可以处理时区;这里不再做展开。
回答:
同一时刻,差整360秒
这个问题,参看
https://blog.csdn.net/starrain00/article/details/18323807
update
其实有更简单的方法,就是使用datautil库
from dateutil import tzfrom datetime import datetime
cntzinfo = tz.gettz('Asina/Shanghai')
now = datetime.now()
now_cn = now.replace(tzinfo=cntzinfo)
以上是 datetime.replace(tzinfo=pytz.timezone('Asia/Shanghai’) 后时间戳变小 的全部内容, 来源链接: utcz.com/a/163728.html