[python] ISO 8601 형식의 날짜를 어떻게 구문 분석합니까?

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 3.7+의 새로운 기능


datetime표준 라이브러리 반전하는 기능을 도입 datetime.isoformat().

classmethod datetime.fromisoformat(date_string):

및에서 방출되는 형식 중 하나에서에 datetime해당 하는를 반환합니다 .date_stringdate.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')


답변

Python 2.6 이상 및 Py3K에서 % f 문자는 마이크로 초를 포착합니다.

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

여기에서 이슈를 보십시오


답변

여기에 몇 가지 대답 은 질문에 표시된 것과 같이 시간대로 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 .)

여기에 여러 답변 strptimeZ형식 문자열에 리터럴을 포함 하여이 문제를 해결 하는 것이 좋습니다 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. 대신 답변에 설명 된 다른 많은 접근법 중 하나를 사용하십시오.


답변

iso8601 모듈을 사용해보십시오 . 정확히이 작업을 수행합니다.

python.org 위키 의 WorkingWithTime 페이지에 언급 된 몇 가지 다른 옵션이 있습니다 .


답변

다시 가져 오기, 날짜
s = "2008-09-03T20 : 56 : 35.450686Z"
d = datetime.datetime (* map (int, re.split ( '[^ \ d]', s) [:-1]))


답변

당신이 얻는 정확한 오류는 무엇입니까? 다음과 같은가요?

>>> 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)