Pythonでのdatetime.dateからUTCタイムスタンプへの変換


295

私はPythonで日付を扱っており、それらをJavaScript内で使用するためにUTCタイムスタンプに変換する必要があります。次のコードは機能しません。

>>> d = datetime.date(2011,01,01)
>>> datetime.datetime.utcfromtimestamp(time.mktime(d.timetuple()))
datetime.datetime(2010, 12, 31, 23, 0)

最初に日付オブジェクトを日付時刻に変換しても、役に立ちません。私はこのリンクで例を試しましたが、

from pytz import utc, timezone
from datetime import datetime
from time import mktime
input_date = datetime(year=2011, month=1, day=15)

そして今どちらか:

mktime(utc.localize(input_date).utctimetuple())

または

mktime(timezone('US/Eastern').localize(input_date).utctimetuple())

動作します。

だから一般的な質問:UTCによると、どのようにしてエポックからの秒数に変換された日付を取得できますか?



29
重複としてマークすることに同意するかどうかはわかりません。ソリューションは似ていますが、質問は異なります。1つ(これ)はからタイムスタンプを作成しようとしていますdatetime.date。もう1つは文字列表現をあるタイムゾーンから別のタイムゾーンに変換しようとしています。この問題の解決策を探している誰かとして、私が後者が私が探している答えを提供するとは限らないかもしれません。
DRH 2012年

5
datetime(date.year、date.month、date.day).timestamp()
Julian

回答:


462

d = date(2011, 1, 1)UTCの場合:

>>> from datetime import datetime, date
>>> import calendar
>>> timestamp1 = calendar.timegm(d.timetuple())
>>> datetime.utcfromtimestamp(timestamp1)
datetime.datetime(2011, 1, 1, 0, 0)

dローカルタイムゾーンの場合:

>>> import time
>>> timestamp2 = time.mktime(d.timetuple()) # DO NOT USE IT WITH UTC DATE
>>> datetime.fromtimestamp(timestamp2)
datetime.datetime(2011, 1, 1, 0, 0)

timestamp1 そして timestamp2ローカルタイムゾーンで深夜はUTCで深夜と同じ時間インスタンスではない場合異なる場合があります。

mktime()あいまいな現地時間にd対応している場合(DSTの移行中など)、またはdutcオフセットが異なる可能性があり、C mktime()が特定のプラットフォームのtzデータベースにアクセスできない場合、過去の(未来の)日付である場合、誤った結果を返すことがあります。 。あなたは可能性があり使用pytz(を経由して、例えばモジュールをtzlocal.get_localzone()すべてのプラットフォーム上のTZデータベースへのアクセスを取得します)。また、タイムゾーンが使用されている場合utcfromtimestamp()失敗し、mktime()POSIX以外のタイムスタンプが返されることがあり"right"ます。


datetime.dateなしでUTCで日付を表すオブジェクトを変換するにはcalendar.timegm()

DAY = 24*60*60 # POSIX day in seconds (exact value)
timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * DAY
timestamp = (utc_date - date(1970, 1, 1)).days * DAY

UTCによると、エポック以降の日付を秒に変換するにはどうすればよいですか?

変換するdatetime.datetime(しないdatetime.date)が既に対応するPOSIXタイムスタンプ(AとUTCの時刻を表すオブジェクトfloat)に。

Python 3.3以降

datetime.timestamp()

from datetime import timezone

timestamp = dt.replace(tzinfo=timezone.utc).timestamp()

注:それtimezone.utc以外の場合は明示的に指定する必要があります.timestamp()するがあります。場合は、単純なdatetimeオブジェクトがローカルタイムゾーンにあると想定します。

Python 3(<3.3)

のドキュメントからdatetime.utcfromtimestamp()

日時インスタンスからタイムスタンプを取得する方法はありませんが、日時インスタンスdtに対応するPOSIXタイムスタンプは、次のように簡単に計算できます。素朴なdtの場合:

timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)

そして、認識しているdtの場合:

timestamp = (dt - datetime(1970,1,1, tzinfo=timezone.utc)) / timedelta(seconds=1)

興味深い読み物:エポック時間と1日の時間の違いは何時ですか?そして何秒が経過しましたか?

参照:datetimeには「エポック」メソッドが必要

Python 2

上記のコードをPython 2に適合させるには:

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

どこtimedelta.total_seconds()に相当し(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6、真の分裂を有効にして計算しました。

from __future__ import division
from datetime import datetime, timedelta

def totimestamp(dt, epoch=datetime(1970,1,1)):
    td = dt - epoch
    # return td.total_seconds()
    return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6 

now = datetime.utcnow()
print now
print totimestamp(now)

浮動小数点の問題に注意してください。

出力

2012-01-08 15:34:10.022403
1326036850.02

認識datetimeオブジェクトをPOSIXタイムスタンプに変換する方法

assert dt.tzinfo is not None and dt.utcoffset() is not None
timestamp = dt.timestamp() # Python 3.3+

Python 3の場合:

from datetime import datetime, timedelta, timezone

epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
timestamp = (dt - epoch) / timedelta(seconds=1)
integer_timestamp = (dt - epoch) // timedelta(seconds=1)

Python 2の場合:

# utc time = local time              - utc offset
utc_naive  = dt.replace(tzinfo=None) - dt.utcoffset()
timestamp = (utc_naive - datetime(1970, 1, 1)).total_seconds()

2
Python 2の場合、なぜtimestamp = (dt - datetime.fromtimestamp(0)).total_seconds()ですか:?
m01

7
@ m01:datetime(1970, 1, 1)より明示的です。fromtimestamp()ここでは正しくありません(dtUTCにあるため、utcfromtimestamp()代わりに使用する必要があります)。
jfs

1
@fedorqui totimestamp()関数の答えを見てください。
jfs 2015年

14
私がpythonを愛しているのと同じくらい、その日時ライブラリは深刻に壊れています。
Realfun 2016年

3
@Realfun:タイムゾーン、DSTトランジション、tzデータベース、うるう秒はPythonから独立しています。
jfs

81

以下のためのUNIXシステムのみ

>>> import datetime
>>> d = datetime.date(2011,01,01)
>>> d.strftime("%s")  # <-- THIS IS THE CODE YOU WANT
'1293832800'

注1: dizzyfは、これがローカライズされたタイムゾーンに適用されることを確認しました。本番環境では使用しないでください。

注2: JakubNarębskiは、オフセット対応の日時(Python 2.7でテスト済み)であってもタイムゾーン情報を無視することに注意しました。


4
コードが実行されるシステムがわかっている場合は良い答えですが、 '%s'形式の文字列がすべてのOSに存在するわけではないため、このコードは移植性がないことに注意してください。サポートされているかどうかを確認したい場合はman strftime、Unixライクなシステムで確認できます。
アリスヒートン2016

5
これにより、秒の小数部(マイクロ秒など)が削除されることに注意してください。
2017年

11
警告:これはローカライズされたタイムゾーンに適用されます!マシンの時間に応じて、同じdatetimeオブジェクトに対して異なるstrftime動作を取得します
dizzyf

3
さらに、これはタイムゾーン情報無視し、tzinfoが設定されたオフセット対応のdatetimeでも、datetimeがローカルタイムゾーンにあると想定します。まあ、少なくともPython 2.7では。
JakubNarębski2018年

1
javascriptタイムスタンプ= pythonタイムスタンプ* 1000
Trinh Hoang Nhu

38
  • 前提1:日付をタイムスタンプに変換しようとしていますが、日付は24時間をカバーしているため、その日付を表す単一のタイムスタンプはありません。真夜中(00:00:00.000)の日付のタイムスタンプを表すと仮定します。

  • 仮定2:提示する日付が特定のタイムゾーンに関連付けられていないが、特定のタイムゾーン(UTC)からのオフセットを決定する必要がある。日付が含まれているタイムゾーンがわからない場合、特定のタイムゾーンのタイムスタンプを計算することはできません。日付をローカルシステムのタイムゾーンであるかのように扱いたいと仮定します。

最初に、timetuple()メンバーを使用して、日付インスタンスをさまざまな時間コンポーネントを表すタプルに変換できます。

dtt = d.timetuple() # time.struct_time(tm_year=2011, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=-1)

次に、次のコマンドを使用してタイムスタンプに変換できますtime.mktime

ts = time.mktime(dtt) # 1293868800.0

このメソッドは、エポック時間自体(1970-01-01)でテストすることで確認できます。その場合、関数はその日付のローカルタイムゾーンのタイムゾーンオフセットを返す必要があります。

d = datetime.date(1970,1,1)
dtt = d.timetuple() # time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=-1)
ts = time.mktime(dtt) # 28800.0

28800.0 は8時間です。これは、太平洋のタイムゾーン(私がいる場所)に適しています。


なぜこれが反対投票されたのかはわかりません。これはOPの問題に対処します(OPが「機能していない」というラベルの付いた機能するコード)。それは私の質問に答えません(UTC datetime.datetimeをタイムスタンプに変換します)が、それでも…賛成票を投じます。
タナトス2012年

9
注意してください。「日付をローカルシステムのタイムゾーンであるかのように扱いたいという仮定は、Pythonのタイムゾーンに関するすべての問題の根源です。スクリプトを実行するマシンのローカリゼーション、特に世界のどこからでもアクセスできるクライアントにサービスを提供する場合は、常に日付がUTCであると想定し、変換をできるだけ早く行います。これにより、髪の毛が途切れることはありません。信頼してください
Romain G

8

python2.7ドキュメントに従ってください。time.mktime()の代わりにcalendar.timegm()を使用する必要があります

>>> d = datetime.date(2011,01,01)
>>> datetime.datetime.utcfromtimestamp(calendar.timegm(d.timetuple()))
datetime.datetime(2011, 1, 1, 0, 0)

3
UTCの場合、私の回答とどう違うのdですか?
jfs、2014

8

私は自分の2つの関数を定義しました

  • utc_time2datetime(utc_time、tz = None)
  • datetime2utc_time(datetime)

ここに:

import time
import datetime
from pytz import timezone
import calendar
import pytz


def utc_time2datetime(utc_time, tz=None):
    # convert utc time to utc datetime
    utc_datetime = datetime.datetime.fromtimestamp(utc_time)

    # add time zone to utc datetime
    if tz is None:
        tz_datetime = utc_datetime.astimezone(timezone('utc'))
    else:
        tz_datetime = utc_datetime.astimezone(tz)

    return tz_datetime


def datetime2utc_time(datetime):
    # add utc time zone if no time zone is set
    if datetime.tzinfo is None:
        datetime = datetime.replace(tzinfo=timezone('utc'))

    # convert to utc time zone from whatever time zone the datetime is set to
    utc_datetime = datetime.astimezone(timezone('utc')).replace(tzinfo=None)

    # create a time tuple from datetime
    utc_timetuple = utc_datetime.timetuple()

    # create a time element from the tuple an add microseconds
    utc_time = calendar.timegm(utc_timetuple) + datetime.microsecond / 1E6

    return utc_time

1
私はあなたの例を通り過ぎて閲覧しました。そのような単純なことのために乱雑で複雑になる方法.. pythonicではありません。
Angry 84

@Mayhem:少し整理してコメントを追加しました。時刻から日付時刻に変換し、時間帯を設定できるようにするためのより一般的なソリューションがある場合は、お知らせください。また、私のコードのよりPython的な例がどのようになるかを教えてください。
agittarius

3

質問は少し混乱しています。タイムスタンプはUTCではありません-それらはUnixのものです。日付はUTCかもしれませんか?そうであると仮定し、Python 3.2以降を使用している場合、simple-dateはこれを簡単にします。

>>> SimpleDate(date(2011,1,1), tz='utc').timestamp
1293840000.0

実際に年、月、日がある場合、作成する必要はありませんdate

>>> SimpleDate(2011,1,1, tz='utc').timestamp
1293840000.0

そして、日付が他のタイムゾーンにある場合(これは、関連付けられた時刻がない真夜中を想定しているため、これは重要です):

>>> SimpleDate(date(2011,1,1), tz='America/New_York').timestamp
1293858000.0

[simple-dateの背後にある考え方は、すべてのpythonの日付と時刻を1つの一貫したクラスに収集することです。これにより、任意の変換を実行できます。したがって、たとえば、それは逆の方向にも行きます。

>>> SimpleDate(1293858000, tz='utc').date
datetime.date(2011, 1, 1)

]


SimpleDate(date(2011,1,1), tz='America/New_York')は発生しますがNoTimezonepytz.timezone('America/New_York')例外は発生しません(simple-date==0.4.8pytz==2014.7)。
jfs 2014年

でエラーが発生しましたpip install simple-date。python3/ pip3のみのようです。
NoBugs

3

arrowパッケージの使用:

>>> import arrow
>>> arrow.get(2010, 12, 31).timestamp
1293753600
>>> time.gmtime(1293753600)
time.struct_time(tm_year=2010, tm_mon=12, tm_mday=31, 
    tm_hour=0, tm_min=0, tm_sec=0, 
    tm_wday=4, tm_yday=365, tm_isdst=0)

注:arrowdateutil 、タイムゾーンの処理に関連するバグ使用し、長年にわたってdateutil知ら ています。UTCオフセットが固定されていないタイムゾーンの正しい結果が必要な場合は使用しないでください(UTCタイムゾーンに使用しても問題ありませんが、stdlibがUTCケースを処理しても問題ありません)。
jfs

@JFSebastianそのバグは、移行中にのみ、あいまいな時間に発生します。
Paul

バグは3月28日に修正されたようです
Mathieu Longtin

どうやら、それは最高のクロスPythonソリューションのようです。矢印を使用してください。ありがとう;)
maxkoryukov

