Wie konvertiere ich eine zeitzonenabhängige Zeichenfolge in Python ohne Datumsangabe in Datum / Uhrzeit?

77

Ich muss eine zeitzonenbewusste Zeichenfolge wie "2012-11-01T04:16:13-04:00"in ein Python- datetimeObjekt konvertieren .

Ich habe das dateutilModul gesehen, das eine Analysefunktion hat, aber ich möchte es nicht wirklich verwenden, da es eine Abhängigkeit hinzufügt.

Wie kann ich das machen? Ich habe so etwas wie das Folgende versucht, aber ohne Glück.

datetime.datetime.strptime("2012-11-01T04:16:13-04:00", "%Y-%m-%dT%H:%M:%S%Z")
lxyu
quelle
2
Was ist falsch daran, eine Abhängigkeit hinzuzufügen, wenn diese Abhängigkeit genau Ihren Anforderungen entspricht? Wenn die gleichen Ergebnisse ohne das zusätzliche Modul erzielt werden könnten, gäbe es sicherlich keinen Grund, warum das Modul überhaupt existieren würde, oder? Wie schwer fällt es Ihnen, eine Abhängigkeit hinzuzufügen?
Jon Skeet
Ich denke, es ist vielleicht ein persönlicher Gefallen? Ich möchte nicht wirklich ein ganzes großes Modul in das Projekt einführen, da ich nur eine winzige einzelne Funktion benötige.
lxyu
2
Was sind die konkreten Kosten für das Hinzufügen einer Abhängigkeit zu Ihrem Projekt im Vergleich zu den Kosten für das Verstehen Ihres Codes, als es sein muss ? Ignorieren Sie die Tatsache, dass Sie derzeit nur eine einzige Funktion benötigen - konzentrieren Sie sich auf die Kosten.
Jon Skeet

Antworten:

86

Ab Python 3.7 datetime.datetime.fromisoformat()können Sie Ihr Format verarbeiten:

>>> import datetime
>>> datetime.datetime.fromisoformat('2012-11-01T04:16:13-04:00')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000)))

In älteren Python-Versionen ist dies nicht möglich, nicht ohne eine Menge sorgfältiger manueller Zeitzonendefinitionen.

Python enthält keine Zeitzonendatenbank, da diese zu schnell veraltet wäre. Stattdessen stützt sich Python auf externe Bibliotheken, die einen weitaus schnelleren Veröffentlichungszyklus haben können, um ordnungsgemäß konfigurierte Zeitzonen für Sie bereitzustellen.

Als Nebeneffekt bedeutet dies, dass das Parsen der Zeitzone auch eine externe Bibliothek sein muss. Wenn dateutiles Ihnen zu schwer ist, verwenden Sie es iso8601stattdessen. Es analysiert Ihr spezifisches Format einwandfrei:

>>> import iso8601
>>> iso8601.parse_date('2012-11-01T04:16:13-04:00')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=<FixedOffset '-04:00'>)

iso8601ist satte 4KB klein. Vergleichen Sie die python-dateutil148 KB dieses Tot.

Ab Python 3.2 kann Python einfache Offset-basierte Zeitzonen verarbeiten und %zanalysiert -hhmmund +hhmmZeitzonen-Offsets in einem Zeitstempel. Das bedeutet, dass Sie für einen ISO 8601-Zeitstempel Folgendes :in der Zeitzone entfernen müssen :

>>> from datetime import datetime
>>> iso_ts = '2012-11-01T04:16:13-04:00'
>>> datetime.strptime(''.join(iso_ts.rsplit(':', 1)), '%Y-%m-%dT%H:%M:%S%z')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000)))

Das Fehlen einer ordnungsgemäßen ISO 8601-Analyse wird in der Python-Ausgabe 15873 verfolgt .

Martijn Pieters
quelle
Es scheint mir datetime, dass es so etwas wie iso8601ISO 8601-Zeitzonen geben könnte - ein bisschen Parsen und zwei tzinfoUnterklassen.
Eryk Sun
@eryksun: ISO8601 ist in Bezug auf Zeitzonen sehr simpel, aber sobald Sie diese Offsets in die Python-Stdlib aufnehmen, werden Sie von Missverständnissen überflutet, warum reale Zeitzonen (die mehr als nur ein Offset sind) nicht funktionieren usw.
Martijn Pieters
1
Es ist nicht so schmerzhaft, eine FixedOffset Klasse zu definieren . Hier ist ein Codebeispiel
jfs
46

Hier ist das Python Doc für datetime-Objekt mit dem dateutil-Paket.

from dateutil.parser import parse

get_date_obj = parse("2012-11-01T04:16:13-04:00")
print get_date_obj
Mohideen bin Mohammed
quelle
5
Dies soll die richtige Antwort sein, um dies ohne externe Bibliothek zu tun
Paullo
6
@Paullo Python-Dateutil ist genau "externe Bibliothek".
Der Pate
12

Es gibt zwei Probleme mit dem Code in der ursprünglichen Frage: Es sollte keine :in der Zeitzone geben und die Formatzeichenfolge für "Zeitzone als Versatz" ist Kleinbuchstaben, %znicht Großbuchstaben %Z.

Dies funktioniert für mich in Python v3.6

>>> from datetime import datetime
>>> t = datetime.strptime("2012-11-01T04:16:13-0400", "%Y-%m-%dT%H:%M:%S%z")
>>> print(t)
2012-11-01 04:16:13-04:00
Jamie Czuy
quelle
Wenn es falsch ist, warum print(t)fügt der Doppelpunkt dem utc-Offset hinzu?
Moooeeeep
@moooeeeep Da standardmäßig Datetime verwendet die isoformat(sep=' ')für die __str__Funktion , die die UTC als Offsetdrucke „+ HH: MM“. Die Verwendung print(t.strftime("%Y-%m-%dT%H:%M:%S%z"))wird ohne das ":" in der Zeitzone gedruckt.
Jamie Czuy
3
Ein Doppelpunkt in der Zeitzone ist nicht falsch. Viele Quellen präsentieren ihre Zeit in Zeichenfolgenform : 2012-11-01T04:16:13-04:00. OP versucht, diese Form zu analysieren.
DaveL17
2

Sie können so konvertieren.

date = datetime.datetime.strptime('2019-3-16T5-49-52-595Z','%Y-%m-%dT%H-%M-%S-%f%z')
date_time = date.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
Muruganandam C.
quelle
1

Ich bin neu in Python, habe aber einen Weg gefunden, um zu konvertieren

2017-05-27T07:20:18.000-04:00 zu

2017-05-27T07:20:18 ohne neue Dienstprogramme herunterzuladen.

from datetime import datetime, timedelta

time_zone1 = int("2017-05-27T07:20:18.000-04:00"[-6:][:3])
>>returns -04

item_date = datetime.strptime("2017-05-27T07:20:18.000-04:00".replace(".000", "")[:-6], "%Y-%m-%dT%H:%M:%S") + timedelta(hours=-time_zone1)

Ich bin mir sicher, dass es bessere Möglichkeiten gibt, dies zu tun, ohne die Saite so stark zu zerschneiden, aber das hat den Job erledigt.

Wiseco68
quelle