Python 怎么知道一个时间戳是不是 utc 时间转过来的

2018-04-17 10:26:02 +08:00
 mzmxcvbn

新手一枚,以前一直以为时间戳是不带时区的,可今天发现 datetime.now().timestamp()和 datetime.utcnow().timestamp()转出来的时间戳不一样。 那么问题来了,拿到一个外部传进来的时间戳时,我应该用 utcfromtimestamp()呢,还是 fromtimestamp()去转成 datetime 形式

7726 次点击
所在节点    Python
53 条回复
mzmxcvbn
2018-04-17 11:09:24 +08:00
@wwqgtxx 啊。。。为什么我 time.time()出来的时间戳是和 datetime.now().timestamp()一样的,
bolide2005
2018-04-17 11:11:13 +08:00
@mzmxcvbn #16
用 time.gmtime(0)查一下你系统的 epoch,看看是不是标准 utc,可能是你系统配置或者时钟有问题
mzmxcvbn
2018-04-17 11:14:45 +08:00
@bolide2005 time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0) 查出来是这个,应该对的吧
honeycomb
2018-04-17 11:15:46 +08:00
如果它是一个 ISO8601 格式的时间戳,那么它已经携带了时区信息,或表示它是一个 UTC 时间(即以 UTC+0 处理)

如果已知它是整数且是 Unix 时间戳,那么就隐含了是 UTC 时间的信息

如果什么都没有,就不好说了
zsdroid
2018-04-17 11:20:32 +08:00
。。。首先时间戳是没有时区的
那么为什么 datetime.now().timestamp()和 datetime.utcnow().timestamp()转出来的时间戳不一样,
因为 datetime.now()和 datetime.utcnow()不一样
zjsxwc
2018-04-17 11:20:40 +08:00
咦,我 python 里的 datetime 对象怎么没有 timestamp 方法。
scriptB0y
2018-04-17 11:24:43 +08:00
用个 arrow 或 https://github.com/sdispater/pendulum (推荐后者)

importPython 3.6.4 (default, Mar 9 2018, 23:15:03)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import arrow

In [2]: arrow.now().timestamp, arrow.utcnow().timestamp
Out[2]: (1523935279, 1523935279)
wwqgtxx
2018-04-17 11:25:08 +08:00
@mzmxcvbn 又翻了一下文档,time.time()用的是本地时区,标准的时间戳还是应该用 datetime.utcnow().timestamp()
wwqgtxx
2018-04-17 11:28:44 +08:00
@scriptB0y 你那个还是按照 GMT+8 时区算的时间戳
mzmxcvbn
2018-04-17 11:29:07 +08:00
@wwqgtxx 好的,谢谢,辛苦了。我还以为是我电脑有问题呢,看来取标准时间戳只能用 datetime.utcnow().timestamp()了
bolide2005
2018-04-17 11:35:02 +08:00
@wwqgtxx #28 时间戳没有时区概念


@mzmxcvbn #23 看代码,datetime.timestamp 方法,实际上计算的是你给的那个 datetime 相对于 utc 时间的秒数,但里面默认了使用本地时区

看这里
>>> datetime.utcnow()
datetime.datetime(2018, 4, 17, 3, 32, 23, 714844)
>>> datetime.utcfromtimestamp(datetime.utcnow().timestamp())
datetime.datetime(2018, 4, 16, 19, 32, 41, 180266)

看到了吗?用这个 utcnow 时间戳是转换不回来正确的 utc 时间的,因为提前了 8 个小时,所以,time.time()才是正确的,用这个网站验证你的时间戳
https://www.unixtimestamp.com/
ETiV
2018-04-17 11:35:37 +08:00
看你们讨论让我想起几周前我跟我们同事讨论时间戳的问题,也是特别纠结。
当时还说,得叫霍金来帮忙…

每隔几天霍金去世了……
AndyMo
2018-04-17 11:36:17 +08:00
@AndyMo 看了 NoAnyLove 的回复,去查了下。时间戳没有时区概念,datetime.datetime.fromtimestamp()和 utcfromtimestamp()区别只是前者将时间转到了当前主机的本地时间。所以用哪个方法转化时间戳都一样……之前我也没理解时间戳的概念啊。但是不问外部传来时间戳的时区,就不知道它原来的本地时间。这个我应该还是没说错。
wwqgtxx
2018-04-17 11:36:32 +08:00
@bolide2005 时间戳本身的确没有时区的概念,但是按照 unix 标准时间戳的定义是用 utc 时区进行计算的
incompatible
2018-04-17 11:36:33 +08:00
楼主没搞清设计这个接口时的权责划分的问题。
你拿到 datetime 时,你不需要考虑它的来源是 datetime.now()还是 datetime.utcnow(),这是调用你的接口的人应该考虑的问题。你只要按照固定的方法(比如 fromtimestamp())来处理就好了。

如果你真的这么在意 datetime 的时区,那么改一下接口的设计,加上 tzinfo,让调用方把 datetime 和 tzinfo 一并传给你。
Justkkk
2018-04-17 11:37:51 +08:00
推荐个库 arrow 专解决这些时间转换的破问题
bolide2005
2018-04-17 11:38:00 +08:00
@wwqgtxx #34 你可以按我给的那个网站验证一下,那个时间戳是正确的
wwqgtxx
2018-04-17 11:54:08 +08:00
@bolide2005 真的觉得时间是一个值得讨论 N 小时的问题,,我再清清脑子,,
AndyMo
2018-04-17 12:12:20 +08:00
@zsdroid 突然想到,既然时间戳没有时区概念,那么转化时间戳的 timestamp()是不应该传入带时区的时间。也就是 datetime.now().timestamp()是错误的用法?
mzmxcvbn
2018-04-17 12:12:21 +08:00
@bolide2005
不不不,datetime.utcnow().timestamp()只要用 fromtimestamp()就能换回正确的 utc 时间了。
datetime.now().timestamp()才要用 utcfromtimestamp()才能得到 utc 时间

d1 = datetime.now()
d2 = datetime.utcnow()

t1 = d1.timestamp()
t2 = d2.timestamp()
t3 = time.time()

nd1 = datetime.utcfromtimestamp(t1)
nd2 = datetime.fromtimestamp(t2)
nd3 = datetime.utcfromtimestamp(t3)

这里 nd1,nd2,nd3 拿到的都是相同的 utc 时间


另外,你的意思是 time.time()才是 unix 标准时间戳?,那 datetime.utcnow().timestamp()是啥

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/447412

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX