RFC 3339文字列"2008-09-03T20:56:35.450686Z"
をPythonのdatetime
型のように解析する必要があります。
私はstrptime
Python標準ライブラリで見つけましたが、あまり便利ではありません。
これを行う最良の方法は何ですか?
RFC 3339文字列"2008-09-03T20:56:35.450686Z"
をPythonのdatetime
型のように解析する必要があります。
私はstrptime
Python標準ライブラリで見つけましたが、あまり便利ではありません。
これを行う最良の方法は何ですか?
回答:
python-dateutilパッケージは、問題の1のようにだけでなく、RFC 3339日時文字列を解析することができますが、他のISO 8601なしUTCを持つものは、オフセットRFC 3339に準拠していない日付と時刻の文字列(のような、またはものは表しています日付のみ)。
>>> import dateutil.parser
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686Z') # RFC 3339 format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686') # ISO 8601 extended format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903T205635.450686') # ISO 8601 basic format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903') # ISO 8601 basic format, date only
datetime.datetime(2008, 9, 3, 0, 0)
注dateutil.parser.isoparse
以上ハックよりもおそらく厳しいですdateutil.parser.parse
が、それらの両方が非常に寛容され、あなたが渡しする文字列を解釈しようとします。あなたが任意の誤読の可能性を排除したい場合は、これらのいずれかよりも、何かの厳しいを使用する必要があります機能。
Pypiの名前はpython-dateutil
、ではなく、ですdateutil
(thanks code3monk3y):
pip install python-dateutil
Python 3.7を使用している場合は、に関するこの回答をご覧くださいdatetime.datetime.fromisoformat
。
python-dateutil
はnot を介してインストールされるためdateutil
、次のようになりますpip install python-dateutil
。
dateutil.parser
は意図的にハッキングされていることに注意してください。これは形式を推測しようとし、あいまいな場合には避けられない仮定(手動でのみカスタマイズ可能)を作成します。したがって、不明な形式の入力を解析する必要があり、時々の誤読を許容できる場合にのみ使用してください。
datetime
標準ライブラリは反転するための機能を導入しましたdatetime.isoformat()
。
classmethod
datetime.fromisoformat(date_string)
:and によって発行されたいずれかの形式でaに
datetime
対応するを返しdate_string
ますdate.isoformat()
datetime.isoformat()
。具体的には、この関数は次の形式の文字列をサポートしています。
YYYY-MM-DD[*HH[:MM[:SS[.mmm[mmm]]]][+HH:MM[:SS[.ffffff]]]]
where
*
は任意の1文字に一致します。注意:これは、任意のISO 8601文字列の解析をサポートしていません。これは、の逆の操作としてのみ意図されてい
datetime.isoformat()
ます。
使用例:
from datetime import datetime
date = datetime.fromisoformat('2017-01-01T12:30:59.000000')
datetime
が含まれている可能性があるため、tzinfo
タイムゾーンが出力されますがdatetime.fromisoformat()
、tzinfoは解析されません。バグのようです..
isoformat
たものだけを受け入れます。"2008-09-03T20:56:35.450686Z"
末尾Z
が原因で問題の例を受け入れませんが、受け入れ"2008-09-03T20:56:35.450686"
ます。
Z
入力スクリプトを適切にサポートするには、を使用して変更できますdate_string.replace("Z", "+00:00")
。
Python 2.6+およびPy3Kでは、%f文字がマイクロ秒をキャッチすることに注意してください。
>>> datetime.datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")
ここで問題を参照してください
strptime
。
datetime.datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f')
ため、これでうまく
ここでいくつかの回答 は、質問に示されているもののように、タイムゾーンを使用してRFC 3339またはISO 8601の日時を解析することを提案しています。 datetime.datetime.strptime
2008-09-03T20:56:35.450686Z
これは悪い考えです。
ゼロ以外のUTCオフセットのサポートを含む完全なRFC 3339形式をサポートする場合、これらの回答が示唆するコードは機能しません。確かに、それはできません RFC 3339の構文を解析使用しているので、仕事strptime
は不可能。Pythonのdatetimeモジュールで使用されるフォーマット文字列は、RFC 3339構文を記述できません。
問題はUTCオフセットです。RFC 3339インターネット日付/時刻の形式は、すべての日時はUTCオフセット、およびそれらのオフセットはいずれかになりますことを含んでいることが必要ですZ
(「ズールー時間」の短縮形)または中+HH:MM
または-HH:MM
フォーマット、同様+05:00
または-10:30
。
したがって、これらはすべて有効なRFC 3339の日時です。
2008-09-03T20:56:35.450686Z
2008-09-03T20:56:35.450686+05:00
2008-09-03T20:56:35.450686-10:30
悲しいかな、RFC 3339形式のUTCオフセットに対応するディレクティブを使用しstrptime
てstrftime
いるディレクティブはありません。それらがサポートするディレクティブの完全なリストはhttps://docs.python.org/3/library/datetime.html#strftime-and-strptime-behaviorにあり、リストに含まれる唯一のUTCオフセットディレクティブは%z
次のとおりです。
%z
+ HHMMまたは-HHMMの形式のUTCオフセット(オブジェクトがナイーブの場合は空の文字列)。
例:(空)、+ 0000、-0400、+ 1030
これはRFC 3339オフセットの形式と一致しません。実際%z
に、形式文字列で使用してRFC 3339日付を解析しようとすると、失敗します。
>>> from datetime import datetime
>>> datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%f%z")
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
(data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686Z' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
>>> datetime.strptime("2008-09-03T20:56:35.450686+05:00", "%Y-%m-%dT%H:%M:%S.%f%z")
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
(data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686+05:00' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
(実際、上記はPython 3で表示されるものにすぎません。Python2では、さらに単純な理由で失敗します。これは、Python 2でディレクティブをまったく実装してstrptime
いないため%z
です。です。)
質問者の例の日時文字列のと一致strptime
するリテラルZ
をフォーマット文字列に含めることにより、これを回避することをすべて推奨するここでの複数の回答Z
(および破棄してdatetime
タイムゾーンなしのオブジェクトを生成)
>>> datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
これにより、元の日時文字列に含まれていたタイムゾーン情報が破棄されるため、この結果も正しいと見なすべきかどうかは疑問です。しかし、さらに重要なことに、このアプローチには特定のUTCオフセットをフォーマット文字列にハードコーディングする必要があるため、別のUTCオフセットを使用してRFC 3339の日時を解析しようとすると、次のようになります。
>>> datetime.strptime("2008-09-03T20:56:35.450686+05:00", "%Y-%m-%dT%H:%M:%S.%fZ")
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
(data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686+05:00' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'
RFC 3339の日時をZulu時間でのみサポートする必要があり、他のタイムゾーンオフセットの日時をサポートする必要がないことが確実でない限り、は使用しないでくださいstrptime
。代わりに、ここで回答に記載されている他の多くのアプローチの1つを使用してください。
strptime()
Python 3.7では、この回答で不可能と記述されているすべてをサポートするようになりました(タイムゾーンオフセットの「Z」リテラルと「:」)。残念ながら、RFC 3339がISO 8601と根本的に互換性がない別のコーナーケースがあります。つまり、前者は負のnullタイムゾーンオフセット-00:00を許可し、後者は許可しません。
iso8601モジュールを試してください。それはまさにこれを行います。
python.org wikiのWorkingWithTimeページで言及されている他のいくつかのオプションがあります。
iso8601.parse_date("2008-09-03T20:56:35.450686Z")
インポート日時 s = "2008-09-03T20:56:35.450686Z" d = datetime.datetime(* map(int、re.split( '[^ \ d]'、s)[:-1]))
datetime.datetime(*map(int, re.findall('\d+', s))
あなたが得る正確なエラーは何ですか?次のようですか?
>>> datetime.datetime.strptime("2008-08-12T12:20:30.656234Z", "%Y-%m-%dT%H:%M:%S.Z")
ValueError: time data did not match format: data=2008-08-12T12:20:30.656234Z fmt=%Y-%m-%dT%H:%M:%S.Z
はいの場合、入力文字列を「。」で分割し、取得した日時にマイクロ秒を追加できます。
これを試して:
>>> def gt(dt_str):
dt, _, us= dt_str.partition(".")
dt= datetime.datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S")
us= int(us.rstrip("Z"), 10)
return dt + datetime.timedelta(microseconds=us)
>>> gt("2008-08-12T12:20:30.656234Z")
datetime.datetime(2008, 8, 12, 12, 20, 30, 656234)
""
、または"Z"
、直接DateTimeオブジェクトへ/から減算添加することができ、時間/分でオフセットされなければなりません。tzinfoサブクラスを作成してそれを処理することもできますが、それはおそらくお勧めできません。
Python 3.7以降、strptimeはUTCオフセット(source)のコロン区切り文字をサポートしています。だからあなたはそれから使うことができます:
import datetime
datetime.datetime.strptime('2018-01-31T09:24:31.488670+00:00', '%Y-%m-%dT%H:%M:%S.%f%z')
編集:
Martijnが指摘したように、isoformat()を使用してdatetimeオブジェクトを作成した場合は、単純にdatetime.fromisoformat()を使用できます。
datetime.fromisoformat()
ますdatetime.datetime.isoformat('2018-01-31T09:24:31.488670+00:00')
。
datetime.fromisoformat()
してdatetime.isoformat()
最近では、Arrowはサードパーティのソリューションとしても使用できます。
>>> import arrow
>>> date = arrow.get("2008-09-03T20:56:35.450686Z")
>>> date.datetime
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
python-dateutil
モジュールを使用するだけです:
>>> import dateutil.parser as dp
>>> t = '1984-06-02T19:05:00.000Z'
>>> parsed_t = dp.parse(t)
>>> print(parsed_t)
datetime.datetime(1984, 6, 2, 19, 5, tzinfo=tzutc())
455051100
(epochconverter.comでチェック)。
dateutilを使用したくない場合は、次の関数を試すことができます。
def from_utc(utcTime,fmt="%Y-%m-%dT%H:%M:%S.%fZ"):
"""
Convert UTC time string to time.struct_time
"""
# change datetime.datetime to time, return time.struct_time type
return datetime.datetime.strptime(utcTime, fmt)
テスト:
from_utc("2007-03-04T21:08:12.123Z")
結果:
datetime.datetime(2007, 3, 4, 21, 8, 12, 123000)
strptime
。異なるUTCオフセットで日時を解析できず、例外が発生するため、これは悪い考えです。RFC 3339をstrptimeで解析することが実際にどのように不可能であるかを説明する私の回答を参照してください。
toISOString
メソッドで生成されたことがわかっている場合などです。しかし、この回答では、ズールー語の日付の制限についての言及はありません。また、質問でそれが必要なすべてであることも示されていませんdateutil
。
Djangoを使用している場合は、タイムゾーンなど、ISO形式に類似した一連の形式を受け入れるdateparseモジュールが提供されます。
Djangoを使用しておらず、ここで説明した他のライブラリを使用したくない場合は、おそらくDjangoのソースコードをdateparse用にプロジェクトに適合させることができます。
DateTimeField
は文字列値を設定するときにこれを使用します。
ciso8601がISO 8601タイムスタンプを解析する最も速い方法であることがわかりました。名前が示すように、Cで実装されています。
import ciso8601
ciso8601.parse_datetime('2014-01-09T21:48:00.921000+05:30')
GitHubのレポREADME他の回答に記載されている他のライブラリのすべての対彼らの> 10倍の高速化を示しています。
私の個人的なプロジェクトには、多くのISO 8601解析が含まれていました。通話を切り替えるだけで10倍高速に処理できて良かったです。:)
編集:私は以来、ciso8601のメンテナーになりました。今までよりも速くなりました!
datetime.strptime()
が次の最速のソリューションであることを示すために洞察に富んでいました。すべての情報をまとめてくれてありがとう!
datetime.strptime()
これは完全なISO 8601解析ライブラリではないことに注意してください。Python 3.7を使用しているdatetime.fromisoformat()
場合は、このメソッドを使用できます。このメソッドは少し柔軟性があります。すぐにciso8601 READMEにマージされるパーサーのこのより完全なリストに興味があるかもしれません。
これはPython 3.2以降のstdlibで機能します(すべてのタイムスタンプがUTCであると想定):
from datetime import datetime, timezone, timedelta
datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%fZ").replace(
tzinfo=timezone(timedelta(0)))
例えば、
>>> datetime.utcnow().replace(tzinfo=timezone(timedelta(0)))
... datetime.datetime(2015, 3, 11, 6, 2, 47, 879129, tzinfo=datetime.timezone.utc)
strptime
。異なるUTCオフセットで日時を解析できず、例外が発生するため、これは悪い考えです。RFC 3339をstrptimeで解析することが実際にどのように不可能であるかを説明する私の回答を参照してください。
timezone.utc
代わりに使用できますtimezone(timedelta(0))
。また、コードは2.6+ Pythonで動作します(少なくとも)あなたがあれば提供utc
tzinfoのオブジェクトを
%Z
最新バージョンのPythonでforタイムゾーンを使用できます。
datetime.datetime
サードパーティのモジュールをインストールせずに、サポートされているすべてのPythonバージョンでISO 8601のような日付文字列をUNIXタイムスタンプまたはオブジェクトに変換する簡単な方法の1つは、SQLiteの日付パーサーを使用することです。
#!/usr/bin/env python
from __future__ import with_statement, division, print_function
import sqlite3
import datetime
testtimes = [
"2016-08-25T16:01:26.123456Z",
"2016-08-25T16:01:29",
]
db = sqlite3.connect(":memory:")
c = db.cursor()
for timestring in testtimes:
c.execute("SELECT strftime('%s', ?)", (timestring,))
converted = c.fetchone()[0]
print("%s is %s after epoch" % (timestring, converted))
dt = datetime.datetime.fromtimestamp(int(converted))
print("datetime is %s" % dt)
出力:
2016-08-25T16:01:26.123456Z is 1472140886 after epoch
datetime is 2016-08-25 12:01:26
2016-08-25T16:01:29 is 1472140889 after epoch
datetime is 2016-08-25 12:01:29
ISO 8601標準のパーサーをコード化し、GitHubに配置しました:https : //github.com/boxed/iso8601。この実装は、期間、間隔、定期的な間隔、およびPythonの日時モジュールのサポートされている日付範囲外の日付を除いて、仕様のすべてをサポートします。
テストが含まれています!:P
Djangoのparse_datetime()関数はUTCオフセットの日付をサポートします:
parse_datetime('2016-08-09T15:12:03.65478Z') =
datetime.datetime(2016, 8, 9, 15, 12, 3, 654780, tzinfo=<UTC>)
したがって、プロジェクト全体のフィールドでISO 8601日付を解析するために使用できます。
from django.utils import formats
from django.forms.fields import DateTimeField
from django.utils.dateparse import parse_datetime
class DateTimeFieldFixed(DateTimeField):
def strptime(self, value, format):
if format == 'iso-8601':
return parse_datetime(value)
return super().strptime(value, format)
DateTimeField.strptime = DateTimeFieldFixed.strptime
formats.ISO_INPUT_FORMATS['DATETIME_INPUT_FORMATS'].insert(0, 'iso-8601')
ISO 8601では、基本的に、オプションのコロンとダッシュのさまざまなバリエーションが存在できるためですCCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
。strptimeを使用する場合は、最初にこれらのバリエーションを取り除く必要があります。
目標は、utc datetimeオブジェクトを生成することです。
2016-06-29T19:36:29.3453Z
:
datetime.datetime.strptime(timestamp.translate(None, ':-'), "%Y%m%dT%H%M%S.%fZ")
2016-06-29T19:36:29.3453-0400
や2008-09-03T20:56:35.450686+05:00
、以下を使用します。これらは、すべてのバリエーション20080903T205635.450686+0500
を、より一貫性のある/解析しやすいようにするなど、変数区切り文字のないものに変換 します。
import re
# this regex removes all colons and all
# dashes EXCEPT for the dash indicating + or - utc offset for the timezone
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp)
datetime.datetime.strptime(conformed_timestamp, "%Y%m%dT%H%M%S.%f%z" )
%z
strptimeディレクティブをサポートしていない場合(のように表示されますValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z'
)、時刻をZ
(UTC)から手動でオフセットする必要があります。%z
Pythonバージョン3未満のシステムでは、システム/ Pythonビルドタイプ(Jython、Cythonなど)によって異なるcライブラリサポートに依存しているため、注意が機能しない場合があります。
import re
import datetime
# this regex removes all colons and all
# dashes EXCEPT for the dash indicating + or - utc offset for the timezone
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp)
# split on the offset to remove it. use a capture group to keep the delimiter
split_timestamp = re.split(r"[+|-]",conformed_timestamp)
main_timestamp = split_timestamp[0]
if len(split_timestamp) == 3:
sign = split_timestamp[1]
offset = split_timestamp[2]
else:
sign = None
offset = None
# generate the datetime object without the offset at UTC time
output_datetime = datetime.datetime.strptime(main_timestamp +"Z", "%Y%m%dT%H%M%S.%fZ" )
if offset:
# create timedelta based on offset
offset_delta = datetime.timedelta(hours=int(sign+offset[:-2]), minutes=int(sign+offset[-2:]))
# offset datetime with timedelta
output_datetime = output_datetime + offset_delta
2.X標準ライブラリで動作するものについては、以下を試してください。
calendar.timegm(time.strptime(date.split(".")[0]+"UTC", "%Y-%m-%dT%H:%M:%S%Z"))
calendar.timegmは、不足しているgmバージョンのtime.mktimeです。
python-dateutilは、無効な日付文字列を解析すると例外をスローするため、例外をキャッチしたい場合があります。
from dateutil import parser
ds = '2012-60-31'
try:
dt = parser.parse(ds)
except ValueError, e:
print '"%s" is an invalid date' % ds
最近では、人気のあるRequests:HTTP for Humans™パッケージの作者によるMaya:Datetimes for Humans™があります。
>>> import maya
>>> str = '2008-09-03T20:56:35.450686Z'
>>> maya.MayaDT.from_rfc3339(str).datetime()
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=<UTC>)
ISO-8601の専用パーサーを使用する別の方法は、dateutilパーサーのisoparse関数を使用することです。
from dateutil import parser
date = parser.isoparse("2008-09-03T20:56:35.450686+01:00")
print(date)
出力:
2008-09-03 20:56:35.450686+01:00
この関数は、標準のPython関数datetime.fromisoformatのドキュメントにも記載されています。
フル機能のISO 8601パーサーであるdateutil.parser.isoparseは、サードパーティのパッケージdateutilで利用できます。
素晴らしいMark Ameryの回答のおかげで、日時の可能なすべてのISO形式を説明する関数を考案しました。
class FixedOffset(tzinfo):
"""Fixed offset in minutes: `time = utc_time + utc_offset`."""
def __init__(self, offset):
self.__offset = timedelta(minutes=offset)
hours, minutes = divmod(offset, 60)
#NOTE: the last part is to remind about deprecated POSIX GMT+h timezones
# that have the opposite sign in the name;
# the corresponding numeric value is not used e.g., no minutes
self.__name = '<%+03d%02d>%+d' % (hours, minutes, -hours)
def utcoffset(self, dt=None):
return self.__offset
def tzname(self, dt=None):
return self.__name
def dst(self, dt=None):
return timedelta(0)
def __repr__(self):
return 'FixedOffset(%d)' % (self.utcoffset().total_seconds() / 60)
def __getinitargs__(self):
return (self.__offset.total_seconds()/60,)
def parse_isoformat_datetime(isodatetime):
try:
return datetime.strptime(isodatetime, '%Y-%m-%dT%H:%M:%S.%f')
except ValueError:
pass
try:
return datetime.strptime(isodatetime, '%Y-%m-%dT%H:%M:%S')
except ValueError:
pass
pat = r'(.*?[+-]\d{2}):(\d{2})'
temp = re.sub(pat, r'\1\2', isodatetime)
naive_date_str = temp[:-5]
offset_str = temp[-5:]
naive_dt = datetime.strptime(naive_date_str, '%Y-%m-%dT%H:%M:%S.%f')
offset = int(offset_str[-4:-2])*60 + int(offset_str[-2:])
if offset_str[0] == "-":
offset = -offset
return naive_dt.replace(tzinfo=FixedOffset(offset))
def parseISO8601DateTime(datetimeStr):
import time
from datetime import datetime, timedelta
def log_date_string(when):
gmt = time.gmtime(when)
if time.daylight and gmt[8]:
tz = time.altzone
else:
tz = time.timezone
if tz > 0:
neg = 1
else:
neg = 0
tz = -tz
h, rem = divmod(tz, 3600)
m, rem = divmod(rem, 60)
if neg:
offset = '-%02d%02d' % (h, m)
else:
offset = '+%02d%02d' % (h, m)
return time.strftime('%d/%b/%Y:%H:%M:%S ', gmt) + offset
dt = datetime.strptime(datetimeStr, '%Y-%m-%dT%H:%M:%S.%fZ')
timestamp = dt.timestamp()
return dt + timedelta(hours=dt.hour-time.gmtime(timestamp).tm_hour)
文字列がで終わらないかどうかを調べる必要があることに注意してください。Z
を使用して解析できます%z
。
最初に私は試しました:
from operator import neg, pos
from time import strptime, mktime
from datetime import datetime, tzinfo, timedelta
class MyUTCOffsetTimezone(tzinfo):
@staticmethod
def with_offset(offset_no_signal, signal): # type: (str, str) -> MyUTCOffsetTimezone
return MyUTCOffsetTimezone((pos if signal == '+' else neg)(
(datetime.strptime(offset_no_signal, '%H:%M') - datetime(1900, 1, 1))
.total_seconds()))
def __init__(self, offset, name=None):
self.offset = timedelta(seconds=offset)
self.name = name or self.__class__.__name__
def utcoffset(self, dt):
return self.offset
def tzname(self, dt):
return self.name
def dst(self, dt):
return timedelta(0)
def to_datetime_tz(dt): # type: (str) -> datetime
fmt = '%Y-%m-%dT%H:%M:%S.%f'
if dt[-6] in frozenset(('+', '-')):
dt, sign, offset = strptime(dt[:-6], fmt), dt[-6], dt[-5:]
return datetime.fromtimestamp(mktime(dt),
tz=MyUTCOffsetTimezone.with_offset(offset, sign))
elif dt[-1] == 'Z':
return datetime.strptime(dt, fmt + 'Z')
return datetime.strptime(dt, fmt)
しかし、それは負のタイムゾーンでは機能しませんでした。ただし、これはPython 3.7.3では問題なく動作しました。
from datetime import datetime
def to_datetime_tz(dt): # type: (str) -> datetime
fmt = '%Y-%m-%dT%H:%M:%S.%f'
if dt[-6] in frozenset(('+', '-')):
return datetime.strptime(dt, fmt + '%z')
elif dt[-1] == 'Z':
return datetime.strptime(dt, fmt + 'Z')
return datetime.strptime(dt, fmt)
一部のテストでは、出力はマイクロ秒の精度でのみ異なることに注意してください。私のマシンでは6桁の精度を得ましたが、YMMV:
for dt_in, dt_out in (
('2019-03-11T08:00:00.000Z', '2019-03-11T08:00:00'),
('2019-03-11T08:00:00.000+11:00', '2019-03-11T08:00:00+11:00'),
('2019-03-11T08:00:00.000-11:00', '2019-03-11T08:00:00-11:00')
):
isoformat = to_datetime_tz(dt_in).isoformat()
assert isoformat == dt_out, '{} != {}'.format(isoformat, dt_out)
frozenset(('+', '-'))
?('+', '-')
同じことを達成できるような通常のタプルはありませんか?