RFC 3339 문자열 "2008-09-03T20:56:35.450686Z"
을 Python datetime
유형 으로 구문 분석해야 합니다.
strptime
파이썬 표준 라이브러리에서 찾았 지만 그리 편리하지는 않습니다.
가장 좋은 방법은 무엇입니까?
RFC 3339 문자열 "2008-09-03T20:56:35.450686Z"
을 Python datetime
유형 으로 구문 분석해야 합니다.
strptime
파이썬 표준 라이브러리에서 찾았 지만 그리 편리하지는 않습니다.
가장 좋은 방법은 무엇입니까?
답변:
파이썬 dateutil 패키지는 문제의 하나처럼뿐만 아니라 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
(감사합니다 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)
:및에서 방출되는 형식 중 하나에서에
datetime
해당 하는를 반환합니다 .date_string
date.isoformat()
datetime.isoformat()
특히이 함수는 다음 형식으로 문자열을 지원합니다.
YYYY-MM-DD[*HH[:MM[:SS[.mmm[mmm]]]][+HH:MM[:SS[.ffffff]]]]
여기서
*
하나의 문자를 일치시킬 수 있습니다.주의 : 이것은 임의의 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
이것은 나쁜 생각입니다.
0이 아닌 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
아아, 형식 문자열에 사용 strptime
하고 strftime
어떤 지침이 없다는 RFC 3339 형식의 UTC 오프셋에 해당합니다. 지원하는 지시문의 전체 목록은 https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior 에서 찾을 수 있으며 목록에 포함 된 유일한 UTC 오프셋 지시문은 %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에서 볼 수있는 내용입니다. Python 2에서는 더 간단한 이유로 실패합니다. 즉, 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 오프셋을 형식 문자열로 하드 코딩하는 것이 포함되므로 RFC 3339 날짜 시간을 다른 UTC 오프셋으로 구문 분석하려고하는 순간을 질식시킵니다.
>>> 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에게 다른 시간대 오프셋 (offset) 3339 줄루 시간에서 날짜 시간, 그리고 사람들을 지원하는 데 필요한 사용하지 마십시오 strptime
. 대신 답변에 설명 된 다른 많은 접근법 중 하나를 사용하십시오.
strptime()
Python 3.7에서는 이제이 답변에서 불가능하다고 설명 된 모든 것을 지원합니다 (표준 시간대 오프셋의 'Z'리터럴 및 ':'). 불행히도 RFC 3339가 ISO 8601과 근본적으로 호환되지 않는 또 다른 코너 케이스가 있습니다. 즉, 전자는 음의 null 시간대 오프셋 -00 : 00을 허용하고 나중에는 그렇지 않습니다.
iso8601 모듈을 사용해보십시오 . 정확히이 작업을 수행합니다.
python.org 위키 의 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"
시간 / 분 단위의 오프셋이어야하며 날짜 / 시간 객체에서 직접 추가 / 빼기 할 수 있습니다. 당신은 수 를 처리하는 서브 클래스 tzinfo을 만들 수 있지만, 아마도 reccomended 아니에요.
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())
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 오프셋으로 날짜 시간을 구문 분석하고 예외를 발생시키지 않기 때문에 나쁜 생각입니다. strptime으로 RFC 3339를 구문 분석하는 것이 실제로 불가능한 방법을 설명하는 내 대답 을 참조하십시오 .
toISOString
메소드 로 생성 된 것을 알고있는 경우에 해당 될 수 있습니다 . 그러나이 답변에 Zulu 시간 날짜에 대한 제한에 대한 언급은 없으며, 그것이 필요한 전부이며, 사용하는 dateutil
것이 일반적으로 똑같이 편리하고 구문 분석 할 수있는 범위가 좁다 는 질문도 나타내지 않았습니다 .
Django로 작업하는 경우 시간대를 포함하여 ISO 형식과 유사한 여러 형식을 허용하는 dateparse 모듈 을 제공합니다 .
Django를 사용하지 않고 여기에 언급 된 다른 라이브러리 중 하나를 사용하지 않으려는 경우 프로젝트 에 날짜 분석 용 Django 소스 코드를 적용 할 수 있습니다.
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에 병합해야 할 보다 완전한 파서 목록에 관심이 있을 것 입니다.
이것은 파이썬 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 오프셋으로 날짜 시간을 구문 분석하고 예외를 발생시키지 않기 때문에 나쁜 생각입니다. strptime으로 RFC 3339를 구문 분석하는 것이 실제로 불가능한 방법을 설명하는 내 대답 을 참조하십시오 .
%Z
최신 버전의 Python에서 시간대를 사용할 수 있습니다 .
datetime.datetime
타사 모듈을 설치하지 않고 지원되는 모든 Python 버전에서 ISO 8601과 같은 날짜 문자열을 UNIX 타임 스탬프 또는 객체 로 변환하는 간단한 방법 중 하나 는 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의 datetime 모듈의 지원되는 날짜 범위를 벗어난 날짜를 제외하고 사양의 모든 것을 지원합니다.
시험이 포함되어 있습니다! :피
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
파이썬 버전의 <당신의 시스템에서 작동하지 않을 수 있습니다 3은 시스템 / 파이썬 빌드 형식 (예 : 자이 썬, 사이 썬 등)에 걸쳐 다양 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은 time.mktime의 누락 된 gm 버전입니다.
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
이 함수는 표준 파이썬 함수 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(('+', '-'))
될까요? 정상적인 튜플이 같은 ('+', '-')
것을 성취 할 수 없어야 합니까?