Formatieren Sie das Datum in einer bestimmten Zeitzone

177

Ich verwende Moment.js , um Daten in meiner Web-App zu analysieren und zu formatieren. Als Teil eines JSON-Objekts sendet mein Backend-Server Daten in Millisekunden ab der UTC-Epoche (Unix-Offset).

Das Parsen von Daten in einer bestimmten Zeitzone ist einfach. Fügen Sie vor dem Parsen einfach die RFC 822-Zeitzonen-ID an das Ende der Zeichenfolge an:

// response varies according to your timezone
const m1 = moment('3/11/2012 13:00').utc().format("MM/DD HH:mm")

// problem solved, always "03/11 17:00"
const m2 = moment('3/11/2012 13:00 -0400').utc().format("MM/DD HH:mm")

console.log({ m1, m2 })
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

Aber wie formatiere ich ein Datum in einer bestimmten Zeitzone ?

Ich möchte konsistente Ergebnisse unabhängig von der aktuellen Uhrzeit des Browsers, aber ich möchte keine Daten in UTC anzeigen.

quietmint
quelle
2
Moment unterstützt dies noch nicht, aber sie arbeiten daran. github.com/timrwood/moment/pull/671
Ben
5
Das sollte einfach funktionieren. Wenn Sie eine Zeitzeichenfolge übergeben, die den gewünschten Versatz enthält, sollte dieser Versatz beibehalten und die Ortszeit wie angegeben angezeigt werden, anstatt sich automatisch an die lokale Zeit des Browsers anzupassen. Wenn ich wollte, dass es sich an die lokale Zeit des Browsers anpasst, würde ich ihm eine UTC-Zeit geben, anstatt ihm explizit einen Offset zur Verwendung zu geben. Ich meine ... ich gebe ihm einen expliziten Offset, warum frisst es es im Grunde auf und macht seine eigene Konvertierung in den Offset des Browsers. Schreckliches Design.
Triynko
@Triynko-Offsets unterliegen der Sommerzeit, sodass sie nicht immer wie erwartet funktionieren.
Pinkpanther
1
In diesem Zusammenhang möchte ich die Zeit in einem bestimmten Format drucken, z. B. am 15. März 2018, aber ich kann die Formatzeichenfolge dafür nicht finden. Das Generikum DD MMM, YYYYfunktioniert nicht, wenn ich es gerne benutze moment.tz("2018-02-15T14:20:00.000+0530", "Asia/Bangkok").format("DD MMM, YYYY"). Kann mich jemand in der Dokumentation darauf hinweisen, wo ich bei Verwendung dieser API alle Schlüssel für die Formatierungszeit finden kann?
PRMDK
@PramodKumar Was ist los? Das gibt "15 Feb, 2018". Wollten Sie Formatzeichenfolge verwenden DD MMMM, YYYY, um zu erhalten "15 February, 2018"?
quietmint

Antworten:

248

Wie in Mantos Antwort ausgeführt , .utcOffset()ist dies ab Moment 2.9.0 die bevorzugte Methode. Diese Funktion verwendet den realen Versatz von UTC, nicht den umgekehrten Versatz (z. B. -240 für New York während der Sommerzeit). Versetzte Zeichenfolgen wie "+0400" funktionieren wie zuvor:

// always "2013-05-23 00:55"
moment(1369266934311).utcOffset(60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).utcOffset('+0100').format('YYYY-MM-DD HH:mm')

Der Ältere .zone()als Setter war in Moment.js 2.9.0 veraltet . Es wurde eine Zeichenfolge akzeptiert, die eine Zeitzonen-ID (z. B. "-0400" oder "-04: 00" für -4 Stunden) oder eine Zahl enthält, die Minuten hinter UTC darstellt (z. B. 240 für New York während der Sommerzeit).

// always "2013-05-23 00:55"
moment(1369266934311).zone(-60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).zone('+0100').format('YYYY-MM-DD HH:mm')

Um mit benannten Zeitzonen anstelle von numerischen Offsets zu arbeiten, schließen Sie Moment Timezone ein und verwenden Sie .tz()stattdessen:

// determines the correct offset for America/Phoenix at the given moment
// always "2013-05-22 16:55"
moment(1369266934311).tz('America/Phoenix').format('YYYY-MM-DD HH:mm')
quietmint
quelle
Ich hatte Probleme damit über einen Fehler "TypeError: Object 240 hat keine Methode 'format' '. Ich habe festgestellt, dass zone nur als Setter in Version 2.1.0 und höher von Moment.js verfügbar ist (und ich war in einer älteren Version). Vielen Dank!
Melinda Weathers
5
@ebi Standardmäßig wird bereits die Zeitzone des Browsers verwendet. Um auf den Zeitzonenversatz des Browsers zuzugreifen , verwenden Sie ihn .zone()als Getter, der Minuten von UTC zurückgibt (z. B. 300 für New York während der Standardzeit).
quietmint
1
@EricCope Nein, nicht ganz. Sie können es jedoch auch verwenden, .tz("America/Phoenix")wenn Sie momentjs.com/timezone angeben . Ich habe die Antwort mit einem Beispiel aktualisiert.
quietmint
1
Beachten Sie, dass die Verwendung des Versatzes nicht wie erwartet funktioniert, wenn die Zeitzone aufgrund der Sommerzeit unterschiedliche Versätze aufweist.
Pinkpanther
1
Verwaltet .utcOffset () automatisch die Sommerzeit? Wenn ich im Winter UTC +1 MEZ einstelle, wird UTC +2 MESZ während der Sommerzeit gesetzt? Weil dies es nutzbar macht oder nicht!
Haemse
61

Verwenden Sie die Moment-Zeitzone

moment(date).tz('Europe/Berlin').format(format)

