問題描述
有沒有辦法通過指定日期來獲取 UTC 時間戳?我的期望:
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)
應該會導致
1199145600
創建一個簡單的日期時間對象意味著沒有時區信息.如果我查看 datetime.utcfromtimestamp 的文檔,創建 UTC 時間戳意味著忽略時區信息.所以我猜想,創建一個天真的日期時間對象(就像我所做的那樣)會導致一個 UTC 時間戳.然而:
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')))
結果
2007-12-31 23:00:00
datetime 對象中是否還有隱藏的時區信息?我做錯了什么?
Is there still any hidden time zone information in the datetime object? What am I doing wrong?
推薦答案
樸素 datetime
與有意識 datetime
Na?ve datetime
versus aware datetime
默認的 datetime
對象被稱為na?ve":它們保留時間信息而沒有時區信息.將樸素的 datetime
視為一個沒有明確來源的相對數字(即:+4
)(實際上,您的來源在整個系統邊界中都很常見).
Default datetime
objects are said to be "na?ve": they keep time information without the time zone information. Think about na?ve datetime
as a relative number (ie: +4
) without a clear origin (in fact your origin will be common throughout your system boundary).
相比之下,將感知 datetime
視為具有全球共同起源的絕對數字(即:8
).
In contrast, think about aware datetime
as absolute numbers (ie: 8
) with a common origin for the whole world.
沒有時區信息,您無法將樸素"日期時間轉換為任何非樸素時間表示(如果我們不知道從哪里到哪里,+4
目標在哪里開始 ?).這就是為什么你不能有 datetime.datetime.toutctimestamp()
方法的原因.(參見:http://bugs.python.org/issue1457227)
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 a datetime.datetime.toutctimestamp()
method. (cf: http://bugs.python.org/issue1457227)
要檢查您的 datetime
dt
是否幼稚,請檢查 dt.tzinfo
,如果 None
,那么它是天真:
To check if your datetime
dt
is na?ve, check dt.tzinfo
, if None
, then it's na?ve:
datetime.now() ## DANGER: returns na?ve datetime pointing on local time
datetime(1970, 1, 1) ## returns na?ve datetime pointing on user given time
我的約會時間很幼稚,我該怎么辦?
您必須根據您的特定上下文做出假設:您必須問自己的問題是:您的 datetime
是 UTC 嗎?還是當地時間?
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 ?
如果您使用的是 UTC(您就沒有麻煩了):
import calendar
def dt2ts(dt):
"""Converts a datetime object to UTC timestamp
naive datetime will be considered UTC.
"""
return calendar.timegm(dt.utctimetuple())
如果您沒有使用 UTC,歡迎來到地獄.
在使用前者之前,您必須使您的 datetime
不幼稚功能,通過將它們歸還給它們預期的時區.
You have to make your datetime
non-na?ve prior to using the former
function, by giving them back their intended timezone.
您需要時區名稱和關于時區的信息如果 DST 在生成目標樸素日期時間時生效(角盒需要有關 DST 的最后信息):
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):
import pytz ## pip install pytz
mytz = pytz.timezone('Europe/Amsterdam') ## Set your timezone
dt = mytz.normalize(mytz.localize(dt, is_dst=True)) ## Set is_dst accordingly
不提供is_dst
的后果:
Consequences of not providing is_dst
:
不使用 is_dst
將生成不正確的時間(和 UTC 時間戳)如果在設置后向 DST 時生成了目標日期時間(例如通過刪除一小時來更改 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).
提供不正確的is_dst
當然會產生不正確的時間(和 UTC 時間戳)僅在 DST 重疊或孔上.什么時候提供時間也不正確,發生在洞"中(由于時間不存在向前移動 DST),is_dst
將給出解釋如何考慮這個虛假時間,這是唯一的情況.normalize(..)
實際上會在這里做一些事情,因為它會將其翻譯為實際有效時間(更改日期時間和DST 對象(如果需要).注意 .normalize()
不是必需的最后有一個正確的 UTC 時間戳,但可能是如果你不喜歡在你的時間里有虛假時間的想法,推薦變量,特別是如果您在其他地方重復使用此變量.
Providing incorrect is_dst
will of course generate incorrect
time (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 of
how to consider this bogus time, and this is the only case where
.normalize(..)
will actually do something here, as it'll then
translate it as an actual valid time (changing the datetime AND the
DST object if required). Note that .normalize()
is not required
for 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.
和避免使用以下內容:(參見:使用 pytz 進行日期時間時區轉換)
dt = dt.replace(tzinfo=timezone('Europe/Amsterdam')) ## BAD !!
為什么?因為 .replace()
盲目地替換了 tzinfo
而沒有考慮到目標時間,會選擇一個壞的 DST 對象.而 .localize()
使用目標時間和您的 is_dst
提示選擇正確的 DST 對象.
Why? because .replace()
replaces blindly the tzinfo
without
taking into account the target time and will choose a bad DST object.
Whereas .localize()
uses the target time and your is_dst
hint
to select the right DST object.
舊的錯誤答案(感謝@J.F.Sebastien 提出這個問題):
OLD incorrect answer (thanks @J.F.Sebastien for bringing this up):
希望,當您創建天真的 datetime
對象時,很容易猜測時區(您的本地來源),因為它與您希望不會在天真的日期時間之間更改的系統配置有關對象創建和您想要獲取 UTC 時間戳的時刻.這個技巧可以用來給出一個不完美的問題.
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.
通過使用time.mktime
,我們可以創建一個utc_mktime
:
By using time.mktime
we can create an utc_mktime
:
def utc_mktime(utc_tuple):
"""Returns number of seconds elapsed since epoch
Note that no timezone are taken into consideration.
utc tuple must be: (year, month, day, hour, minute, second)
"""
if len(utc_tuple) == 6:
utc_tuple += (0, 0, 0)
return time.mktime(utc_tuple) - time.mktime((1970, 1, 1, 0, 0, 0, 0, 0, 0))
def datetime_to_timestamp(dt):
"""Converts a datetime object to UTC timestamp"""
return int(utc_mktime(dt.timetuple()))
您必須確保您的 datetime
對象與創建您的 datetime
對象的時區在同一時區.
You must make sure that your datetime
object is created on the same timezone than the one that has created your datetime
.
最后一個解決方案是不正確的,因為它假設從現在開始的 UTC 偏移量與從 EPOCH 開始的 UTC 偏移量相同. 對于很多時區來說,情況并非如此(在特定時刻夏令時 (DST) 偏移量的年度最佳值).
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).
這篇關于使用 datetime 在 python 中獲取 UTC 時間戳的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!