日付を指定してUTCタイムスタンプを取得する方法はありますか?私が期待するもの:
datetime(2008, 1, 1, 0, 0, 0, 0)
結果になるはずです
1199145600
単純な日時オブジェクトを作成するということは、タイムゾーン情報がないことを意味します。 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
とは?
デフォルトのdatetime
オブジェクトは「ナイーブ」であると言われます:それらは時間帯情報なしで時間情報を保持します。単純なdatetime
を、明確なOriginのない相対番号(例:+4
)として考えてください(実際、Originはシステムの境界全体で共通です)。全世界で共通のOriginを持つ絶対変数(8
)としてdatetime
を認識することを考えてください。
タイムゾーン情報なしできません「単純な」日付時刻を非単純な時刻表現に変換します(どこから始めればわからない場合は+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
私はナイーブな日付時刻があります、私は何ができますか?
特定のコンテキストに応じて仮定を行う必要があります。あなたが自問しなければならない質問は、UTCのdatetime
でしたか?それとも現地時間でしたか?
TCを使用していた場合(問題はありません):
import calendar
def dt2ts(dt):
"""Converts a datetime object to UTC timestamp
naive datetime will be considered UTC.
"""
return calendar.timegm(dt.utctimetuple())
TCを使用していない場合、地獄へようこそ。
前の関数を使用する前に、datetime
を非ナイーブにする必要があります。これには、目的のタイムゾーンを返す必要があります。
タイムゾーンの名前およびDSTが有効かどうかに関する情報が必要です。ターゲットのナイーブな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
を使用しないと、逆方向の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オブジェクトを選択します。
古い不正解(これを報告してくれた@ J.F.Sebastienに感謝します):
単純なdatetime
オブジェクトを作成するときにタイムゾーン(ローカルOrigin)を推測するのは非常に簡単です。これは、単純なdatetimeオブジェクトの作成と取得したい瞬間との間で変更しないことが望ましいシステム構成に関連しているためですUTCタイムスタンプ。このトリックは、imperfectの質問に使用できます。
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オフセットがエポックからのUTCオフセットと同じであるという仮定を立てているため、正しくありません。多くのタイムゾーン(夏時間(DST)オフセットの特定の年の瞬間)。
別の可能性は次のとおりです。
d = datetime.datetime.utcnow()
Epoch = datetime.datetime(1970,1,1)
t = (d - Epoch).total_seconds()
これは、「d」と「Epoch」の両方が単純な日付時刻であるため、「-」演算子が有効になり、間隔が返されます。 total_seconds()
は、間隔を秒に変換します。 total_seconds()
はd.microsecond == 0
であってもfloatを返すことに注意してください
this ブログエントリで説明されている calendar.timegm() 関数にも注意してください。
import calendar
calendar.timegm(utc_timetuple)
出力は、vaabの解と一致する必要があります。
入力日時オブジェクトがUTCの場合:
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> timestamp = (dt - datetime(1970, 1, 1)).total_seconds()
1199145600.0
注:浮動小数点数を返します。つまり、マイクロ秒は秒の小数部として表されます。
入力日付オブジェクトがUTCの場合:
>>> from datetime import date
>>> utc_date = date(2008, 1, 1)
>>> timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * 24*60*60
1199145600
詳細は datetime.dateをPythonのUTCタイムスタンプに変換する でご覧ください。
実際、utcfromtimestampの使用とタイムゾーンの指定には問題があります。素敵な例/説明は、次の質問で利用できます。
受け入れられた答えは私にとってはうまくいかないようです。私の解決策:
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