Das ISO-Format des Python-UTC-Datetime-Objekts enthält kein Z (Zulu oder Zero offset)

Lesezeit: 8 Minuten

Benutzer-Avatar
Murali Mopuru

Warum enthält Python 2.7 im Gegensatz zu JavaScript kein Z-Zeichen (Zulu oder Null-Offset) am Ende der Isoformat-Zeichenfolge des UTC-Datetime-Objekts?

>>> datetime.datetime.utcnow().isoformat()
'2013-10-29T09:14:03.895210'

Während in Javascript

>>>  console.log(new Date().toISOString()); 
2013-10-29T09:38:41.341Z

  • Python-datetime-Werte haben KEINE Zeitzoneninformationen. Probieren Sie pytz oder Babel aus, wenn Sie Zeitzoneninformationen in Ihrem Zeitstempel speichern möchten.

    – tnknepp

    12. Dezember 2013 um 16:06 Uhr

  • datetime.datetime.utcnow().isoformat() + 'Z'

    – jfs

    17. Mai 2014 um 3:23 Uhr

  • Verwandte: Wie erhalte ich eine Datetime-Zeichenfolge im Isoformat einschließlich der Standardzeitzone?

    – jfs

    5. Oktober 2016 um 19:40 Uhr

  • ..und das fehlende Z führt überraschenderweise dazu, dass einige Dinge nicht funktionieren, zB API-Aufruf

    – Kardamom

    20. März 2017 um 15:32 Uhr

  • Es wird noch schlimmer, wenn der letzte Teil von datetime 0 ist, wird es abgeschnitten …

    – ntg

    25. Mai 2020 um 8:25 Uhr

Benutzer-Avatar
Manav Kataria

Möglichkeit: isoformat()

Pythons datetime unterstützt die nicht militärische Zeitzone Suffixe wie das Suffix „Z“ für UTC. Der folgende einfache String-Ersatz macht den Trick:

In [1]: import datetime

In [2]: d = datetime.datetime(2014, 12, 10, 12, 0, 0)

In [3]: str(d).replace('+00:00', 'Z')
Out[3]: '2014-12-10 12:00:00Z'

str(d) ist im Wesentlichen dasselbe wie d.isoformat(sep=' ')

Sehen: Datetime, Python-Standardbibliothek

Möglichkeit: strftime()

Oder Sie könnten verwenden strftime um den gleichen Effekt zu erzielen:

In [4]: d.strftime('%Y-%m-%dT%H:%M:%SZ')
Out[4]: '2014-12-10T12:00:00Z'

Hinweis: Diese Option funktioniert nur, wenn Sie wissen, dass das angegebene Datum in UTC ist.

Sehen: datetime.strftime()


Zusätzlich: Vom Menschen lesbare Zeitzone

Wenn Sie weiter gehen, könnten Sie daran interessiert sein, menschenlesbare Zeitzoneninformationen anzuzeigen, pytz mit strftime %Z Zeitzonenflagge:

In [5]: import pytz

In [6]: d = datetime.datetime(2014, 12, 10, 12, 0, 0, tzinfo=pytz.utc)

In [7]: d
Out[7]: datetime.datetime(2014, 12, 10, 12, 0, tzinfo=<UTC>)

In [8]: d.strftime('%Y-%m-%d %H:%M:%S %Z')
Out[8]: '2014-12-10 12:00:00 UTC'

  • Sollte das Trennzeichen nicht sein T statt Leerzeichen?

    – Marcello Romani

    30. März 2019 um 10:19 Uhr

  • es sollte sein d = datetime.datetime(2014, 12, 10, 12, 0, 0, tzinfo=datetime.timezone.utc) in Zeile 2. Btw., in RFC3339 es sagt, dass ein Leerzeichen ‘ok’ ist (anstelle des ‘T’).

    – FObersteiner

    9. Juni 2020 um 7:29 Uhr


Benutzer-Avatar
stiv

