Python的time.time()返回本地时间戳还是UTC时间戳?

675

Python time 模块中的 time.time() 返回的是系统时间还是UTC时间?


112
时间戳没有时区,它们表示自历元以来的秒数。历元是一个特定的时间点,不依赖于时区。 - jwg
7
常用的POSIX时间戳不考虑闰秒,因此它们并不是"自纪元以来经过的[国际单位制]秒数"(它们接近于此)。 - jfs
9
@J.F.Sebastian,我认为这不是一个准确的反对意见。闰秒并不是“自纪元以来经过的秒数”。它们是时钟所记录的时间表示中不对应经过的秒数的更改。 - jwg
2
@jwg,“they”在我的评论中(以及您的第一条评论中)显然是指“时间戳”,而不是“闰秒”(否则就没有意义了)。 - jfs
4
抱歉让您感到困惑。闰秒不是“经过的秒数”,因此时间戳(即“经过的秒数”)不应该包含闰秒,也没有包含闰秒。 - jwg
6
@jwg 错了。你不能抹去物理时间。POSIX时间戳不是经过SI秒数的累计。这里有个例子:在纽约“2016年12月31日下午6:59:59”和“2016年12月31日下午7:00:01”之间经过了3秒,但对应的POSIX时间戳之间的差别只有2秒(闰秒不计算)。 - jfs
9个回答

899
time.time() 函数返回自纪元以来的秒数,类型为浮点数。请注意,“纪元”是指在UTC时间1970年1月1日开始的定义。因此,纪元是基于UTC并建立全球时间统一的。无论你在地球上哪个地方, “自纪元以来经过的秒数” (time.time()) 在同一时刻都会返回相同的值。

这里是我在我的电脑上运行的一些样本输出,同时将其转换为字符串。

>>> import time
>>> ts = time.time()
>>> ts
1355563265.81
>>> import datetime
>>> datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
'2012-12-15 01:21:05'
>>>

ts 变量是以秒为单位返回的时间。我然后使用 datetime 库将其转换为可读性更强的字符串。


