私は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)
ができました。
時間が合いません。私はここで何が恋しいですか?
あなたがここで逃したのはタイムゾーンです。
おそらく、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でも同じように動作します。)
解決策は
import time
import datetime
d = datetime.date(2015,1,5)
unixtime = time.mktime(d.timetuple())
dt
からPOSIXタイムスタンプを作成するには、この式ではなく、
(dt - datetime(1970,1,1)).total_seconds()
これを使って:
int(dt.strftime("%s"))
2番目の方法を使用してあなたの例で正しい答えを得ます。
編集:いくつかのフォローアップ...いくつかのコメント(下記参照)の後、私はstrftime
の%s
に対するサポートまたはドキュメンテーションの欠如について興味がありました。これが私が見つけたものです:
Pythonのソースdatetime
とtime
では、文字列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の受け入れられた答えを見てください。
あなたが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
DatetimeオブジェクトがUTC時間を表している場合は、Tupleがローカルタイムゾーンにあると想定しているため、time.mktimeを使用しないでください。代わりに、calendar.timegmを使用してください。
>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60
UTCタイムゾーンを操作する場合:
time_stamp = calendar.timegm(dt.timetuple())
datetime.utcfromtimestamp(time_stamp)
さて、TO unixタイムスタンプを変換するとき、pythonは基本的にUTCを想定していますが、変換し直す間にあなたのローカルタイムゾーンに変換された日付を与えるでしょう。
この質問/回答を参照してください。 datetime.datetime.fromtimestamp()で使用されるタイムゾーンを取得する
あなたはタイムゾーン情報を見逃しています(すでに回答済み、同意済み)
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'
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