Python datetime Objekte haben standardmäßig keine Zeitzoneninformationen, und ohne sie verstößt Python tatsächlich gegen die ISO 8601-Spezifikation (Wenn keine Zeitzoneninformationen angegeben sind, wird die Ortszeit angenommen). Du kannst den … benutzen pytz-Paket um einige Standardzeitzonen zu erhalten, oder direkt eine Unterklasse tzinfo dich selbst:

from datetime import datetime, tzinfo, timedelta
class simple_utc(tzinfo):
    def tzname(self,**kwargs):
        return "UTC"
    def utcoffset(self, dt):
        return timedelta(0)

Dann können Sie die Zeitzoneninformationen manuell hinzufügen utcnow():

>>> datetime.utcnow().replace(tzinfo=simple_utc()).isoformat()
'2014-05-16T22:51:53.015001+00:00'

Beachten Sie, dass dies dem ISO 8601-Format entspricht, das beides zulässt Z oder +00:00 als Suffix für UTC. Beachten Sie, dass letzteres tatsächlich besser dem Standard entspricht, wie Zeitzonen im Allgemeinen dargestellt werden (UTC ist ein Sonderfall).

  • wie füge ich ein Z Anstatt von +00:00 ?

    – Leopard

    9. Februar 2017 um 23:32 Uhr

  • WARNUNG!!! pytz verstößt gegen Pythons tzinfo Protokoll und ist gefährlich zu verwenden! Sehen blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html

    – ivan_pozdeev

    10. Mai 2019 um 9:44 Uhr

  • @ivan_pozdeev Danke für den Link, sehr interessant. Beachten Sie, dass die Änderungen zulassen dateutil funktionieren, wurden sozusagen erst mit Python 3.6 mit PEP 495 implementiert pytz nicht die Standardschnittstelle verwendet haben, ist unfair, weil sich die Schnittstelle geändert hat. Vor der Änderung war der einzige Weg, es zum Laufen zu bringen, der Weg pytz geschafft.

    – Markieren Sie Lösegeld

    30. Oktober 2019 um 1:31 Uhr

Benutzer-Avatar
Clay Risser

Die folgenden Javascript- und Python-Skripte liefern identische Ausgaben. Ich denke, es ist das, wonach Sie suchen.

JavaScript

new Date().toISOString()

Python

from datetime import datetime

datetime.utcnow().isoformat()[:-3]+'Z'

Die Ausgabe, die sie geben, ist die UTC-Zeit (zulu), formatiert als ISO-String mit einer signifikanten Ziffer von 3 Millisekunden und angehängt mit einem Z.

2019-01-19T23:20:25.459Z

  • Doch wenn now() ist 0 Millisekunden, Minuten und : wird auch gestrippt.

    – Michail Murugow

    23. November 2020 um 14:00 Uhr

  • @МихаилМуругов beim Laufen .isoformat()erstellt es eine Zeichenfolge mit einer festen Anzahl von Zeichen einschließlich nachgestellter Nullen, sodass dies zuverlässig funktioniert

    – Peter VanderMeer

    19. Februar 2021 um 16:09 Uhr


  • @PeterVanderMeer datetime(2021, 2, 19, 23, 21, 15).isoformat() -> '2021-02-19T23:21:15', datetime(2021, 2, 19, 23, 21, 15, 256).isoformat() -> '2021-02-19T23:21:15.000256'. Unterschiedliche Darstellungen. Mein Fehler ist, dass ich über Minuten geschrieben habe, nicht über Sekunden.

    – Michail Murugow

    19. Februar 2021 um 16:27 Uhr

  • Mit Zeitzonenversatz müssen Sie verwenden [:-6]+'Z'.

    – Gringo Suave

    4. März 2021 um 2:53 Uhr

Benutzer-Avatar
Hochposten

Ihr Ziel sollte nicht das Hinzufügen eines Z-Zeichens sein, sondern das Generieren einer UTC-bewussten Datetime-Zeichenfolge im ISO 8601-Format. Die Lösung besteht darin, ein UTC-Zeitzonenobjekt an zu übergeben datetime.now() statt zu verwenden datetime.utcnow():