81
为什么在 datetime 已经可以提供时间戳的情况下我们还需要 import time 呢?只需移除毫秒部分即可得到时间戳:str(datetime.datetime.now()).split('.')[0] - Hussain
18
@Alexis,Unix纪元在这里被定义得非常清楚(http://www.epochconverter.com/)。页面往下一些甚至给出了一个Python示例。我不明白你的评论。 - squiguy
9
@Squiguy,说实话,我不记得是什么让我这样说的。我可能误读了某些内容,并且在我在法国和美国之间移动时,一直在努力找到为什么某些测试会中断的原因,最终发现问题是由于夏令时使这段时间的星期变长。对此感到抱歉,也感谢你指出了这一点。 - Alexis
6
time.time() 返回的时间戳并不处于任何时区,它不是"秒数(seconds)在UTC时区"。"自纪元以来的秒数(seconds since the epoch)" 是一个术语;它并不代表自某一时间点以来经过的已流逝秒数(elapsed seconds)。您可以使用时区数据库(tz database)将其转换为本地时间和/或UTC时区。另外,如果您省略 .strftime(),结果几乎相同(+/- 微秒)。 - jfs
5
刚刚测试了一下,time.time() 不会返回 UTC 时间,而是返回我的本地时区时间。 - sliders_alpha
显示剩余7条评论

343

这是用于文本文件中的时间戳文本格式。您可以使用datetime.datetime.now().utcnow()函数将时间戳转换为字符串:

>>> import datetime
>>> print datetime.datetime.utcnow()
2012-12-15 10:14:51.898000

nowutcnow的差异符合预期 -- 除此之外它们的工作方式相同:

>>> print datetime.datetime.now()
2012-12-15 11:15:09.205000

您可以将时间戳显式地转换为字符串:

>>> str(datetime.datetime.now())
'2012-12-15 11:15:24.984000'

或者您可以更明确地按照自己的喜好格式化时间戳:

>>> datetime.datetime.now().strftime("%A, %d. %B %Y %I:%M%p")
'Saturday, 15. December 2012 11:19AM'

如果您想要ISO格式,请使用对象的.isoformat()方法:

>>> datetime.datetime.now().isoformat()
'2013-11-18T08:18:31.809000'

您可以在变量中使用这些,进行计算和打印而无需进行转换。

>>> ts = datetime.datetime.now()
>>> tf = datetime.datetime.now()
>>> te = tf - ts
>>> print ts
2015-04-21 12:02:19.209915
>>> print tf
2015-04-21 12:02:30.449895
>>> print te
0:00:11.239980

2
我想要纪元时间...不是日期格式...正如我提到的命令time.time()所显示的那样。 - Saransh Mohapatra
39
好的,没问题。有些人可能需要时间戳来放置在文本文件中。 - pepr
1
我是另一个人,可能由于过多的点赞而被重定向到这里。该问题存在格式错误,并且所接受的答案对于典型需求来说是误导性的:在最常用的服务器时区中获取可读的后缀 - 比如文件名。 - user6996876
要将时间戳作为字符串的一部分打印,请使用以下代码:Python2:import datetime; print "%s: My timestamp message" % datetime.datetime.utcnow() Python3:import datetime; print ("%s: My timestamp message" % datetime.datetime.utcnow()) - Mr-IDE
2
datetime.datetime.utcnow() 是有害的。它创建了一个不是本地时间的无序日期时间。除非您的本地时间是UTC,否则它将是错误的。请改用datetime.datetime.now(datetime.timezone.utc)。这会创建一个时区感知的日期时间,表示当前时间。 - Terrel Shumway
@TerrelShumway:我无法确认这一点。我的本地时间不是UTC,结果是正确的。这可能取决于操作系统和时间的操作系统设置。这也可能取决于(旧的)Python版本——如果过去存在错误。您能否更好地描述您的情况并展示出错了什么? - pepr

159

根据#squiguy的回答,为了获得真正的时间戳,我会将其从浮点数类型转换。

>>> import time
>>> ts = int(time.time())
>>> print(ts)
1389177318

至少这就是概念。


1
将时间戳进行类型转换的原因是什么?默认情况下是什么类型? - Tizzee
4
type(time.time()) 的输出结果为 <type 'float'>,表示返回值的数据类型为浮点数。 - famousgarkin
4
如果你需要比秒更精确的时间,使用浮点数就很合理。 - pepr
3
Python是强类型语言,但不要将其与静态类型混淆。 - jfs
1
@CheokYanCheng:int()是多态的。在旧版Python中,如果需要,它将返回long -- 在新版Python中,所有整数都是长整型。 - jfs
显示剩余3条评论

33

答案可能既不是也是。

  • 不是: time.time() 返回自 Epoch 以来经过的秒数,结果不依赖于时区,因此既不是 UTC 也不是本地时间。这里是关于“自 Epoch 以来的秒数”的 POSIX 定义

  • 也是: time.time() 不需要您计算机的时钟同步,因此它反映了其值(尽管与本地时区无关)。在同一时间,不同的计算机可能会得到不同的结果。另一方面,如果您的计算机时间被同步,则可以从时间戳中轻松获取 UTC 时间(如果我们忽略闰秒):

  • from datetime import datetime
    
    utc_dt = datetime.utcfromtimestamp(timestamp)
    

关于如何从各种Python版本的UTC时间中获取时间戳,请参见 如何将日期转换为根据UTC的时代秒数?


6
有一篇回答提到了datetime.utcfromtimestamp,并且是唯一正确的答案,而另一篇回答使用了datetime.fromtimestamp,但是却获得了308个赞。-(表达失落或无奈) - user6996876
@TerrelShumway 这个问题是关于 time.time() 函数返回值的(非常简短)。你的评论回答了其他问题(自从我开始回答后,你已经更改了评论。而且变得更糟了)。另外一点,应该谨慎使用“正确”这个词(时区很复杂——没有银弹——只有特定用例的权衡)。 - jfs
不要使用datetime.datetime.utcfromtimestamp(ts)。除非您的本地时间是UTC,否则它将是错误的,因为它创建了一个不是本地时间的naive datetime。相反,请使用datetime.datetime.fromtimestamp(ts, datetime.timezone.utc)。这将创建一个时区感知的datetime,表示与时间戳相同的瞬间。 - Terrel Shumway
是的。我的先前评论完全错误。datetime模块中的大多数代码将naive datetimes视为本地时间。使用naive datetimes就像在不知道编码的情况下打开文本文件。 - Terrel Shumway
@TerrelShumway 假设 UTC 时间仅适用于本地时间为 UTC 的系统是错误的。确实,stdlib 的某些部分将天真的 datetime 对象视为具有本地时区(遗憾的是)。我希望 naive_dt.astimezone() 不像 Python 3 中隐式的 bytes.encode() 那样存在。在许多情况下,内部使用 UTC 时间是有益的。关于 datetime 模块可以说很多话(我已经回答了足够多的问题以获得金徽章),但大多数都超出了“time.time() 返回什么”的范围。 - jfs

7
使用datetime库,Python 3.x可以获取本地时间戳。
#wanted format: year-month-day hour:minute:seconds

from datetime import datetime

# get time now
dt = datetime.now()
# format it to a string
timeStamp = dt.strftime('%Y-%m-%d %H:%M:%S')

# print it to screen
print(timeStamp)

我使用这个时间戳是因为它清楚地显示了日期和时间。 - Nam G VU

4

我最终选择了:

>>> import time
>>> time.mktime(time.gmtime())
1509467455.0

1
这可能满足您的本地需求,但对于期望该范围内的数字表示自[GMT]时代以来的秒数的人来说可能会产生误导。 time.time()返回类似于1574115250.818733的十进制/浮点数,而自时代以来的毫秒数很容易使用int(time.time() * 1000)得到,例如1574115254915 - MarkHu

3

在特定时区中不存在“纪元”的概念。纪元被定义为特定的时间点,因此如果更改时区,则时间本身也会发生变化。具体来说,这个时间是1970年1月1日00: 00: 00 UTC。所以,time.time()返回自纪元以来的秒数。


虽然UTC是一个时间标准而不是时区,但标准是它与GMT共享相同的时间。因此... - Craig Hicks

3

时间戳始终是UTC时间,但当您调用datetime.datetime.fromtimestamp时,它会返回与此时间戳对应的本地时区时间,因此结果取决于您的时区设置。

>>> import time, datetime

>>> time.time()
1564494136.0434234

>>> datetime.datetime.now()
datetime.datetime(2019, 7, 30, 16, 42, 3, 899179)
>>> datetime.datetime.fromtimestamp(time.time())
datetime.datetime(2019, 7, 30, 16, 43, 12, 4610)

有一个名为arrow的优秀库,具有不同的行为。在某些情况下,它会返回带有UTC时区的时间对象。

>>> import arrow
>>> arrow.now()
<Arrow [2019-07-30T16:43:27.868760+03:00]>
>>> arrow.get(time.time())
<Arrow [2019-07-30T13:43:56.565342+00:00]>

1

time.time() 返回 Unix 时间戳。您可以使用 datetime 库获取本地时间或 UTC 时间。

import datetime

local_time = datetime.datetime.now()
print(local_time.strftime('%Y%m%d %H%M%S'))

utc_time = datetime.datetime.utcnow() 
print(utc_time.strftime('%Y%m%d %H%M%S'))

.utcnow()返回的utc_time字符串格式没问题,但作为datetime对象却存在风险。由于它是naive类型,如果在Python脚本中对其进行任何操作(如timedelta算术运算),它仍然会像本地时间一样行为 - FObersteiner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接