日時を使用してPythonでUTCタイムスタンプを取得する


82

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

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

結果として

 1199145600

ナイーブな日時オブジェクトを作成するということは、タイムゾーン情報がないことを意味します。datetime.utcfromtimestampのドキュメントを見ると、UTCタイムスタンプを作成するということは、タイムゾーン情報を省略することを意味します。したがって、(私が行ったように)単純な日時オブジェクトを作成すると、UTCタイムスタンプが生成されると思います。しかしながら:

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

結果は

2007-12-31 23:00:00

datetimeオブジェクトに非表示のタイムゾーン情報がまだありますか?私は何が間違っているのですか?


問題はthen.strftime('%s')現地時間を想定しているが、タイムスタンプはそれdatetime(2008, 1, 1)がUTCであることを示していることです。
jfs 2014

回答:


90

ナイーブdatetime対認識datetime

デフォルトのdatetimeオブジェクトは「ナイーブ」と呼ばれ、タイムゾーン情報なしで時間情報を保持します。ナイーブdatetimeは、+4明確な起源のない相対的な数(つまり、:)と考えてください(実際、起源はシステムの境界全体で共通になります)。

対照的に、全世界に共通の起源を持つdatetime絶対数(つまり:)として認識していると考えて8ください。

タイムゾーン情報がないと、「ナイーブ」日時を非ナイーブ時間表現に変換できません+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が有効であった場合についての情報を対象ナイーブ日時を(DSTについての最後の情報がcornercasesのために必要とされる)を製造する際に:

    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と、後方DSTが設定されている間にターゲット日時が生成された場合(たとえば、1時間を削除してDST時間を変更した場合)、誤った時刻(およびUTCタイムスタンプ)が生成されます。

    is_dstもちろん、正しくない値を指定すると、DSTのオーバーラップまたはホールでのみ誤った時刻(およびUTCタイムスタンプ)が生成されます。また、「穴」(DSTの順方向シフトのために存在しなかった時間)で発生する誤った時間を提供すると、is_dstこの偽の時間をどのように考慮するかが解釈されます。これは、.normalize(..)実際にここで何かを行う唯一のケース です。次に、それを実際の有効時間として変換します(必要に応じて日時とDSTオブジェクトを変更します)。これ.normalize()は、最後に正しいUTCタイムスタンプを設定するために必須ではありませんが、変数に偽の時間を含めるという考えが嫌いな場合、特にこの変数を他の場所で再利用する場合は、おそらく推奨されます。

    そして次のように使用しないでください:(CF:pytzを用い日時タイムゾーン変換

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

    どうして?なぜなら、ターゲット時間を考慮せずに.replace()盲目的に置き換えtzinfoられ、不良なDSTオブジェクトを選択するからです。一方.localize()、ターゲット時間とis_dstヒントを使用して、適切なDSTオブジェクトを選択します。

古い間違った答え(これを提起してくれた@JFSebastienに感謝します):

うまくいけば、ナイーブ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)オフセットの特定の時期)。


4
ナイーブ日時オブジェクトは、常にUTCで時刻を表す必要があります。その他のタイムゾーンは、I / O(表示)にのみ使用する必要があります。Python3.3にはdatetime.timestamp()メソッドがあります。
jfs 2012年

2
time.mktime()現地時間にのみ使用する必要があります。calendar.timegm()UTCタイムタプルをPOSIXタイムスタンプに変換するために使用できます。または、日時メソッドのみを使用することをお勧めします。私の答えを
jfs 2012年

4
-1。コードでは、utc_offset(now)とutc_offset(epoch)がローカルタイムゾーンで同じであると想定しています。116のタイムゾーン(430の一般的なタイムゾーンから)ではそうではありません。
jfs 2014年

1
それでも-1:.replace()などの固定されていないutcオフセットがあるタイムゾーンでは使用しないでください'Europe/Amsterdam'pytzを使用した日時タイムゾーン変換を参照してください
jfs 2016

1
1-なぜ使用すべきでないのか理解しています.replace(tzinfo=get_localzone())か?2-すでにtimegm()戻りますint。でラップする必要はありませんint。また、.timetuple()数分の1秒をドロップします。
jfs 2016年

29

別の可能性は次のとおりです。

d = datetime.datetime.utcnow()
epoch = datetime.datetime(1970,1,1)
t = (d - epoch).total_seconds()

これは、「d」と「エポック」の両方がナイーブな日時であるため機能し、「-」演算子を有効にして、間隔を返します。total_seconds()間隔を秒に変換します。total_seconds()でもフロートを返すことに注意してくださいd.microsecond == 0


12
実はそうではありませんが、考え方は同じですが、これは理解しやすいです:)
Natim 2015年

3
タイムライブラリか何かに単一のメソッドがあると思うでしょう... sheesh
wordsforthewise

21

また、このブログエントリで説明されているcalendar.timegm()関数にも注意してください。

import calendar
calendar.timegm(utc_timetuple)

出力はvaabの解と一致する必要があります。


13

入力日時オブジェクトがUTCの場合:

>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> timestamp = (dt - datetime(1970, 1, 1)).total_seconds()
1199145600.0

注:floatを返します。つまり、マイクロ秒は1秒の端数として表されます。

入力日付オブジェクトがUTCの場合:

>>> from datetime import date
>>> utc_date = date(2008, 1, 1)
>>> timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * 24*60*60
1199145600

詳細については、Pythonでdatetime.dateをUTCタイムスタンプに変換するをご覧ください。


8

主な答えはまだはっきりしていないように感じます。時間をかけて時間タイムゾーンを理解する価値があります。

時間を扱うときに理解する最も重要なことは、時間は相対的であるということです!

  • 2017-08-30 13:23:00:(ナイーブな日時)は、世界のどこかで現地時間を表しますが2017-08-30 13:23:00、ロンドンではサンフランシスコと同じ時間でないことに注意してください2017-08-30 13:23:00

同じ時間文字列は、世界のどこにいるかによって異なる時点として解釈される可能性があるため、絶対的な時間の概念が必要です。

A UTCタイムスタンプは秒(またはミリ秒)の数値であるから(として定義エポック1 January 1970 00:00:00GMT:00タイムゾーンのオフセット+00)。

エポックはGMTタイムゾーンに固定されているため、絶対的な時点です。A UTCタイムスタンプされたオフセットの絶対時間からしたがって定義時間における絶対ポイント

これにより、イベントを時間内に注文することが可能になります。

タイムゾーン情報がないと、時間は相対的であり、ナイーブな日時をどのタイムゾーンに固定する必要があるかを示すことなく、時間の絶対的な概念に変換することはできません。

コンピュータシステムで使用される時間の種類は何ですか?

  • ナイーブ日時:通常、OSがプログラムにタイムゾーン情報を提供できる現地時間(つまりブラウザ)で表示します。

  • UTCタイムスタンプ:前述のように、UTCタイムスタンプは絶対的な時点ですが、特定のタイムゾーンに固定されているため、UTCタイムスタンプは任意のタイムゾーンの日時に変換できますがタイムゾーン情報は含まれていません。どういう意味ですか?手段1504119325それに相当するもの2017-08-30T18:55:24Z、または2017-08-30T17:55:24-0100、あるいはまた2017-08-30T10:55:24-0800。記録された日時がどこから来たのはわかりません。これは通常、サーバー側でイベント(ログなど)を記録するために使用されるか、タイムゾーン対応の日時絶対的な時点に変換して時差を計算するために使用されます

  • ISO-8601日時文字列:ISO-8601は、タイムゾーンで日時を記録するための標準化された形式です。(実際にはいくつかの形式です。ここで読んでください:https//en.wikipedia.org/wiki/ISO_8601)これは、システム間でシリアル化可能な方法でタイムゾーン対応の日時情報を通信するために使用されます。

いつどちらを使うの?というか、いつタイムゾーンを気にする必要がありますか?

  • 何らかの方法で時刻を気にする必要がある場合は、タイムゾーン情報が必要です。カレンダーまたはアラームは、世界中のすべてのユーザーの正しい時刻に会議を設定するために時刻を必要とします。このデータがサーバーに保存されている場合、サーバーは日時が対応するタイムゾーンを知る必要があります。

  • 世界のさまざまな場所から発生するイベント間の時差を計算するには、UTCタイムスタンプで十分ですが、イベントが発生した時刻を分析する機能が失われます(つまり、Web分析の場合、ユーザーがいつアクセスするかを知りたい場合があります。現地時間のサイト:朝または夕方に多くのユーザーが表示されますか?時刻情報なしではそれを理解することはできません。

日付文字列のタイムゾーンオフセット

重要なもう1つのポイントは、日付文字列のタイムゾーンオフセットが固定されていないことです。つまり2017-08-30T10:55:24-0800、オフセット-0800または8時間前と言っているので、常にそうなるとは限りません。

夏は夏時間になるかもしれませんが、 -0700

つまり、タイムゾーンオフセット(+0100)は、タイムゾーン名(ヨーロッパ/フランス)またはタイムゾーン指定(CET)と同じではありません。

America/Los_Angelesタイムゾーンは、世界での場所、それがに変わりPST、冬に(太平洋標準時)タイムゾーンオフセットの表記、そしてPDT夏には(太平洋夏時間)。

したがって、日付文字列からタイムゾーンオフセットを取得することに加えて、タイムゾーン名も正確にする必要があります。

ほとんどのパッケージは、夏時間から標準時間への数値オフセットを独自に変換できますが、オフセットだけでは必ずしも簡単ではありません。たとえばWAT、西アフリカのタイムゾーン指定はCET、フランスのタイムゾーンと同じようにUTC + 0100ですが、フランスは夏時間を採用していますが、西アフリカは夏時間を採用していません(赤道に近いため)。

つまり、それは複雑です。非常に複雑なので、自分でこれを行うべきではありませんが、それを行うパッケージを信頼し、最新の状態に保ってください。


さまざまなパッケージの落とし穴を理解するには、Pythonでの日付と時刻に関する私のブログ投稿を参照してください。medium.com
@ eleroy /

3

外部モジュールを使用しない簡単なソリューション:

from datetime import datetime, timezone

dt = datetime(2008, 1, 1, 0, 0, 0, 0)
int(dt.replace(tzinfo=timezone.utc).timestamp())


1

Is there a way to get the timestamp by specifying the date in UTC?タイムスタンプは相対的なものではなく絶対的な数値であるため、質問を表現する正しい方法 はです。相対的な(またはタイムゾーンを認識する)部分は日付です。

パンダはタイムスタンプに非常に便利だと思うので、次のようにします。

import pandas as pd
dt1 = datetime(2008, 1, 1, 0, 0, 0, 0)
ts1 = pd.Timestamp(dt1, tz='utc').timestamp()
# make sure you get back dt1
datetime.utcfromtimestamp(ts1)  

パンダを使用することは私見の正しいアプローチです。現在の時刻には、正しい時刻を直接取得するためのt = Timestamp.utcnow()もあります:)
ntg

0

受け入れられた答えは私にはうまくいかないようです。私の解決策:

import time
utc_0 = int(time.mktime(datetime(1970, 01, 01).timetuple()))
def datetime2ts(dt):
    """Converts a datetime object to UTC timestamp"""
    return int(time.mktime(dt.utctimetuple())) - utc_0

dtローカルタイムゾーンと1970年の現在の()UTCオフセットが異なる場合は失敗します。mktime()現地時間を期待しています。
jfs 2014年

0

最も簡単な方法:

>>> from datetime import datetime
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> dt.strftime("%s")
'1199163600'

編集:@Danielは正しいです、これはそれをマシンのタイムゾーンに変換します。修正された回答は次のとおりです。

>>> from datetime import datetime, timezone
>>> epoch = datetime(1970, 1, 1, 0, 0, 0, 0, timezone.utc)
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0, timezone.utc)
>>> int((dt-epoch).total_seconds())
'1199145600'

実際、timezone.utc両方datetimeが同じタイムゾーンを持っている(またはタイムゾーンがない)限り、時差は同じであるため、を指定する必要はありません。

>>> from datetime import datetime
>>> epoch = datetime(1970, 1, 1, 0, 0, 0, 0)
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> int((dt-epoch).total_seconds())
1199145600

このメソッドはUTCを返しませんが、日時を現在のタイムゾーンに調整します。すなわち。現在がtz + 3で午前12時の場合、エポックで午前9時を返します。
Daniel Dubovski 2018年

ああ、その通りです。私のタイムゾーンはUTCでした-それがそれが機能した理由です。
Mike Furlender 2018年

(Python 3.2以降の)timezone.utcオブジェクトを使用する場合は、それを.timestamp():と一緒に使用しますdatetime(2008, 1, 1, tzinfo=timezone.utc).timestamp()。エポックオブジェクトを作成し、減算..する必要はありません
マルタインピータース
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.