ナイーブdatetime
対認識datetime
デフォルトのdatetime
オブジェクトは「ナイーブ」と呼ばれ、タイムゾーン情報なしで時間情報を保持します。ナイーブdatetime
は、+4
明確な起源のない相対的な数(つまり、:)と考えてください(実際、起源はシステムの境界全体で共通になります)。
対照的に、全世界に共通の起源を持つdatetime
絶対数(つまり:)として認識していると考えて8
ください。
タイムゾーン情報がないと、「ナイーブ」日時を非ナイーブ時間表現に変換できません(+4
どこから開始するかわからない場合、ターゲットはどこにありますか?)。これがあなたがdatetime.datetime.toutctimestamp()
メソッドを持つことができない理由です。(cf:http://bugs.python.org/issue1457227)
あなたがいるかどうかを確認するにはdatetime
dt
ナイーブで、チェックがdt.tzinfo
、あればNone
、それはナイーブです。
datetime.now()
datetime(1970, 1, 1)
ナイーブな日時がありますが、どうすればよいですか?
あなたはあなたの特定の文脈に応じて仮定をしなければなりません:あなたがあなた自身に尋ねなければならない質問は:あなた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
mytz = pytz.timezone('Europe/Amsterdam')
dt = mytz.normalize(mytz.localize(dt, is_dst=True))
提供しないことの結果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'))
どうして?なぜなら、ターゲット時間を考慮せずに.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)オフセットの特定の時期)。
then.strftime('%s')
現地時間を想定しているが、タイムスタンプはそれdatetime(2008, 1, 1)
がUTCであることを示していることです。