日時をUnixタイムスタンプに変換し、それをpythonに戻す


186

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

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

それを使用して変換し直すとき、datetime.fromtimestamp私は得ましたdatetime.datetime(2013, 9, 1, 6, 0)

時間は一致しません。ここで何を逃したのですか?



1
余談ですが、Python 3.3以降を使用しているtimestamp場合は、自分で実行するのではなく、実際にこのメソッドを使用したいと考えています。1つには、異なるタイムゾーンからナイーブ時間を差し引く可能性を完全に回避します。
abarnert 2013年

1
どこdtから来たの?それは現地時間ですか、それともUTCの時間ですか?
jfs 2013年

2
@abarnertすべてのコードページとユニコードシンボルを削除するリクエスト、つまり、ASCII以外のコードとデフォルト以外のコードページをすべて非合法にするリクエストも送信したいと思います。シンボルのペイントは引き続き許可されます。
Daniel F 14

6
@DanielF:リクエストが拒否されました。私はここで1つの世界の言語を作成することに興味はありません。たとえ私たちが作成したとしても、歴史的な言語学者やトールキンの学者に人生を不可能にしたくはありません。Unicodeはすでに問題を解決していますが、特定の組織と製品(TRONコンソーシアム、Shift-JIS over UTF-8を使用する日本語ソフトウェア、Microsoftはユーザーテキストファイルのデフォルトがcp1252であるOS、およびそのUTFを装うさまざまなSDKを提供しています) -16は固定幅の文字セットであるか、Unicodeと同じです(またはその両方)。
abarnert 2014

回答:


105

ここで見逃したのはタイムゾーンです。

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

datetimeタイムゾーンと「単純」および「認識」オブジェクトについて説明しているドキュメントの先頭を読む必要があります。

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

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

または、認識している日時オブジェクトがある場合は、両側でローカル(認識)エポックを使用するか、明示的にUTCとの間で変換する必要があります。

Python 3.3以降を使用している場合、またはPython 3.3以降にアップグレードできる場合は、timestamp自分で方法を理解するのではなく、メソッドを使用するだけでこれらの問題をすべて回避できます。そうでない場合でも、ソースコードを借用することを検討してください。

(そして、Python 3.4を待つことができる場合、PEP 341が最終リリースになる可能性が高いようです。つまり、JFセバスチャンと私がコメントで話していたすべてのことは、stdlibだけで実行できるはずです。 UnixとWindowsの両方で同じように動作します。)


1
dtがローカルのタイムゾーンにある場合、質問の式は正しくありませんdatetime.fromtimestamp(0)(現在のタイムゾーンのエポック)をdatetime(1970, 1,1)(UTCのUNIXエポック)の代わりに使用する必要があります。
jfs 2013年

@JFSebastian:3つの可能性のすべてを詳細にカバーしたくありませんでしたが、あなたが正しいと思います。
abarnert 2013年

ちなみに、fromtimestamp(0)Windowsなど、システムがタイムゾーンの履歴情報を保存していない場合、失敗することがあります。pytzこの場合に使用できます。
jfs 2013年

@JFSebastian:しかし、pytz自分がどのタイムゾーンにいるかをすでに知っているのでなければ、役に立ちません。プログラムでこれを行うには、現在のWindowsタイムゾーンを取得してタイムゾーンに変換pytzしたり、名前で検索したりする別のライブラリが必要です。
abarnert 2013年

そこにあるtzlocalまた、Windows上で動作するモジュールが。utc時間を現地時間に変換する方法は次のとおりです。
jfs 2013年

141

解決策は

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

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

12
これは、dローカル時間を表す単純な日付/日付時刻オブジェクトであると想定します(あいまいな時間、またはOSが履歴tz dbを提供しない場合、過去/未来の日付で失敗する可能性があります(UTCオフセットはローカルで過去に異なっていた可能性があります)タイムゾーン))。その他のオプション
jfs

6
誰もが浮動小数点ソリューションを気にしていないように見えます。それは誰にとっても明白ですか?
Ivan Balashov 2016年

4
これはマイクロ秒を落とします。興味深いかもしれません。
Alfe

唯一の問題は、タイムゾーンが考慮されていないことです。
Blairg23 2017年

すべきではない。TZを調整する必要がある場合は、最初に調整する必要があります。
Marcin Orlowski、2018年

