Pythonで RFC 3339 UTCタイムスタンプを生成しようとしています。これまでのところ、次のことができました。
>>> d = datetime.datetime.now()
>>> print d.isoformat('T')
2011-12-18T20:46:00.392227
私の問題は、UTCオフセットの設定にあります。
docs によると、クラスメソッドdatetime.now([tz])
は、オプションのtz
引数を取ります。ここでtz must be an instance of a class tzinfo subclass
、およびdatetime.tzinfo
はan abstract base class for time zone information objects.
です
ここで私は迷子になります-なぜtzinfoは抽象クラスであり、どのように実装するのですか?
(注:In PHPそれはtimestamp = date(DATE_RFC3339);
と同じくらい簡単です。 Pythonのアプローチが複雑である理由を理解していない...)
さらに下 リンク先と同じドキュメントで、実装方法を説明し、UTC
クラス(UTCを表す)の完全なコード、FixedOffset
クラス(DSTおよびその他のタイムゾーンとは対照的に、UTCからの固定オフセットを持つタイムゾーンを表します)およびその他のいくつか。
タイムゾーンは苦痛です。これがおそらく、タイムゾーンを日時ライブラリに含めないことを選択した理由です。
pytzを試してください。探しているtzinfoがあります。 http://pytz.sourceforge.net/
最初にdatetime
オブジェクトを作成し、次に以下のようにタイムゾーンを適用する必要があります。その後、.isoformat()
出力には必要に応じてUTCオフセットが含まれます。
d = datetime.datetime.utcnow()
d_with_timezone = d.replace(tzinfo=pytz.UTC)
d_with_timezone.isoformat()
'2017-04-13T14:34:23.111142 + 00:00'
または、UTCを使用し、最後に「Z」(Zuluタイムゾーン)をスローして、「タイムゾーン」をUTCとしてマークします。
d = datetime.datetime.utcnow() # <-- get time in UTC
print d.isoformat("T") + "Z"
'2017-04-13T14:34:23.111142Z'
In Python 3.3+:
>>> from datetime import datetime, timezone
>>> local_time = datetime.now(timezone.utc).astimezone()
>>> local_time.isoformat()
'2015-01-16T16:52:58.547366+01:00'
古いバージョンPythonバージョンでは、UTCで現在の時刻を表す認識日時オブジェクトだけが必要な場合は、ドキュメントに示すように単純なtzinfoサブクラスを定義することができます UTCタイムゾーンを表します :
from datetime import datetime
utc_now = datetime.now(utc)
print(utc_now.isoformat('T'))
# -> 2015-05-19T20:32:12.610841+00:00
tzlocal
module を使用して、ローカルタイムゾーンを表すpytz
タイムゾーンを取得することもできます。
#!/usr/bin/env python
from datetime import datetime
from tzlocal import get_localzone # $ pip install tzlocal
now = datetime.now(get_localzone())
print(now.isoformat('T'))
Python 2および3。
RFC3339のdatetime形式にはかなり苦労しましたが、date_string <=> datetime_objectを両方向に変換する適切なソリューションを見つけました。
2つの異なる外部モジュールが必要です。1つは一方向の変換しかできないためです(残念ながら)。
最初のインストール:
Sudo pip install rfc3339
Sudo pip install iso8601
次に含まれます:
import datetime # for general datetime object handling
import rfc3339 # for date object -> date string
import iso8601 # for date string -> date object
どのモジュールがどの方向に向いているかを覚える必要がないため、2つの簡単なヘルパー関数を作成しました。
def get_date_object(date_string):
return iso8601.parse_date(date_string)
def get_date_string(date_object):
return rfc3339.rfc3339(date_object)
コード内で次のように簡単に使用できます。
input_string = '1989-01-01T00:18:07-05:00'
test_date = get_date_object(input_string)
# >>> datetime.datetime(1989, 1, 1, 0, 18, 7, tzinfo=<FixedOffset '-05:00' datetime.timedelta(-1, 68400)>)
test_string = get_date_string(test_date)
# >>> '1989-01-01T00:18:07-05:00'
test_string is input_string # >>> True
ヘレカ!これで、日付文字列と使用可能な形式の日付文字列を簡単に(haha)使用できます。
pytz パッケージは、Python 2.Xおよび3.Xで使用可能です。tzinfo
などの具体的なサブクラスを実装しているため、する必要はありません。
UTCオフセットを追加するには:import datetime import pytz
dt = datetime.datetime(2011, 12, 18, 20, 46, 00, 392227)
utc_dt = pytz.UTC.localize(dt)
そして今、これ:
print utc_dt.isoformat()
印刷します:
2011-12-18T20:46:00.392227+00:00
最新の(3.x)Pythonでは、RFC 3339 UTC時間を取得するために必要なことは、datetimeとこの単一行を使用することだけです(サードパーティのモジュールは不要です)。
import datetime
datetime.datetime.now(datetime.timezone.utc).isoformat()
結果は次のようになります: '2019-06-13T15:29:28.972488 + 00:00'
このISO 8601文字列もRFC3339互換です。
実際、組み込みの datetime モジュールを使用できます。 @ ruakhmentions のように、ページに方法を示す例があります。 tzinfo のセクションを見ると、多くの異なるユースケースを示す長い例があります。探しているコードのコードは次のとおりです。RFC3339 UTCタイムスタンプを生成します。
from datetime import tzinfo, timedelta, datetime
import time as _time
ZERO = timedelta(0)
STDOFFSET = timedelta(seconds=-_time.timezone)
if _time.daylight:
DSTOFFSET = timedelta(seconds=-_time.altzone)
else:
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
def utcoffset(self, dt):
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return DSTDIFF
else:
return ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, 0)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0
Local = LocalTimezone()
d = datetime.now(Local)
print d.isoformat('T')
# which returns
# 2014-04-28T15:44:45.758506-07:00