@MathieuLongtin dateutilには他の問題
jfs 2018年

1

完全な時間文字列には以下が含まれます。

  • 日付
  • 時間
  • utcoffset [+HHMM or -HHMM]

例えば:

1970-01-01 06:00:00 +0500 == 1970-01-01 01:00:00 +0000 == UNIX timestamp:3600

$ python3
>>> from datetime import datetime
>>> from calendar import timegm
>>> tm = '1970-01-01 06:00:00 +0500'
>>> fmt = '%Y-%m-%d %H:%M:%S %z'
>>> timegm(datetime.strptime(tm, fmt).utctimetuple())
3600

注意:

UNIX timestampエポックからの秒数で表される浮動小数点数(UTC)


編集:

$ python3
>>> from datetime import datetime, timezone, timedelta
>>> from calendar import timegm
>>> dt = datetime(1970, 1, 1, 6, 0)
>>> tz = timezone(timedelta(hours=5))
>>> timegm(dt.replace(tzinfo=tz).utctimetuple())
3600

6
そして、これは私の質問にどのように答えますか?
Andreas Jung

1
@ user908088要求どおりに変換1970-01-01 06:00:00 +05003600ます。
kev

1
@ user908088一切ありませんtimezonepython2(あなたが計算を行うことができ、06:00:00- +0500= 01:00:00)手動。
kev 2012年

5
投票数が-1でもこの回答がトップになっている理由、SOに問題がある
Umair

1

というdatetimeオブジェクトがあることを考慮してd、以下を使用してUTCでタイムスタンプを取得します。

d.strftime("%Y-%m-%dT%H:%M:%S.%fZ")

そして反対の方向については、以下を使用してください:

d = datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")

0

深い議論に感銘を受けました。

私の2セント:

日時インポートから日時インポート時間

utcのタイムスタンプは次のとおりです。

timestamp = \
(datetime.utcnow() - datetime(1970,1,1)).total_seconds()

または、

timestamp = time.time()

同じDSTで、datetime.now()の結果となった場合

utcoffset = (datetime.now() - datetime.utcnow()).total_seconds()
timestamp = \
(now - datetime(1970,1,1)).total_seconds() - utcoffset
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.