web-dev-qa-db-ja.com

PythonでRFC 3339タイムスタンプを生成

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.tzinfoan abstract base class for time zone information objects.です

ここで私は迷子になります-なぜtzinfoは抽象クラスであり、どのように実装するのですか?


注:In PHPそれはtimestamp = date(DATE_RFC3339);と同じくらい簡単です。 Pythonのアプローチが複雑である理由を理解していない...)

50
Yarin

さらに下 リンク先と同じドキュメントで、実装方法を説明し、UTCクラス(UTCを表す)の完全なコード、FixedOffsetクラス(DSTおよびその他のタイムゾーンとは対照的に、UTCからの固定オフセットを持つタイムゾーンを表します)およびその他のいくつか。

7
ruakh

タイムゾーンは苦痛です。これがおそらく、タイムゾーンを日時ライブラリに含めないことを選択した理由です。

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'

39
monkut

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。

25
jfs

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)使用できます。

6
MenschMarcus

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
1
Eli_B

最新の(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互換です。

0
JJC

実際、組み込みの 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
0
gene_wood

私が作業を始めたばかりのもう1つの便利なユーティリティ: dateutil タイムゾーン処理と日付解析のためのライブラリ。これを含むSOの周りに推奨 answer

0
Yarin