69

Pythonの日時をエポックからの秒数に変換する場合は、明示的に行う必要があります。

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

5
タイムゾーンは考慮されません。
Blairg23 2017年

3
%s現在使用しているシステムのクロックにローカライズされるため、は使用しないでください。.timestamp()正しいEpoch / UNIXの時刻を取得するためにのみ使用してください。
Blairg23 2017

3
%sWindowsシステムでは機能しません(ValueError: Invalid format string
chrki

1
@ amitnair92ちょうど置く89
フランシスココスタ

54

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

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

これを使って:

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

2番目の方法を使用した例では、正しい答えが得られます。

編集:いくつかのフォローアップ...いくつかのコメント(下記を参照)の後、私はのサポートやドキュメントが不足していることに興味を持っていまし%sstrftime。これが私が見つけたものです:

およびのPythonソースでは、文字列から次のことがわかります。datetimetimeSTRFTIME_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の受け入れられた回答を参照してください。


4
これは文書化されていない動作です(私は信じています)。たとえば、Windowsでは「無効なフォーマット文字列」になります。
クレセントフレッシュ

@CrescentFresh、面白い。君の言う通りかもね。strftime("%s")ドキュメントには記載されていませんが、MacとLinuxで動作することを確認しました。ありがとう。
ダレンストーン

1
どうやら、それはtzinfoフィールドを無視します。
ダニエルF 14

1
@DarrenStone:ソースを読む必要はありません。time.strftime()datetime.strftimeドキュメントの両方が、strftime(3)サポートされていないディレクティブに対して機能するプラットフォームに委任します。%sMac OS Xでも失敗する可能性があります。たとえば、datetime.strftime( '%s')はtzinfoを尊重する必要があります。
jfs

1
あなたは使用しないでください%s、あなただけあなたがしているシステムのローカライズされたシステム時刻を使用しますと。.timestamp()実際のUNIXタイムスタンプを取得しようとしている場合に使用します。
Blairg23 2017

6

UTCタイムゾーンを使用する場合:

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

datetime.utcfromtimestamp(time_stamp)

1時間検索した後、これが機能した唯一の回答でした:))
Qurashi

4

タイムゾーン情報を見逃しました(回答済み、同意済み)

arrowパッケージでは、日時によるこの拷問を回避できます。それはすでに書かれ、テストされ、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'

3

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

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


1
def dt2ts(dt, utc=False):
    if utc:
        return calendar.timegm(dt.timetuple())
    if dt.tzinfo is None:
        return int(time.mktime(dt.timetuple()))
    utc_dt = dt.astimezone(tz.tzutc()).timetuple()
    return calendar.timegm(utc_dt)

あなたはUTCタイムスタンプをしたい場合:time.mktimeだけのために地元の DT .USEはcalendar.timegm安全ですが、dtは、UTCゾーンはUTCそうにゾーンを変更する必要があります。UTCのdtの場合は、単にを使用しますcalendar.timegm


1
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

このクラスはニーズをカバーします。変数をConvertUnixToDatetimeに渡し、どの関数に基づいて動作させたいかを呼び出すことができます。

from datetime import datetime
import time

class ConvertUnixToDatetime:
    def __init__(self, date):
        self.date = date

    # Convert unix to date object
    def convert_unix(self):
        unix = self.date

        # Check if unix is a string or int & proceeds with correct conversion
        if type(unix).__name__ == 'str':
            unix = int(unix[0:10])
        else:
            unix = int(str(unix)[0:10])

        date = datetime.utcfromtimestamp(unix).strftime('%Y-%m-%d %H:%M:%S')

        return date

    # Convert date to unix object
    def convert_date(self):
        date = self.date

        # Check if datetime object or raise ValueError
        if type(date).__name__ == 'datetime':
            unixtime = int(time.mktime(date.timetuple()))
        else:
            raise ValueError('You are trying to pass a None Datetime object')
        return type(unixtime).__name__, unixtime


if __name__ == '__main__':

    # Test Date
    date_test = ConvertUnixToDatetime(datetime.today())
    date_test = date_test.convert_date()
    print(date_test)

    # Test Unix
    unix_test = ConvertUnixToDatetime(date_test[1])
    print(unix_test.convert_unix())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.