1. ホーム
  2. python

[解決済み] Pythonでdatetimeを使ってUTCタイムスタンプを取得する

2023-01-31 14:34:27

質問

日付を指定してUTCタイムスタンプを取得する方法はありますか?私が期待するもの。

datetime(2008, 1, 1, 0, 0, 0, 0)

は、結果として

 1199145600

ナイーブなdatetimeオブジェクトを作成するということは、タイムゾーンの情報がないということです。datetime.utcfromtimestampのドキュメントを見ると、UTCタイムスタンプの作成は、タイムゾーン情報を省くことを意味します。ですから、(私が行ったように)素朴なdatetimeオブジェクトを作成すると、UTCタイムスタンプになるのでしょう。しかし

then = datetime(2008, 1, 1, 0, 0, 0, 0)
datetime.utcfromtimestamp(float(then.strftime('%s')))

の結果は

2007-12-31 23:00:00

datetimeオブジェクトには、まだ隠されたタイムゾーン情報があるのでしょうか?私は何を間違えているのでしょうか?

どのように解決するのですか?

ナイーブ datetime vs 意識高い系 datetime

デフォルト datetime オブジェクトはquot;naïve"と呼ばれます。つまり、タイムゾーン情報なしで時刻情報を保持します。ナイーブについて考えてみましょう。 datetime を相対的な数として考えてみてください(つまり +4 のように)、明確な原点がない相対的な数値として扱われます(実際には、原点はシステム境界全体で共通となります)。

これに対して datetime は絶対数として(つまり 8 を全世界共通の起源を持つ絶対数として扱います。

タイムゾーンの情報がない場合 はできません。 は、quot;naive" datetimeをnaiveでない時間表現に変換することができます(quot;naive" はどこにあるのでしょうか? +4 はどこから始めればいいのかわからない場合、どこにターゲットを置くのでしょうか?) このため datetime.datetime.toutctimestamp() というメソッドが必要なのです。(cf: http://bugs.python.org/issue1457227 )

を確認するために datetime dt がナイーブであるかどうかを確認するには dt.tzinfo もし None であれば、ナイーブです。

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 か、それとも現地時間か?

  • 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 を非ナイーブにする必要があります。 関数を使う前に、意図したタイムゾーンを返すことで、をナイーブにしないようにする必要があります。

    必要なものは タイムゾーンの名前 に関する情報 サマータイムが適用されている場合 を生成する際に、夏時間が有効であるかどうかの情報 (コーナーケースの場合は最後の夏時間に関する情報が必要です) を提供します。 DSTに関する最後の情報は、コーナーケースのために必要です)。

    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 :

    使用しない is_dst を使用すると、不正確な時刻(およびUTCタイムスタンプ)が生成されます。 ターゲットとなる日付が夏時間が適用されている間に生成された場合、不正確な時刻(およびUTCタイムスタンプ)が生成されます。 (例えば、1 時間削除することによって DST 時間を変更する) 場合、ターゲットデータタイムは不正確な時間 (および UTC タイムスタンプ) を生成します。

    不正確な is_dst を指定すると、もちろん を指定すると、サマータイムが重なるか重ならないかのどちらかのみ、誤った時刻(およびUTCタイムスタンプ)を生成します。また を提供する場合 を提供する場合にも、不正確な時刻が発生し、quot;holes" (夏時間の前倒しにより存在しなかった時刻) で発生します。 で発生します。) is_dst の解釈が与えられます。 はこの不正な時間をどのように考慮するかの解釈を与えます。 .normalize(..) はここで実際に何かをします。 はそれを実際の有効な時間として変換します (必要なら datetime と オブジェクトを変更します)。注意点として .normalize() は必須ではありません。 は正しい UTC タイムスタンプを最後に持つためには必要ありませんが、おそらく が推奨されるでしょう。 特に、この変数を他の場所で再利用する場合は。

    の使用は避けてください。 : (cf: pytzを使ったDatetimeのタイムゾーンの変換 )

    dt = dt.replace(tzinfo=timezone('Europe/Amsterdam'))  ## BAD !!
    
    

    なぜかというと .replace() をやみくもに置き換えてしまうからです。 tzinfo を置き換えます。 はターゲット時刻を考慮せずに盲目的にを置き換えるので、悪いDSTオブジェクトが選ばれてしまいます。 一方 .localize() はターゲット時刻を使用し is_dst ヒント を使用して、正しい DST オブジェクトを選択します。

OLD不正解 (@J.F.Sebastienさんに感謝します):

うまくいけば、あなたのナイーブを作成するときに、タイムゾーン(あなたのローカル起源)を推測するのは非常に簡単です。 datetime オブジェクトを作成したときに、タイムゾーン (あなたのローカルな起源) を推測するのは非常に簡単です。これは、単純な datetime オブジェクトの作成と UTC タイムスタンプを取得する瞬間の間に変更しないことを望むシステム構成に関連しているからです。このトリックは 不完全な という質問をすることができます。

を使うことで time.mktime を使うことで 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 .

この最後の解決策は、現在からの UTC オフセットが EPOCH からの UTC オフセットと同じであるという仮定を行うため、正しくありません。 これは、多くのタイムゾーン (夏時間 (DST) オフセットのための 1 年の特定の瞬間) の場合ではありません。