web-dev-qa-db-ja.com

DatetimeをUnixタイムスタンプに変換し、それをpythonに変換し直す

私はdt = datetime(2013,9,1,11)を持っています、そして私はこのdatetimeオブジェクトのUnixタイムスタンプを得たいです。

dt - datetime(1970,1,1)).total_seconds()を実行すると、タイムスタンプ1378033200を取得しました。

datetime.fromtimestampを使って変換し直すとdatetime.datetime(2013, 9, 1, 6, 0)ができました。

時間が合いません。私はここで何が恋しいですか?

145
bridgewater

あなたがここで逃したのはタイムゾーンです。

おそらく、UTCから5時間離れているので、2013-09-01T11:00:00ローカルと2013-09-01T06:00:00Zは同じ時間です。

datetime docsの先頭を読む必要があります。これは、タイムゾーンと「ナイーブ」および「アウェア」オブジェクトについて説明しています。

元のナイーブな日時がUTCの場合、それを回復する方法はutcfromtimestampの代わりに fromtimestamp を使用することです。

一方、元のナイーブな日時がローカルである場合は、最初にUTCタイムスタンプを差し引くべきではありません。代わりにdatetime.fromtimestamp(0)を使用してください。

あるいは、もしあなたが気付いているdatetimeオブジェクトを持っていたら、両側でローカルな(気付いている)Epochを使うか、あるいは明示的にUTCとの間で変換する必要があります。

Python 3.3以降を持っている、あるいはそれにアップグレードできるのであれば、自分でやろうとする代わりに timestamp メソッドを使うだけでこれらの問題をすべて回避することができます。そうでなくても、 そのソースコードを借りることを考えたいかもしれません

(そして、Python 3.4を待つことができれば、 PEP 341 は最終リリースになるでしょう。これは、JF Sebastianと私がコメントで話していたすべてのことが、 stdlibで、UnixでもWindowsでも同じように動作します。)

83
abarnert

解決策は

import time
import datetime
d = datetime.date(2015,1,5)

unixtime = time.mktime(d.timetuple())
112
DmitrySemenov

dtからPOSIXタイムスタンプを作成するには、この式ではなく、

(dt - datetime(1970,1,1)).total_seconds()

これを使って:

int(dt.strftime("%s"))

2番目の方法を使用してあなたの例で正しい答えを得ます。

編集:いくつかのフォローアップ...いくつかのコメント(下記参照)の後、私はstrftime%sに対するサポートまたはドキュメンテーションの欠如について興味がありました。これが私が見つけたものです:

Pythonのソースdatetimetimeでは、文字列STRFTIME_FORMAT_CODESは次のように教えてくれます。

"Other codes may be available on your platform.
 See documentation for the C library strftime function."

man strftime(Mac OS XなどのBSDシステムの場合)なら、%sのサポートが見つかります。

"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."

とにかく、それが%sが動作するシステム上で動作する理由です。しかし、OPの問題に対するより良い解決策があります(それはタイムゾーンを考慮に入れています)。ここで@ abarnertの受け入れられた答えを見てください。

49
Darren Stone

あなたがPythonのdatetimeをEpochからの秒数に変換したいのなら、あなたはそれを明示的にするべきです:

>>> import datetime
>>> datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'
>>> (datetime.datetime(2012,04,01,0,0) - datetime.datetime(1970,1,1)).total_seconds()
1333238400.0

Python 3.3以降では、代わりに timestamp() を使用できます。

>>> import datetime
>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0
38
Francisco Costa

DatetimeオブジェクトがUTC時間を表している場合は、Tupleがローカルタイムゾーンにあると想定しているため、time.mktimeを使用しないでください。代わりに、calendar.timegmを使用してください。

>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60
3
Matt Kramer

UTCタイムゾーンを操作する場合:

time_stamp = calendar.timegm(dt.timetuple())

datetime.utcfromtimestamp(time_stamp)
3
Dede

さて、TO unixタイムスタンプを変換するとき、pythonは基本的にUTCを想定していますが、変換し直す間にあなたのローカルタイムゾーンに変換された日付を与えるでしょう。

この質問/回答を参照してください。 datetime.datetime.fromtimestamp()で使用されるタイムゾーンを取得する

2
Ronald Portier

あなたはタイムゾーン情報を見逃しています(すでに回答済み、同意済み)

arrow package を使用すると、dateTimeによるこの拷問を回避できます。それはすでに書かれ、テストされ、pypi発行され、クロスpython(2.6 - 3.xx)です。

pip install arrow(または依存関係に追加)

あなたの場合の解決策

dt = datetime(2013,9,1,11)
arrow.get(dt).timestamp
# >>> 1378033200

bc = arrow.get(1378033200).datetime
print(bc)
# >>> datetime.datetime(2013, 9, 1, 11, 0, tzinfo=tzutc())
print(bc.isoformat())
# >>> '2013-09-01T11:00:00+00:00'
2
maxkoryukov
def datetime_to_Epoch(d1):

    # create 1,1,1970 in same timezone as d1
    d2 = datetime(1970, 1, 1, tzinfo=d1.tzinfo)
    time_delta = d1 - d2
    ts = int(time_delta.total_seconds())
    return ts


def Epoch_to_datetime_string(ts, tz_name="UTC"):
    x_timezone = timezone(tz_name)
    d1 = datetime.fromtimestamp(ts, x_timezone)
    x = d1.strftime("%d %B %Y %H:%M:%S")
    return x
0
rjha94