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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15447632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:08:08  来源:igfitidea点击:

Python: Convert UTC time-tuple to UTC timestamp

pythondatetime

提问by treecoder

My problem: I need to convert a UTC time-tuple into a UTC timestamp. But I have some confusions.

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

First a bit info:

首先是一点信息:

  • time.mktime(tuple): this function always returns the timestamp in localtime.

    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): this returns the UTC timestampfrom the supplied time tuple

    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

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

    这是 localtime() 的反函数。它的参数是 struct_time 或完整的 9 元组,它表示本地时间的时间,而不是 UTC。

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

    接受时间模块中的 gmtime() 函数返回的时间元组,并返回相应的 Unix 时间戳值。事实上,time.gmtime() 和 timegm() 是彼此的倒数

Now let's do a test:

现在让我们做一个测试:

>>> 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)

Why are there four different values? And which one is right when I want to convert a UTC time-tuple into a UTC timestamp?

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

UPDATTE

更新



I think I have found answers to my confusions, so let me explain.

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

First, we need to know something important:

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

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.

有两种日期和时间对象:“naive”和“aware”。

感知对象具有足够的适用算法和时间调整知识,例如时区和夏令时信息,以相对于其他感知对象定位自身。有意识的对象用于表示不可解释的特定时刻[1]。

一个天真的对象不包含足够的信息来明确地相对于其他日期/时间对象定位自己。一个简单的对象是否代表协调世界时 (UTC)、本地时间或其他时区的时间完全取决于程序,就像特定数字代表米、英里或质量取决于程序一样。朴素的对象易于理解和使用,但代价是忽略了现实的某些方面。

What we get from datetime.utcnow()or datetime.now()are "naive" objects. This means that the datetimeobject that is returned does not, in anyway, say anything about your local time or UTC time -- it just represents "some time". It just encapsulates date & time information (year, month, day, hour,minutes, seconds, etc.). It is YOUR responsibility to associate it with the notion of local or UTC.

我们从datetime.utcnow()或者datetime.now()是“天真的”对象。这意味着datetime返回的对象无论如何都不会说明您的本地时间或 UTC 时间——它只是代表“某个时间”。它只是封装了日期和时间信息(年、月、日、小时、分钟、秒等)。您有责任将其与本地或 UTC 的概念相关联。

So, remember that a naive datetime object just represents "some time". The datetime.now()function returns a "some time" that is equal to your current time, and the datetime.utcnow()function returns "some time" that is the current time in Greenwich England (which is what UTC is).

所以,请记住,一个简单的 datetime 对象只代表“某个时间”。该datetime.now()函数返回一个等于您当前时间的datetime.utcnow()“某个时间”,该函数返回“某个时间”,即英格兰格林威治的当前时间(即 UTC 时间)。

The "some time" is just a value for date & time. And note that on different locations on earth, the "some time" occurs on different times. For example, if a "some time" value is January 1, 10:30, than it will be the current time in Greenwich England some 5 hours BEFORE it becomes the current time in New York.

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

Hence we can see that there is two things: a generic "some time" value, and the notion that that "some time" becomes current time at different locations at different "times". (no pun here, read on)

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

Now, let's first define what is "epoch". We know that "some time" is just a generic value of time. Then, the epoch is a "some time" that occurred in Greenwich England where the values of the parameters are: January 1 1970, 00:00:00.

现在,让我们首先定义什么是“纪元”。我们知道“一些时间”只是时间的一般值。随后,时代是“一段时间”发生在格林威治英格兰各参数的值是:January 1 1970, 00:00:00

A "timestamp" is no. of seconds that have elapsed since the epoch. This means that the timestamp was 0when the time was Jan 1, 1970, 00:00:00in Greenwich England. But the timestamp was approx. (5 * 60 * 60) when time was Jan 1, 1970, 00:00:00in New York.

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

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

Thus, we can see that the same "some time" value of Jan 1, 1970, 00:00:00has different timestamps when we change locations. Hence when you talk about timestamp, you need to also say "what location" is the timestamp related to, and how much eastward or westward that location is related to Greenwich England. That location is expressed as a "timezone".

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

Now, every system (computer) has a timezone configured, and all timestamps related to that timezone effectively become the "local". The UTC is the global reference.

现在,每个系统(计算机)都配置了一个时区,并且与该时区相关的所有时间戳实际上都变成了“本地”。UTC 是全球参考。

So, let's say you have an Xvalue for "some time" which converts to:

所以,假设你有一个X“一段时间”的值,它转换为:

  • Ytimestamp in your local time
  • Ztimestamp in UTC
  • Y您当地时间的时间戳
  • ZUTC 时间戳

then this means that Yno. of seconds will have to elapse for "some time" to become the current time in your location and Zno of seconds will have to pass in order for current time in Greenwich England to become "some time".

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

Now, finally, let's come back to our functions mktimeand timegm. These take a time-tuple, which is just another representation for "some time". Remember that we're passing them a naive time which does not have any notion of local or UTC.

现在,最后,让我们回到我们的函数mktimetimegm. 这些需要一个时间元组,这只是“一段时间”的另一种表示。请记住,我们传递给他们的是一个没有任何本地或 UTC 概念的幼稚时间。

Let's say Xis a time-tuple representing a naive "some time". Then

假设X是一个时间元组,表示一个幼稚的“某个时间”。然后

  • mktime(X)will return the no. of seconds that will have to elapse in order for your local current time to become that "some time", and
  • timegm(X)will return the no of seconds that will have to be spent to make the current time of Greenwich England equal to that "some time".
  • mktime(X)将返回编号。必须经过的秒数才能使您的本地当前时间成为“某个时间”,以及
  • timegm(X)将返回使格林威治英格兰的当前时间等于“某个时间”所花费的秒数。


In the example above, nowand utc_nowrepresent naive "some time", and when we feed these "some time" values into mktimeand timegm, they simply return the no. of seconds that have to pass for the corresponding locations (your location and Greenwich England) to have their current time be that "some time".

在上面的例子中,nowandutc_now代表朴素的“某时”,当我们将这些“某时”值输入mktimeand 时timegm,它们只是返回 no。相应位置(您的位置和英格兰格林威治)必须经过的秒数才能使它们的当前时间成为“某个时间”。



Finally, back to my problem: I need to convert a UTC time-tuple into a UTC timestamp.

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

Firstly, there is no concept of "UTC time-tuple" -- it's just "some time". If I need to convert it to UTC, I simply use timegm:

首先,没有“UTC 时间元组”的概念——它只是“某个时间”。如果我需要将其转换为 UTC,我只需使用timegm

cal.timegm(datetime.timetuple(utc_now))

which will give me the timestamp for the current UTC time (i.e., the current "some time" in Greenwich England).

这将为我提供当前 UTC 时间的时间戳(即英格兰格林威治的当前“某个时间”)。

回答by Jon Skeet

There are effectively only threedifferent values. These two values:

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

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

only differ by 7 seconds, which is what you originally saw when you dumped the variables:

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

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

(Note the 22 vs 29 in the seconds part of the output.)

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

The other two values are simply erroneous, because you're applying the wrong kind of arguments - you're calling time.mktimewith UTC values instead of local values, and you're calling cal.timegmwith local values instead of UTC values. The documentation clearly says what's expected - so make sure you only use the appropriate values. You're basically seeing your local time offset (4 hours, by the looks of it) being applied when it shouldn't be (in different directions depending on where the error is).

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

When you're diagnosing things like this, it's helpful to use epochconverter.comwhich will give you the current Unix timestamp, so you can compare it with your output.

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