Bevor Sie auf eine bestimmte Zeitzone zugreifen können, müssen Sie sie wie folgt laden (oder alternative Methoden verwenden, die hier beschrieben werden ).

moment.tz.add('Europe/Berlin|CET CEST CEMT|-10 -20 -30')
Philip Nuzhnyy
quelle
Ich glaube nicht, dass der Moment verfügbar war, als die Frage gestellt wurde, aber ich denke, dass dies der richtige Weg sein könnte. Ich arbeite derzeit an einem ähnlichen Problem mit allen Zeitstempeln, die in MySQL als UTC gespeichert sind, aber in einer bestimmten Zone angezeigt werden sollen, abhängig von der Benutzerkonfiguration und nicht von der Zeitzone des Clients.
Nickdnk
46

In einigen Antworten wird bereits erwähnt, dass die Moment-Zeitzone der richtige Weg für die benannte Zeitzone ist. Ich möchte nur etwas über diese Bibliothek klarstellen, das für mich ziemlich verwirrend war. Es gibt einen Unterschied zwischen diesen beiden Aussagen:

moment.tz(date, format, timezone)

moment(date, format).tz(timezone)

Angenommen, in dem übergebenen Datum ist keine Zeitzone angegeben:

Der erste Code nimmt das Datum auf und nimmt an, dass die Zeitzone die übergebene ist. Der zweite Code nimmt das Datum an, übernimmt die Zeitzone vom Browser und ändert dann die Zeit und die Zeitzone entsprechend der übergebenen Zeitzone.

Beispiel:

moment.tz('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss', 'UTC').format() // "2018-07-17T19:00:00Z"

moment('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss').tz('UTC').format() // "2018-07-18T00:00:00Z"

Meine Zeitzone ist +5 von utc. Im ersten Fall ändert es sich also nicht und legt Datum und Uhrzeit für die utc-Zeitzone fest.

Im zweiten Fall wird davon ausgegangen, dass das übergebene Datum in -5 liegt, und dann in UTC umgewandelt. Deshalb wird das Datum "2018-07-18T00: 00: 00Z" ausgespuckt.

HINWEIS: Der Formatparameter ist sehr wichtig. Wenn der Moment weggelassen wird, kann er auf die Date-Klasse zurückgreifen, was zu unvorhersehbaren Verhaltensweisen führen kann


Angenommen, die Zeitzone wird in dem Datum angegeben, an dem Folgendes übergeben wurde:

In diesem Fall verhalten sich beide gleich


Obwohl ich jetzt verstehe, warum es so funktioniert, fand ich das ziemlich verwirrend und erklärenswert.

Nicola Pedretti
quelle
1
Moment (...). tz ist keine Funktion
K - Die Toxizität in SO wächst.
5
Haben Sie moment-timezone installiert?
Nicola Pedretti
Gibt es eine Möglichkeit, den analysierten und konvertierten Moment ohne Formatierung zurückzugewinnen? Zum Beispiel, wenn ich verschiedene Methoden formatieren möchte, ohne sie erneut zu analysieren.
jEremyB
Vielen Dank, dass Sie dies geklärt haben. Ich hatte Probleme beim Einstellen einer anderen Zeitzone als der Browser-Zeitzone des Benutzers, und dies war genau das Problem.
Robin Schaaf
20

.zone () ist veraltet und Sie sollten stattdessen utcOffset verwenden:

// for a timezone that is +7 UTC hours
moment(1369266934311).utcOffset(420).format('YYYY-MM-DD HH:mm')
Manto
quelle
8

Ich hatte das gleiche Problem mit Moment.js. Ich habe moment-timezone installiert, aber das Problem wurde nicht behoben. Dann habe ich genau das getan, was hier gezeigt wird, die Zeitzone eingestellt und es funktioniert wie ein Zauber:

moment(new Date({your_date})).zone("+08:00")

Vielen Dank!

facundofarias
quelle
16
Sie sollten den new Date()Konstruktor nicht verwenden . Moment bietet alles, was Sie jemals brauchen würden, um Daten zu analysieren. Siehe Analysieren von Dokumenten.
quietmint
Ja, aber wenn ich das nicht tue,
erhalte
7
Die Warnung bedeutet, dass Moment intern auf genau das zurückgreift, was Sie tun ( new Date()intern verwenden), dies ist jedoch in allen Browsern inkonsistent . Verwenden Sie stattdessen das erwartete Format als zweites Argument. Beispiel : moment("12-25-1995", "MM-DD-YYYY").
quietmint
4

Ich bin gerade dazu gekommen, und da ich das gleiche Problem hatte, habe ich nur die Ergebnisse veröffentlicht, die ich mir ausgedacht habe

Beim Parsen können Sie den Offset aktualisieren (dh ich analysiere Daten (1.1.2014) und ich möchte nur das Datum, den 1. Januar 2014. Bei GMT + 1 würde ich den 31.12.2013 erhalten. Also versetze ich zuerst den Wert.

moment(moment.utc('1.1.2014').format());

Nun, es hat sich für mich als nützlich erwiesen, über Zeitzonen hinweg zu unterstützen

B.

Bard Rotzer
quelle
-7

Sie können dies versuchen,

Hier können Sie das Datum basierend auf der Client-Zeitzone (Browser) abrufen.

moment(new Date().getTime()).zone(new Date().toString().match(/([-\+][0-9]+)\s/)[1]).format('YYYY-MM-DD HH:mm:ss')

Mit dem regulären Ausdruck erhalten Sie im Grunde den Versatzwert.

Prost!!

K.Karthik
quelle
Normalerweise gibt Ihnen der Moment alles, was Sie brauchen. Sie müssen nie etwas Benutzerdefiniertes finden.
Mahesh Samudra