在Python中使用日期时间获取UTC时间戳
有没有办法通过指定日期来获取 UTC 时间戳?我所期望的:
datetime(2008, 1, 1, 0, 0, 0, 0)
应该导致创建
1199145600
一个简单的日期时间对象意味着没有时区信息。如果我查看 datetime.utcfromtimestamp 的文档,创建 UTC 时间戳意味着忽略时区信息。所以我猜测,创建一个简单的日期时间对象(就像我所做的那样)会产生 UTC 时间戳。但是:
then = datetime(2008, 1, 1, 0, 0, 0, 0)
datetime.utcfromtimestamp(float(then.strftime('%s')))
结果是
2007-12-31 23:00:00
日期时间对象中是否仍然存在隐藏的时区信息?我做错了什么?
Is there a way to get the UTC timestamp by specifying the date? What I would expect:
datetime(2008, 1, 1, 0, 0, 0, 0)
should result in
1199145600
Creating a naive datetime object means that there is no time zone information. If I look at the documentation for datetime.utcfromtimestamp, creating a UTC timestamp means leaving out the time zone information. So I would guess, that creating a naive datetime object (like I did) would result in a UTC timestamp. However:
then = datetime(2008, 1, 1, 0, 0, 0, 0)
datetime.utcfromtimestamp(float(then.strftime('%s')))
results in
2007-12-31 23:00:00
Is there still any hidden time zone information in the datetime object? What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
Naïve
datetime
与感知的datetime
默认
datetime
对象被认为是“naïve”:它们保留时间信息,而不需要时区信息。将简单的datetime
视为没有明确来源的相对数字(即:+4
)(事实上,您的来源在整个系统边界中是通用的)。相反,将意识
日期时间
视为绝对数字(即:8
),具有整个世界的共同起源。如果没有时区信息,您无法将“朴素”日期时间转换为任何非朴素时间表示形式(如果我们不知道从哪里开始,
+4
的目标是哪里?) 。这就是为什么您不能使用datetime.datetime.toutctimestamp()
方法。 (参见:http://bugs.python.org/issue1457227)检查您的
日期时间
dt
很幼稚,检查dt.tzinfo
,如果None
,那么它很幼稚:我有幼稚的日期时间,什么我可以做什么?
您必须根据您的特定上下文做出假设:
您必须问自己的问题是:您的
日期时间
是UTC吗?还是当地时间?如果您使用的是 UTC(您不会遇到麻烦):
如果您没有使用 UTC,欢迎来到地狱。< /p>
在使用前者之前,您必须让您的
日期时间
变得不那么幼稚功能,通过给他们返回他们想要的时区。
您需要时区名称和以下信息:
如果在生成目标原始日期时间时 DST 有效(
极端情况需要有关 DST 的最新信息):
不提供
is_dst
的后果:不使用
is_dst
将生成不正确的时间(和 UTC 时间戳)如果在实施向后 DST 的同时生成了目标日期时间
(例如通过删除一小时来更改 DST 时间)。
提供不正确的
is_dst
当然会生成不正确的仅在 DST 重叠或空洞时的时间(和 UTC 时间戳)。并且,当
提供
也是不正确的时间,发生在“洞”中(由于从未存在过的时间)
向前移动 DST),
is_dst
将给出以下解释如何考虑这个假时间,这是唯一的情况
.normalize(..)
实际上会在这里做一些事情,因为它会将其转换为实际有效时间(更改日期时间和
DST 对象(如果需要)。请注意,
.normalize()
不是必需的最后有一个正确的 UTC 时间戳,但可能是
如果您不喜欢在自己的生活中度过虚假的时光,建议您这样做
变量,特别是当您在其他地方重复使用此变量时。
和避免使用以下内容:(参见:使用 pytz 进行日期时间时区转换)< /p>
为什么?因为
.replace()
盲目地替换了tzinfo
而没有考虑到目标时间,并且会选择一个错误的 DST 对象。
而
.localize()
使用目标时间和您的is_dst
提示选择正确的 DST 对象。
旧的错误答案(感谢 @JFSebastien 提出这个问题):
希望当您创建天真的
datetime
对象时,很容易猜测时区(您的本地来源)它与系统配置有关,您希望在原始日期时间对象创建和想要获取 UTC 时间戳之间不要更改系统配置。这个技巧可以用来给出一个不完美问题。通过使用
time.mktime
,我们可以创建一个utc_mktime
:您必须确保您的
datetime
对象是在与创建的时区相同的时区创建的。已创建您的日期时间
。最后一个解决方案是不正确的,因为它假设从现在开始的 UTC 偏移量与从 EPOCH 开始的 UTC 偏移量相同。对于很多时区来说情况并非如此(在一年中的特定时刻)夏令时 (DST) 偏移量)。
Naïve
datetime
versus awaredatetime
Default
datetime
objects are said to be "naïve": they keep time information without the time zone information. Think about naïvedatetime
as a relative number (ie:+4
) without a clear origin (in fact your origin will be common throughout your system boundary).In contrast, think about aware
datetime
as absolute numbers (ie:8
) with a common origin for the whole world.Without timezone information you cannot convert the "naive" datetime towards any non-naive time representation (where does
+4
targets if we don't know from where to start ?). This is why you can't have adatetime.datetime.toutctimestamp()
method. (cf: http://bugs.python.org/issue1457227)To check if your
datetime
dt
is naïve, checkdt.tzinfo
, ifNone
, then it's naïve:I have naïve datetimes, what can I do ?
You must make an assumption depending on your particular context:
The question you must ask yourself is: was your
datetime
on UTC ? or was it local time ?If you were using UTC (you are out of trouble):
If you were NOT using UTC, welcome to hell.
You have to make your
datetime
non-naïve prior to using the formerfunction, by giving them back their intended timezone.
You'll need the name of the timezone and the information about
if DST was in effect when producing the target naïve datetime (the
last info about DST is required for cornercases):
Consequences of not providing
is_dst
:Not using
is_dst
will generate incorrect time (and UTC timestamp)if target datetime was produced while a backward DST was put in place
(for instance changing DST time by removing one hour).
Providing incorrect
is_dst
will of course generate incorrecttime (and UTC timestamp) only on DST overlap or holes. And, when
providing
also incorrect time, occuring in "holes" (time that never existed due
to forward shifting DST),
is_dst
will give an interpretation ofhow to consider this bogus time, and this is the only case where
.normalize(..)
will actually do something here, as it'll thentranslate it as an actual valid time (changing the datetime AND the
DST object if required). Note that
.normalize()
is not requiredfor having a correct UTC timestamp at the end, but is probably
recommended if you dislike the idea of having bogus times in your
variables, especially if you re-use this variable elsewhere.
and AVOID USING THE FOLLOWING: (cf: Datetime Timezone conversion using pytz)
Why? because
.replace()
replaces blindly thetzinfo
withouttaking into account the target time and will choose a bad DST object.
Whereas
.localize()
uses the target time and youris_dst
hintto select the right DST object.
OLD incorrect answer (thanks @J.F.Sebastien for bringing this up):
Hopefully, it is quite easy to guess the timezone (your local origin) when you create your naive
datetime
object as it is related to the system configuration that you would hopefully NOT change between the naive datetime object creation and the moment when you want to get the UTC timestamp. This trick can be used to give an imperfect question.By using
time.mktime
we can create anutc_mktime
:You must make sure that your
datetime
object is created on the same timezone than the one that has created yourdatetime
.This last solution is incorrect because it makes the assumption that the UTC offset from now is the same than the UTC offset from EPOCH. Which is not the case for a lot of timezones (in specific moment of the year for the Daylight Saving Time (DST) offsets).
另一种可能性是:
这可以工作,因为“d”和“epoch”都是简单的日期时间,使“-”运算符有效,并返回一个间隔。
total_seconds()
将间隔转换为秒。请注意,total_seconds()
返回一个浮点数,即使d.microsecond == 0
Another possibility is:
This works as both "d" and "epoch" are naive datetimes, making the "-" operator valid, and returning an interval.
total_seconds()
turns the interval into seconds. Note thattotal_seconds()
returns a float, evend.microsecond == 0
不使用外部模块的简单解决方案:
A simple solution without using external modules:
另请注意 calendar.timegm() 函数,如 此博客条目:
输出应与 vaab 的解决方案一致。
Also note the calendar.timegm() function as described by this blog entry:
The output should agree with the solution of vaab.
如果输入日期时间对象采用 UTC:
注意:它返回浮点数,即微秒表示为秒的分数。
如果输入日期对象采用 UTC 格式:
请参阅在 Python 中将 datetime.date 转换为 UTC 时间戳了解更多详细信息。
If input datetime object is in UTC:
Note: it returns float i.e., microseconds are represented as fractions of a second.
If input date object is in UTC:
See more details at Converting datetime.date to UTC timestamp in Python.
我觉得主要答案仍然不太清楚,值得花时间理解时间和时区。
在处理时间时要理解的最重要的事情是时间是相对!
2017-08-30 13:23:00
:(一个简单的日期时间),代表世界上某个地方的本地时间,但请注意伦敦的2017-08-30 13:23:00
与伦敦的2017-08-30 13:23:00
不是同一时间旧金山。由于同一时间字符串可以根据您所在的位置被解释为不同的时间点,因此需要一个绝对时间概念。
UTC 时间戳是以秒(或毫秒)为单位的数字,来自纪元(定义为
1970 年 1 月 1 日 00:00:00
,位于GMT
时区 +00:00 偏移量)。Epoch 以 GMT 时区为基础,因此是一个绝对时间点。 UTC 时间戳是相对于绝对时间的偏移,因此定义了绝对时间点。
这使得按时间排序事件成为可能。
如果没有时区信息,时间是相对的,并且无法在没有时区信息的情况下转换为绝对时间概念提供一些指示原始日期时间应锚定到哪个时区。
计算机系统中使用的时间类型是什么?
naive datetime:通常用于显示,以本地时间(即在浏览器中)操作系统可以提供时区给程序的信息。
UTC 时间戳:如上所述,UTC 时间戳是绝对时间点,但它锚定在给定时区,因此 UTC 时间戳可以转换为 中的日期时间任何时区,但它不包含时区信息。这意味着什么?这意味着 1504119325 对应于
2017-08-30T18:55:24Z
、2017-08-30T17:55:24-0100
或2017-08 -30T10:55:24-0800
。它不会告诉您记录的日期时间来自哪里。它通常在服务器端用于记录事件(日志等)或用于将时区感知日期时间转换为绝对点时间并计算时间差。ISO-8601 日期时间 字符串:ISO-8601 是记录带时区的日期时间的标准化格式。 (实际上有多种格式,请在此处阅读:https://en.wikipedia.org/wiki/ISO_8601< /a>) 它用于在系统之间以可序列化的方式传递时区感知的日期时间信息。
什么时候使用哪个?或者更确切地说,您什么时候需要关心时区?
如果您需要以任何方式关心一天中的时间,您需要时区信息。日历或闹钟需要一天中的时间来为世界上的任何用户设置一天中正确的时间举行会议。如果此数据保存在服务器上,则服务器需要知道日期时间对应的时区。
要计算来自世界不同地方的事件之间的时间差异,UTC 时间戳就足够了,但是您无法分析事件发生的时间(即,对于网络分析,您可能想知道用户何时发生) 以当地时间访问您的网站:如果没有一天中的时间信息,您是否会在早上或晚上看到更多用户?
日期字符串中的时区偏移:
另一点是。重要的是,日期字符串中的时区偏移不固定,这意味着因为
2017-08-30T10:55:24-0800
表示偏移量。 -0800
或 8 小时前,并不意味着它永远都是!在夏天,它很可能处于夏令时,并且它会是
-0700
这意味着时区偏移(+0100)与不同>时区名称(欧洲/法国)甚至时区指定(CET)
美洲/Los_Angeles
时区是世界上的一个地方< /em>,但在冬季会变成PST
(太平洋标准时间)时区偏移表示法,在夏季会变成PDT
(太平洋夏令时)。因此,除了获取日期字符串的时区偏移量之外,您还应该获取准确的时区名称。
大多数软件包都能够自行将夏令时的数字偏移量转换为标准时间,但这对于仅偏移量来说并不一定是微不足道的。例如,西非的
WAT
时区指定为 UTC+0100,就像法国的CET
时区一样,但法国遵守夏令时,而西非则不遵守(因为他们'靠近赤道)所以,简而言之,这很复杂。非常复杂,这就是为什么你不应该自己做这件事,而是相信一个可以为你做这件事的软件包,并保持最新!
I feel like the main answer is still not so clear, and it's worth taking the time to understand time and timezones.
The most important thing to understand when dealing with time is that time is relative!
2017-08-30 13:23:00
: (a naive datetime), represents a local time somewhere in the world, but note that2017-08-30 13:23:00
in London is NOT THE SAME TIME as2017-08-30 13:23:00
in San Francisco.Because the same time string can be interpreted as different points-in-time depending on where you are in the world, there is a need for an absolute notion of time.
A UTC timestamp is a number in seconds (or milliseconds) from Epoch (defined as
1 January 1970 00:00:00
atGMT
timezone +00:00 offset).Epoch is anchored on the GMT timezone and therefore is an absolute point in time. A UTC timestamp being an offset from an absolute time therefore defines an absolute point in time.
This makes it possible to order events in time.
Without timezone information, time is relative, and cannot be converted to an absolute notion of time without providing some indication of what timezone the naive datetime should be anchored to.
What are the types of time used in computer system?
naive datetime: usually for display, in local time (i.e. in the browser) where the OS can provide timezone information to the program.
UTC timestamps: A UTC timestamp is an absolute point in time, as mentioned above, but it is anchored in a given timezone, so a UTC timestamp can be converted to a datetime in any timezone, however it does not contain timezone information. What does that mean? That means that 1504119325 corresponds to
2017-08-30T18:55:24Z
, or2017-08-30T17:55:24-0100
or also2017-08-30T10:55:24-0800
. It doesn't tell you where the datetime recorded is from. It's usually used on the server side to record events (logs, etc...) or used to convert a timezone aware datetime to an absolute point in time and compute time differences.ISO-8601 datetime string: The ISO-8601 is a standardized format to record datetime with timezone. (It's in fact several formats, read on here: https://en.wikipedia.org/wiki/ISO_8601) It is used to communicate timezone aware datetime information in a serializable manner between systems.
When to use which? or rather when do you need to care about timezones?
If you need in any way to care about time-of-day, you need timezone information. A calendar or alarm needs time-of-day to set a meeting at the correct time of the day for any user in the world. If this data is saved on a server, the server needs to know what timezone the datetime corresponds to.
To compute time differences between events coming from different places in the world, UTC timestamp is enough, but you lose the ability to analyze at what time of day events occured (ie. for web analytics, you may want to know when users come to your site in their local time: do you see more users in the morning or the evening? You can't figure that out without time of day information.
Timezone offset in a date string:
Another point that is important, is that timezone offset in a date string is not fixed. That means that because
2017-08-30T10:55:24-0800
says the offset-0800
or 8 hours back, doesn't mean that it will always be!In the summer it may well be in daylight saving time, and it would be
-0700
What that means is that timezone offset (+0100) is not the same as timezone name (Europe/France) or even timezone designation (CET)
America/Los_Angeles
timezone is a place in the world, but it turns intoPST
(Pacific Standard Time) timezone offset notation in the winter, andPDT
(Pacific Daylight Time) in the summer.So, on top of getting the timezone offset from the datestring, you should also get the timezone name to be accurate.
Most packages will be able to convert numeric offsets from daylight saving time to standard time on their own, but that is not necessarily trivial with just offset. For example
WAT
timezone designation in West Africa, is UTC+0100 just likeCET
timezone in France, but France observes daylight saving time, while West Africa does not (because they're close to the equator)So, in short, it's complicated. VERY complicated, and that's why you should not do this yourself, but trust a package that does it for you, and KEEP IT UP TO DATE!
使用utcfromtimestamp并指定时区确实存在问题。以下问题有一个很好的示例/解释:
转换为Unix时间时如何指定时区(UTC)? (Python)
There is indeed a problem with using utcfromtimestamp and specifying time zones. A nice example/explanation is available on the following question:
How to specify time zone (UTC) when converting to Unix time? (Python)
接受的答案似乎对我不起作用。我的解决方案:
The accepted answer seems not work for me. My solution:
最简单的方法:
编辑:@Daniel 是正确的,这会将其转换为机器的时区。这是修改后的答案:
事实上,甚至没有必要指定
timezone.utc
,因为只要datetime
具有相同的时区,时间差就相同(或没有时区)。Simplest way:
Edit: @Daniel is correct, this would convert it to the machine's timezone. Here is a revised answer:
In fact, its not even necessary to specify
timezone.utc
, because the time difference is the same so long as bothdatetime
have the same timezone (or no timezone).我认为表达你的问题的正确方法是
有没有办法通过指定UTC日期来获取时间戳?
,因为时间戳只是一个绝对的数字,而不是相对的。相对的(或时区感知的)部分是日期。我发现 pandas 对于时间戳非常方便,所以:
I think the correct way to phrase your question is
Is there a way to get the timestamp by specifying the date in UTC?
, because timestamp is just a number which is absolute, not relative. The relative (or timezone aware) piece is the date.I find pandas very convenient for timestamps, so:
使用 Python v3.9,我们现在还拥有
zoneinfo
模块,它解决了 Python 早期的许多时区问题。With Python v3.9 we now also have the
zoneinfo
module, which solves so many of Python's earlier timezone headaches.