Da ISO 8601 viele Variationen von optionalen Doppelpunkten und Bindestrichen zulässt, gilt grundsätzlich CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
. Wenn Sie strptime verwenden wollen, müssen Sie diese Variationen zuerst entfernen.
Das Ziel ist es, ein UTC-Datetime-Objekt zu erzeugen.
Wenn Sie nur einen einfachen Fall wollen, der für UTC mit dem Suffix Z funktioniert, wie 2016-06-29T19:36:29.3453Z
:
datetime.datetime.strptime(timestamp.translate(None, ':-'), "%Y%m%dT%H%M%S.%fZ")
Wenn Sie Zeitzonenverschiebungen behandeln wollen wie 2016-06-29T19:36:29.3453-0400
o 2008-09-03T20:56:35.450686+05:00
verwenden Sie das Folgende. Diese konvertieren alle Variationen in etwas ohne variable Begrenzungszeichen wie 20080903T205635.450686+0500
wodurch sie konsistenter/leichter zu analysieren sind.
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" )
Wenn Ihr System die Funktion nicht unterstützt %z
strptime-Richtlinie (Sie sehen etwas wie ValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z'
), dann müssen Sie die Zeit manuell von Z
(UTC). Hinweis %z
könnte auf Ihrem System in Python-Versionen < 3 nicht funktionieren, da es von der Unterstützung der C-Bibliothek abhängt, die je nach System/Python-Build-Typ variiert (d.h., Jython , Cython , usw.).
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
28 Stimmen
Es ist zu bedenken, dass es sich nicht um ziemlich ein Duplikat des Problems, gegen das es geschlossen wurde. Das verlinkte Problem bezieht sich speziell auf RFC 3339 Zeichenketten, während diese sich auf ISO 8601-Zeichenketten bezieht. Die RFC 3339-Syntax ist eine Untermenge der ISO 8601-Syntax (die in der nicht kostenlosen ISO 8601-Norm definiert ist, die Sie, wie die meisten ISO-Normen, entweder raubkopieren oder eine hohe Gebühr bezahlen müssen, um sie zu lesen). Der in dieser Frage gezeigte Datumsstring ist ein ISO 8601 Datumsstring, aber KEIN RFC 3339 Datumsstring. UTC-Offsets sind in RFC 3339-Datetimes obligatorisch, und hier ist keiner vorgesehen.