关于datetime:Python:将UTC时间元组转换为UTC时间戳

Python: Convert UTC time-tuple to UTC timestamp

我的问题:我需要将UTC时间元组转换为UTC时间戳。但我有一些困惑。

首先是一点信息:

  • time.mktime(tuple):此函数始终以本地时间返回时间戳。

    This is the inverse function of localtime(). Its argument is the struct_time or full 9-tuple which expresses the time in local time, not UTC.

  • calendar.timegm(tuple):这将从提供??的时间元组返回UTC时间戳

    takes a time tuple such as returned by the gmtime() function in the time module, and returns the corresponding Unix timestamp value. In fact, time.gmtime() and timegm() are each others’ inverse

现在让我们做一个测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> from datetime import datetime
>>> import time
>>> import calendar as cal

>>> utc_now = datetime.utcnow()
>>> now = datetime.now()
>>> utc_now
datetime.datetime(2013, 3, 16, 9, 17, 22, 489225)
>>> now
datetime.datetime(2013, 3, 16, 5, 17, 29, 736903)

>>> time.mktime(datetime.timetuple(utc_now)), time.mktime(datetime.timetuple(now))
(1363439842.0, 1363425449.0)
>>> cal.timegm(datetime.timetuple(utc_now)), cal.timegm(datetime.timetuple(now))
(1363425442, 1363411049)

为什么有四种不同的价值观?当我想将UTC时间元组转换为UTC时间戳时,哪一个是正确的?

UPDATTE

我想我找到了我的困惑的答案,所以让我解释一下。

首先,我们需要知道一些重要的事情:

There are two kinds of date and time objects:"naive" and"aware".

An aware object has sufficient knowledge of applicable algorithmic and political time adjustments, such as time zone and daylight saving time information, to locate itself relative to other aware objects. An aware object is used to represent a specific moment in time that is not open to interpretation [1].

A naive object does not contain enough information to unambiguously locate itself relative to other date/time objects. Whether a naive object represents Coordinated Universal Time (UTC), local time, or time in some other timezone is purely up to the program, just like it is up to the program whether a particular number represents metres, miles, or mass. Naive objects are easy to understand and to work with, at the cost of ignoring some aspects of reality.

我们从datetime.utcnow()datetime.now()获得的是"天真"的对象。这意味着返回的datetime对象无论如何都不会说出您当地时间或UTC时间的任何内容 - 它只代表"一段时间"。它只是封装了日期和时间。时间信息(年,月,日,小时,分钟,秒等)。您有责任将其与本地或UTC的概念联系起来。

所以,请记住,一个天真的日期时间对象只代表"一段时间"。 datetime.now()函数返回一个等于当前时间的"某个时间",datetime.utcnow()函数返回"某个时间",即格林威治英格兰当前时间(这是UTC的时间)。

"一段时间"只是日期和时间的价值。时间。请注意,在地球上的不同位置,"一些时间"发生在不同的时间。例如,如果"某个时间"值是1月1日,10:30,那么它将是格林威治英格兰当前时间大约5个小时,直到它成为纽约当前时间。

因此,我们可以看到有两件事:一般的"一段时间"值,以及"一段时间"在不同"时间"在不同位置成为当前时间的概念。 (这里没有双关语,请继续阅读)

现在,让我们首先定义什么是"时代"。我们知道"一段时间"只是时间的一般价值。然后,该时期是在格林威治英格兰发生的"某个时间",其中参数的值是:January 1 1970, 00:00:00

"时间戳"不是。自纪元以来已经过去的秒数。这意味着当格林威治英格兰的时间Jan 1, 1970, 00:00:00时,时间戳0。但时间戳大约是。 (5 * 60 * 60)纽约的时间Jan 1, 1970, 00:00:00

1
2
3
>>> tt = datetime.timetuple(datetime(1970, 1, 1, 0, 0, 0))
>>> cal.timegm(tt)
0

因此,我们可以看到,当我们更改位置时,Jan 1, 1970, 00:00:00的相同"某个时间"值具有不同的时间戳。因此,当您谈论时间戳时,您还需要说明"与什么位置"相关的时间戳,以及该位置与格林威治英格兰相关的向东或向西的位置。该位置表示为"时区"。

现在,每个系统(计算机)都配置了一个时区,所有与该时区相关的时间戳都有效地成为"本地"。 UTC是全球参考。

所以,假设你有一个X值的"某个时间"转换为:

  • Y您当地时间的时间戳
  • Z UTC时间戳

那意味着Y没有。几秒钟必须经过"一段时间"才能成为您所在位置的当前时间,并且Z没有几秒钟必须通过才能使格林威治英格兰当前时间成为"一段时间"。

现在,最后,让我们回到我们的函数mktimetimegm。这需要一个时间元组,这只是"一段时间"的另一种表现形式。请记住,我们传递的是一个天真的时间,没有任何本地或UTC的概念。

假设X是一个表示天真"某个时间"的时间元组。然后

  • mktime(X)将返回号码。为了让你的当地时间成为"一段时间"而必须经过的秒数,以及
  • timegm(X)将返回必须花费的秒数,以使格林威治英格兰队的当前时间等于"一段时间"。

在上面的示例中,nowutc_now表示天真的"某个时间",当我们将这些"一些时间"值提供给mktimetimegm时,它们只返回no。必须通过相应位置(您的位置和格林威治英格兰)的秒数,以使其当前时间为"一段时间"。

最后,回到我的问题:我需要将UTC时间元组转换为UTC时间戳。

首先,没有"UTC time-tuple"的概念 - 它只是"一段时间"。如果我需要将其转换为UTC,我只需使用timegm

1
cal.timegm(datetime.timetuple(utc_now))

这将给出我当前UTC时间的时间戳(即格林威治英格兰当前的"一段时间")。


实际上只有三个不同的值。 这两个值:

1
2
1363425449.0 (time.mktime(datetime.timetuple(now))
1363425442   (cal.timegm(datetime.timetuple(utc_now)))

仅相差7秒,这是您最初在转储变量时看到的内容:

1
2
3
4
>>> utc_now
datetime.datetime(2013, 3, 16, 9, 17, 22, 489225)
>>> now
datetime.datetime(2013, 3, 16, 5, 17, 29, 736903)

(注意输出的秒部分中的22 vs 29。)

其他两个值只是错误的,因为您正在应用错误类型的参数 - 您使用UTC值而不是本地值调用time.mktime,并且您使用本地值而不是UTC值调用cal.timegm。 文档清楚地说明了预期的内容 - 因此请确保只使用适当的值。 您基本上会看到当它不应该(根据错误的位置在不同的方向)应用的本地时间偏移(4小时,按其外观)。

当您诊断出这样的事情时,使用epochconverter.com会很有帮助,它将为您提供当前的Unix时间戳,因此您可以将其与输出进行比较。