17

私の問題: UTC タイムタプルを UTC タイムスタンプに変換する必要があります。しかし、私にはいくつかの混乱があります。

最初のビット情報:

  • time.mktime(tuple): この関数は常にタイムスタンプを現地時間で返します。

    これは localtime() の逆関数です。その引数は、UTC ではなく現地時間で時刻を表す struct_time または完全な 9 タプルです。

  • calendar.timegm(tuple): これは、指定された時間タプルからUTC タイムスタンプを返します

    time モジュールの gmtime() 関数によって返されるような時間タプルを取り、対応する Unix タイムスタンプ値を返します。実際、time.gmtime() と timegm() は互いに逆です

それでは、テストを行いましょう。

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

なぜ4つの異なる値があるのですか? そして、UTC タイムタプルを UTC タイムスタンプに変換したい場合、どちらが正しいですか?

アップデート


私の混乱に対する答えを見つけたと思うので、説明させてください。

まず、重要なことを知る必要があります。

日時オブジェクトには、「naive」と「aware」の 2 種類があります。

認識オブジェクトは、タイムゾーンや夏時間情報など、適用可能なアルゴリズムおよび政治的な時間調整について十分な知識を持ち、他の認識オブジェクトとの相対的な位置を特定します。認識オブジェクトは、解釈できない特定の瞬間を表すために使用されます [1]。

単純なオブジェクトには、他の日付/時刻オブジェクトとの相対位置を明確に特定するための十分な情報が含まれていません。単純なオブジェクトが協定世界時 (UTC)、現地時間、または他のタイムゾーンの時間を表すかどうかは、純粋にプログラム次第であり、特定の数値がメートル、マイル、または質量を表すかどうかはプログラム次第です。単純なオブジェクトは、現実のいくつかの側面を無視するという犠牲を払って、理解しやすく、操作しやすいです。

「ナイーブ」オブジェクトから得られるもの、datetime.utcnow() またはdatetime.now()「ナイーブ」オブジェクトです。これは、datetime返されるオブジェクトがローカル時間または UTC 時間について何も述べていないことを意味します。これは単に「ある時間」を表すだけです。日付と時刻の情報 (年、月、日、時、分、秒など) をカプセル化するだけです。それをローカルまたは UTC の概念に関連付けるのは、あなたの責任です。

したがって、単純な datetime オブジェクトは単に「ある時間」を表すことに注意してください。このdatetime.now()関数は、現在の時刻に等しい「ある時刻」を返します。この関数は、datetime.utcnow()イギリスのグリニッジの現在時刻 (UTC と同じ) である「ある時刻」を返します。

「いつか」は、日付と時刻の単なる値です。そして、地球上の異なる場所では、「ある時」が異なる時間に発生することに注意してください。たとえば、「ある時間」の値が 1 月 1 日 10:30 の場合、ニューヨークの現在時刻になる約 5 時間前のグリニッジ イングランドの現在時刻になります。

したがって、一般的な「ある時間」の値と、その「ある時間」が異なる「時間」の異なる場所の現在の時間になるという概念の 2 つがあることがわかります。(ここではしゃれはありません、読んでください)

それでは、まず「エポック」とは何かを定義しましょう。「ある時間」は単なる時間の一般的な値であることはわかっています。次に、エポックは、イギリスのグリニッジで発生した「ある時間」であり、パラメーターの値は次のとおりJanuary 1 1970, 00:00:00です。

「タイムスタンプ」はありません。エポックから経過した秒数。これは、タイムスタンプがイギリスのグリニッジ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

したがって、場所を変更すると、同じ「ある時間」の値Jan 1, 1970, 00:00:00が異なるタイムスタンプを持つことがわかります。したがって、タイムスタンプについて話すときは、タイムスタンプが関連する「場所」と、その場所がイギリスのグリニッジとどの程度東または西に関連しているかについても言及する必要があります。その場所は「タイムゾーン」として表されます。

これで、すべてのシステム (コンピューター) にタイムゾーンが構成され、そのタイムゾーンに関連するすべてのタイムスタンプが事実上「ローカル」になります。UTC はグローバル参照です。

したがって、次のようXに変換される「しばらく」の値があるとします。

  • Y現地時間のタイムスタンプ
  • Zタイムスタンプ (UTC)

これは、Yいいえということを意味します。あなたの場所の現在の時刻になるには、秒数が経過する必要があり、Zイギリスのグリニッジの現在の時刻が「ある時間」になるには、何秒も経過する必要はありません。

mktimeさて、最後に、関数andに戻りましょうtimegm。これらは、「しばらく」の別の表現であるタイムタプルをとります。ローカルまたは UTC の概念を持たない単純な時刻を渡していることを思い出してください。

X素朴な「いつか」を表すタイムタプルだとしましょう。それで

  • mktime(X)いいえを返します。現在のローカル時間がその「ある時間」になるまでに経過する必要がある秒数、および
  • timegm(X)グリニッジ イングランドの現在の時刻をその「ある時間」に等しくするために費やさなければならない秒数を返します。

上記の例では、nowutc_nowは単純な「いつか」を表しており、これらの「いつか」の値をmktimeandtimegmに入力すると、単純に no が返されます。対応する場所 (あなたの場所とイギリスのグリニッジ) の現在時刻がその「ある時間」になるまでに経過しなければならない秒数。


最後に、私の問題に戻ります: UTC タイムタプルを UTC タイムスタンプに変換する必要があります。

まず、「UTC タイムタプル」という概念はありません。これは単なる「ある時間」です。UTC に変換する必要がある場合は、次のようにしますtimegm

cal.timegm(datetime.timetuple(utc_now))

これにより、現在の UTC 時間 (つまり、イギリスのグリニッジでの現在の「ある時間」) のタイムスタンプが得られます。

4

1 に答える 1

6

事実上、 3つの異なる値しかありません。これらの2つの値:

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

わずか7秒の違いがあります。これは、変数をダンプしたときに最初に見たものです。

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

(出力の秒部分の22対29に注意してください。)

他の2つの値は、間違った種類の引数を適用しているため、単純に誤りです。ローカル値ではなくUTC値で呼び出しtime.mktimeており、UTC値ではなくローカル値で呼び出しcal.timegm ています。ドキュメントには、何が期待されるかが明確に記載されています。したがって、適切な値のみを使用するようにしてください。基本的に、現地時間のオフセット(4時間、見た目では)が適用されるべきではないときに適用されているのがわかります(エラーの場所に応じて異なる方向に)。

このようなことを診断するときは、現在のUnixタイムスタンプを提供するepochconverter.comを使用すると便利です。これにより、出力と比較できます。

于 2013-03-16T09:32:27.657 に答える