from datetime import datetime, timezone

datetime.now(timezone.utc)
>>> datetime.datetime(2020, 1, 8, 6, 6, 24, 260810, tzinfo=datetime.timezone.utc)

datetime.now(timezone.utc).isoformat()
>>> '2020-01-08T06:07:04.492045+00:00'

Dass sieht aus Gut, also mal sehen, was Django und dateutil denken:

from django.utils.timezone import is_aware
is_aware(datetime.now(timezone.utc))
>>> True

from dateutil.parser import isoparse
is_aware(isoparse(datetime.now(timezone.utc).isoformat()))
>>> True

Beachten Sie, dass Sie verwenden müssen isoparse() aus dateutil.parser weil die Python-Dokumentation für datetime.fromisoformat() sagt, dass es “das Parsen beliebiger ISO 8601-Zeichenfolgen nicht unterstützt”.

Okay, die Python datetime -Objekt und die ISO 8601-Zeichenfolge sind beide UTC “bewusst”. Sehen wir uns nun an, was JavaScript von der datetime-Zeichenfolge hält. In Anlehnung an diese Antwort erhalten wir:

let date="2020-01-08T06:07:04.492045+00:00";
const dateParsed = new Date(Date.parse(date))

document.write(dateParsed);
document.write("\n");
// Tue Jan 07 2020 22:07:04 GMT-0800 (Pacific Standard Time)

document.write(dateParsed.toISOString());
document.write("\n");
// 2020-01-08T06:07:04.492Z

document.write(dateParsed.toUTCString());
document.write("\n");
// Wed, 08 Jan 2020 06:07:04 GMT

Anmerkungen:

Ich bin dieses Problem mit ein paar Zielen angegangen:

  • Generieren Sie eine UTC “bewusste” Datetime-Zeichenfolge im ISO 8601-Format
  • verwenden nur Funktionen der Python-Standardbibliothek für die Erstellung von datetime-Objekten und Zeichenfolgen
  • validieren Sie das datetime-Objekt und die Zeichenfolge mit dem Django timezone Nutzenfunktion, die dateutil Parser- und JavaScript-Funktionen

Beachten Sie, dass dieser Ansatz nicht ein Z-Suffix und enthalten nicht verwenden utcnow(). Aber es basiert auf der Empfehlung in der Python-Dokumentation und es besteht die Musterung sowohl mit Django als auch mit JavaScript.

Siehe auch:

Benutzer-Avatar
Zacken

Kurze Antwort

datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")

Lange Antwort

Der Grund, warum das “Z” nicht enthalten ist, ist, weil datetime.now() und sogar datetime.utcnow() gibt zeitzonennaive Datetimes zurück, d. h. Datetimes ohne zugeordnete Zeitzoneninformationen. Um eine zeitzonenbewusste datetime zu erhalten, müssen Sie eine Zeitzone als Argument an übergeben datetime.now. Zum Beispiel:

from datetime import datetime, timezone

datetime.utcnow()
#> datetime.datetime(2020, 9, 3, 20, 58, 49, 22253)
# This is timezone naive

datetime.now(timezone.utc)
#> datetime.datetime(2020, 9, 3, 20, 58, 49, 22253, tzinfo=datetime.timezone.utc)
# This is timezone aware

Sobald Sie einen zeitzonenfähigen Zeitstempel haben, enthält das Isoformat eine Zeitzonenbezeichnung. So können Sie dann einen ISO 8601-Zeitstempel erhalten über:

datetime.now(timezone.utc).isoformat()
#> '2020-09-03T20:53:07.337670+00:00'

„+00:00“ ist eine gültige ISO 8601-Zeitzonenbezeichnung für UTC. Wenn Sie “Z” statt “+00:00” haben möchten, müssen Sie die Ersetzung selbst vornehmen:

datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
#> '2020-09-03T20:53:07.337670Z'

  • Ich mag diese Antwort, weil die meisten anderen entweder das Hinzufügen von a nicht demonstrieren Z, oder verwenden Sie naive datetime-Objekte. Ich habe das Gefühl, bewusste Objekte zu verwenden, ist der richtige Weg. Einmal sah ich den Unterschied zwischen datetime.utcnow().timestamp() und datetime.now(timezone.utc).timestamp() Ich beschloss zu versuchen, mich an bewusste Objekte zu halten.

    – Jason Capriotti

    17. April 2021 um 2:00 Uhr

  • Wenn Sie wirklich den in Javascript zurückgegebenen Wert abgleichen möchten, können Sie Folgendes tun: datetime.now(timezone.utc).isoformat(timespec='milliseconds').replace('+00:00', 'Z'). Es ist ein bisschen langatmig, aber vielleicht auch leicht zu lesen?

    – Jason Capriotti

    17. April 2021 um 2:07 Uhr

  • Ich denke, dies ist angesichts der API-Einschränkungen die beste Antwort, aber diese Bibliothek sollte wirklich eine Methode haben, um dies zu erreichen. Das manuelle Ersetzen von Saitenkomponenten für eine sehr häufige Operation fühlt sich spröde an und sollte unnötig sein.

    – Schweinetasche

    10. Oktober 2021 um 20:13 Uhr


Benutzer-Avatar
Michel Samia

In Python >= 3.2 können Sie einfach Folgendes verwenden:

>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc).isoformat()
'2019-03-14T07:55:36.979511+00:00'

  • Ich mag diese Antwort, weil die meisten anderen entweder das Hinzufügen von a nicht demonstrieren Z, oder verwenden Sie naive datetime-Objekte. Ich habe das Gefühl, bewusste Objekte zu verwenden, ist der richtige Weg. Einmal sah ich den Unterschied zwischen datetime.utcnow().timestamp() und datetime.now(timezone.utc).timestamp() Ich beschloss zu versuchen, mich an bewusste Objekte zu halten.

    – Jason Capriotti

    17. April 2021 um 2:00 Uhr

  • Wenn Sie wirklich den in Javascript zurückgegebenen Wert abgleichen möchten, können Sie Folgendes tun: datetime.now(timezone.utc).isoformat(timespec='milliseconds').replace('+00:00', 'Z'). Es ist ein bisschen langatmig, aber vielleicht auch leicht zu lesen?

    – Jason Capriotti

    17. April 2021 um 2:07 Uhr

  • Ich denke, dies ist angesichts der API-Einschränkungen die beste Antwort, aber diese Bibliothek sollte wirklich eine Methode haben, um dies zu erreichen. Das manuelle Ersetzen von Saitenkomponenten für eine sehr häufige Operation fühlt sich spröde an und sollte unnötig sein.

    – Schweinetasche

    10. Oktober 2021 um 20:13 Uhr


Benutzer-Avatar
Dima Tisnek

Python-Datetimes sind ein wenig klobig. Verwenden arrow.

> str(arrow.utcnow())
'2014-05-17T01:18:47.944126+00:00'

Arrow hat im Wesentlichen die gleiche API wie datetime, aber mit Zeitzonen und einigen zusätzlichen Feinheiten, die in der Hauptbibliothek enthalten sein sollten.

Ein mit Javascript kompatibles Format kann erreicht werden durch:

arrow.utcnow().isoformat().replace("+00:00", "Z")
'2018-11-30T02:46:40.714281Z'

Javascript Date.parse wird leise Mikrosekunden vom Zeitstempel entfernt.

  • Dies beantwortet die Frage nicht, da die Zeichenfolge nicht mit ‘Z’ endet.

    – kaleisin

    14. Juni 2018 um 8:26 Uhr

1048030cookie-checkDas ISO-Format des Python-UTC-Datetime-Objekts enthält kein Z (Zulu oder Zero offset)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy