Mit Zeitzonen in Javascript arbeiten

Ursprünglicher Autor: TOAST UI
  • Übersetzung


Vor kurzem arbeitete ich daran, Zeitzonen in die Kalender-JS-Bibliothek aufzunehmen, die mein Team leitet. Ich war mir der nutzlosen Unterstützung für Zeitzonen in JavaScript sehr wohl bewusst, aber ich hoffte, dass durch das Abstrahieren vorhandener Datenobjekte die meisten Schwierigkeiten leicht gelöst werden könnten.

Meine Träume waren jedoch ruiniert. Als ich mich mit der Aufgabe beschäftigte, wurde mir klar, dass es in dieser Sprache wirklich schwierig ist, mit Zeitzonen zu arbeiten. Etwas schwieriger zu implementieren, als die Zeitanzeige einfach zu formatieren und das Datum mit komplexen Vorgängen (Kalenderfunktionen) zu berechnen, war äußerst schwierig. Ich habe wertvolle Erfahrungen bei der Lösung dieses Problems gesammelt und dies brachte neue Schwierigkeiten mit sich.

In diesem Artikel möchte ich besprechen, was mir begegnet ist und wie ich es gelöst habe. Während ich den Text schrieb, wurde mir klar, dass die Ursache aller Widrigkeiten mein schlechtes Verständnis des Themas von Zeitzonen war. In Anbetracht dieses Bewusstseins schlage ich vor, zunächst ausführlich über die Definition und die Standards zu sprechen, und erst dann zu JavaScript überzugehen.

Was ist die Zeitzone?


Die Zeitzone ist eine geographische Region, in der die einheitliche Ortszeit verwendet wird, die von der Regierung des Landes festgelegt wird. Viele Länder gehören ganz bestimmten Zeitzonen an, und in den Territorien großer Staaten wie Russland und den USA werden mehrere Zeitzonen verwendet. Es ist merkwürdig, dass China zwar auch recht groß ist, jedoch nur eine Zeitzone einnahm. Manchmal führt dies zu merkwürdigen Situationen, wenn der Sonnenaufgang um 10 Uhr morgens im Westen des Landes beginnt.

GMT, UTC und Offset


GMT


Die lokale südkoreanische Zeit wird als bezeichnet GMT+09:00. GMT steht für Greenwich Mean Time (Greenwich Mean Time), dh diesmal auf der Uhr des Royal Observatory in Greenwich, Großbritannien. Es befindet sich auf dem Nullmeridian. Das Funksignal des GMT-Systems begann am 5. Februar 1924 zu senden und wurde selbst am 1. Januar 1972 zum Weltstandard.

UTC


Viele Leute glauben, dass GMT und UTC ein und dasselbe sind und sie oft als austauschbare Systeme verwenden. Das ist aber ein Fehler. Das UTC-System erschien 1972, um die Auswirkungen der Erdrotation zu kompensieren. Das System basiert auf der Internationalen Atomzeit (International Atomic Time), berechnet aus der Frequenz der elektromagnetischen Schwingungen von Cäsiumatomen. Mit anderen Worten, UTC ist ein genauerer Ersatz für GMT. Obwohl der Echtzeitunterschied zwischen den beiden Systemen sehr gering ist, ist es für Softwareentwickler immer noch besser, sich auf UTC zu verlassen.

Eine interessante Tatsache: Als sich UTC noch in der Entwicklung befand, wurde in englischsprachigen Ländern vorgeschlagen, CUT (Coordinated Universal Time) und in französischsprachigen Ländern TUC (Temps Universal Coordonn) zu nennen. Keines der Lager konnte jedoch gewinnen, und das System erklärte sich bereit, UTC per Brief der beiden vorgeschlagenen Optionen (C, T und U) anzurufen.

Versatz


+09:00UTC+09:00bedeuten , dass die Ortszeit 9 Stunden vor dem UTC-Zeit Standard ist. Das heißt, wenn in Südkorea 21 Uhr, in der UTC-Region Mittag. Der Unterschied zwischen Standardzeit und UTC-local „Offset“ genannt, was als positive oder negative Werte ausgedrückt: +09:00, -03:00etc ...

In vielen Ländern ist es akzeptiert , ihre Zeitzonen eindeutige Namen zu geben. Die Zeitzone Südkoreas heißt beispielsweise KST (Korea Standard Time), ihr Versatz wird als ausgedrückt KST = UTC+09:00. Die Verschiebung wird +09:00jedoch nicht nur von Südkorea verwendet, sondern auch von Japan, Indonesien und vielen anderen Ländern. Daher wird die Verbindung zwischen Verschiebung und Riemen nicht 1: 1, sondern 1: 1 ausgedrückt. Die Liste der Länder mit Versatz +09:00wird hier dargestellt .

Einige Offsets funktionieren nicht nur auf der Uhr. Zum Beispiel in Nordkorea ist es eine Standardzeit +08:30, und in Australien ist in einigen Regionen verwendet +8:45, +09:30und +10:30.

Die vollständige Liste der UTC-Offsets finden Sie hier .

Zeitzone! == Versatz?


Wie gesagt, verwenden wir Zeitzonenbezeichnungen (KST, JST), deren Verschiebungen austauschbar sind und nicht voneinander unterschieden werden. Es ist jedoch falsch, die gleiche Zeit und die Verschiebung einer bestimmten Region anzunehmen. Dafür gibt es mehrere Gründe:

Sommerzeit (DST)


In einigen Ländern ist dieser Begriff unbekannt, aber in vielen Staaten gibt es Sommerzeit, hauptsächlich in Europa. Dafür wird der internationale Begriff DST (Sommerzeit) verwendet. Dies bedeutet, dass Stunden im Sommer um eine Stunde vor der relativen Standardzeit übertragen werden.

Beispielsweise wird in Kalifornien im Winter PST (Pacific Standard Time) und im Sommer PDT (Pacific Daylight Time UTC-07:00) verwendet. In den Vereinigten Staaten und Kanada wird der Begriff Pacific Time (PT, Pacific Time) für Regionen verwendet, die zwei Zeitzonen verwenden.

Wann beginnt und endet die Sommerzeit? Es hängt alles vom Land ab. Beispielsweise wurde in den Vereinigten Staaten und Kanada bis 2006 DST am ersten Sonntag im April von 2 bis 12 Uhr am letzten Sonntag im Oktober verwendet. Ab 2007 begann die Sommerzeit am zweiten Sonntag im März von 2 bis 2 Uhr am ersten Sonntag im November. In Europa wird DST in verschiedenen Ländern je nach Zeitzone schrittweise eingesetzt.

Ändern sich die Zeitzonen?


Jedes Land legt für sich selbst fest, welche Zeitzonen verwendet werden sollen, daher kann die Ortszeit aus politischen und / oder wirtschaftlichen Gründen variieren. In den USA wurden beispielsweise die DST-Grenzen im Jahr 2007 geändert, da George Bush 2005 eine Energiepolitik initiierte. Ägypten und Russland wechselten früher in die Sommerzeit, lehnten dies jedoch ab 2011 ab.

In einigen Fällen kann die Regierung nicht nur die Reihenfolge der Sommerzeit, sondern auch die Standardzeit ändern. Zum Beispiel wurde früher auf Samoa ein Offset verwendet UTC-10:00, der jedoch UTC+14:00aufgrund von Zeitunterschieden zu Australien und Neuseeland die Verluste im Handel reduzierte. Diese Entscheidung führte zum Verlust des ganzen Tages aus dem Leben des Landes - dem 30. Dezember 2011, über das Zeitungen in der ganzen Welt geschrieben haben .

In den Niederlanden wurde die Verschiebung seit 1909 angewandt +0:19:32.13, seit 1937 ist das Land umgezogen +00:20, und von 1940 bis +01:00seitdem hat sich die meiste Zeit dort nicht verändert.

Zeitzone 1: N Offset


Die Zeitzone kann also einen oder mehrere Offsets haben. Welche Zeit als Standard genommen wird, hängt von den aktuellen politischen und / oder wirtschaftlichen Gründen in einem bestimmten Land ab.

Dies verursacht im Alltag keine Schwierigkeiten, bis Sie versuchen, diese Daten anhand einiger Regeln zu systematisieren. Stellen Sie sich vor, Sie möchten mit einem Offset eine Standardzeit auf Ihrem Smartphone einstellen. Wenn Sie in einer Region leben, in der die Sommerzeit praktiziert wird, sollte das Smartphone genau wissen, wann es hin und her gehen soll. Das heißt, Sie müssen die Beziehung zwischen Standard- und Sommerzeit in derselben Zeitzone (z. B. Pacific Time) festlegen.

Dies ist jedoch nicht mit ein paar einfachen Regeln möglich. Als beispielsweise Anfang und Ende der Sommerzeit in den USA im Jahr 2007 geändert wurden, sollte der 31. Mai 2006 PDT ( -07:00) als Standardzeit und der 31. März 2007 - PST ( -08:00) verwenden. Es stellt sich heraus, dass Sie, um sich auf eine bestimmte Zeitzone zu beziehen, den gesamten Verlauf der Zeitzonenänderung oder das Datum der Änderung der Regeln für die Sommerzeit kennen müssen.

Sie können sagen: "Die Zeitzone in New York ist PST ( -08:00)." Es ist jedoch zu klären: "Die aktuelle Zeitzone in New York ist PST." Gleichzeitig benötigen Sie für die genaue Implementierung des Systems einen noch genaueren Ausdruck. Vergiss den Begriff "Zeitzone". Sie sollten sagen: "In New York wird PST jetzt als Standardzeit verwendet."

Was sollten wir also anstelle von Offset verwenden, um die Zeitzone einer bestimmten Region zu bestimmen? Der Name dieser Region. Genauer gesagt, Sie sollten die Regionen, in denen derselbe Übergang zur Sommerzeit und zur Standardzeit erfolgt, in einer einzigen Zeitzone zusammenfassen. Namen wie PT (Pacific Time) können verwendet werden, sie kombinieren jedoch nur die aktuelle Standard- und Sommerzeit und berücksichtigen nicht unbedingt alle historischen Änderungen. Da PT nur in den USA und Kanada verfügbar ist, müssen Sie sich auf die bewährten Standards renommierter Unternehmen verlassen, um die Vielseitigkeit Ihrer Software sicherzustellen.

IANA-Zeitzonendatenbank


Ich muss gestehen, dass Zeitzoneninformationen eher eine Datenbank als ein Satz von Regeln sind, da diese Informationen alle relevanten historischen Änderungen enthalten sollten. Es gibt verschiedene Standarddatenbanken, die zur Lösung von Zeitzonenproblemen entwickelt wurden. Die am häufigsten verwendete IANA-Zeitzonendatenbank , die üblicherweise als tz-Datenbank (oder tzdata) bezeichnet wird. Die Datenbank enthält historische Daten zu Änderungen der Standardzeit und der Sommerzeit auf der ganzen Welt. Darüber hinaus ist es so organisiert, dass Sie alle historischen Daten überprüfen und die Genauigkeit der Zeit seit der Unix-Zeit überprüfen können ( 1970.01/01 00:00:00). Obwohl Sie Informationen bis 1970 in der Datenbank finden können, kann deren Genauigkeit nicht garantiert werden.

Die Namenskonvention verwendet die Regel "Region / Ort". Als Region wird in der Regel der Name des Kontinents oder des Ozeans (Asien, Amerika, Pazifik) und als Ort die Namen der wichtigsten Städte (Seoul, New York) verwendet. Der Grund ist, dass Städte in der Regel länger existieren als Länder. Zum Beispiel ist die Zeitzone von Südkorea Asia/Seoulund Japan ist Asia/Tokyo. Obwohl beide Länder den gleichen Versatz verwenden UTC+09:00, variierte ihre Ortszeit auf unterschiedliche Weise, so dass sie in verschiedene Zeitzonen unterteilt waren.

Die IANA-Datenbank wird von vielen Communities von Entwicklern und Historikern betrieben. Frisch verfügbare historische Daten werden sofort eingegeben und die aktuellen Richtlinien aktualisiert, sodass die Basis heute als zuverlässigste Quelle angesehen werden kann. Darüber hinaus wird es unter der Haube vieler Unix-Systeme, einschließlich Linux und MacOS, sowie einer Reihe von gängigen Programmiersprachen wie Java und PHP verwendet.

Bitte beachten Sie, dass Windows eine Microsoft-Datenbank verwendet . Es ist jedoch in Bezug auf historische Daten ungenau und wird nur von Microsoft selbst unterstützt. Daher ist die Basis weniger zuverlässig als die IANA-Basis.

JavaScript und IANA-Basis


Die zeitzonenbezogene Funktionalität ist in JavaScript implementiert. Standardmäßig verwendet die Sprache die aktuelle Zone der Region (genauer gesagt den bei der Installation des Betriebssystems ausgewählten Gürtel), und es gibt keine Möglichkeit, sie zu ändern. Darüber hinaus sind selbst die Spezifikationen für den Datenbankstandard in JavaScript vage und Sie werden dies selbst verstehen, wenn Sie sich für die Spezifikation für ES2015 entscheiden. Über die lokale Zeitzone und die Verfügbarkeit von DST gibt es nur einige vage Aussagen. Beispielsweise ist DST definiert als: ECMAScript 2015 - Anpassung der Sommerzeit .

Dies ist ein implementierungsabhängiger Algorithmus, der anhand der besten verfügbaren Zeitzoneninformationen die Einstellung der Sommerzeit (t) für die Sommerzeit (in Sommerzeit) berechnet. Die ECMAScript-Implementierung sollte die lokale Sommerzeiteinstellung am besten definieren.

Sieht so aus, als würden sie nur sagen: "Alter, versuche es funktionieren zu lassen." Unter anderem müssen Sie das Problem der Kompatibilität mit verschiedenen Browsern lösen. Sie sagen: "Was für ein Durcheinander!", Und lesen Sie dann die folgende Zeile:

Hinweis: Es wird empfohlen, die IANA-Zeitzonendatenbank http://www.iana.org/time-zones/ in Ihren Implementierungen zu verwenden .

Ja Die ECMA-Spezifikationen geben Ihnen die einfache Empfehlung, die IANA-Datenbank zu verwenden, da in JavaScript keine spezielle Standarddatenbank vorhanden ist. Infolgedessen verwenden verschiedene Browser ihre eigenen Zeitzonenoperationen, um die Zeit zu berechnen, die häufig nicht miteinander kompatibel sind. Später in ECMA für die internationale API haben wir die Option hinzugefügt, IANA-Daten im ECMA-402-Format zu verwenden Intl.DateTimeFormat. Diese Option ist jedoch viel weniger zuverlässig als Analoga in anderen Programmiersprachen.

Zeitzone in der Server-Client-Umgebung


Stellen Sie sich ein einfaches Szenario vor: Wir müssen eine Zeitzone definieren. Angenommen, wir erstellen einen Kalender, der Zeitinformationen verarbeitet. Wenn ein Benutzer in der Client-Umgebung Datum und Uhrzeit in das Registrierungsfenster eingibt, wird das Datum an den Server übertragen und in der Datenbank gespeichert. Dann erhält der Client vom Server das im Zeitplan registrierte Datum für die Anzeige auf dem Bildschirm.

Hier müssen Sie sich für etwas entscheiden. Was ist, wenn sich einige der Clients, die auf den Server zugreifen, in unterschiedlichen Zeitzonen befinden? Die Veranstaltung im Zeitplan, die am 10. März 2017 um 23.30 Uhr in New York in Seoul registriert ist, sollte als 10. März 2017 um 9.30 Uhr angezeigt werden. Damit der Server Clients aus unterschiedlichen Zeitzonen bedienen kann, muss der darauf gespeicherte Zeitplan absolute Werte enthalten, die in keiner Weise vom Gürtel abhängig sind. Jeder Server hat seine eigene Art, solche Werte zu speichern. Diese Frage würde den Rahmen des Artikels sprengen, da alles von dem Server oder der Datenbank abhängt. Im Allgemeinen sollten das Datum und die Uhrzeit, die vom Client an den Server übertragen werden, entweder als Werte angegeben werden, die auf einem einzelnen Offset (normalerweise UTC) basieren, oder als Werte, die Informationen zur Zeitzone der Clientumgebung enthalten.

Üblicherweise werden solche Daten in Form einer Unix-Zeit im UTC-Format oder gemäß ISO-8601- Standard mit Offset-Informationen übertragen. Wenn wir in unserem Beispiel am 10. März 2017 um 21.30 Uhr Seoul in Unix-Zeit konvertieren, erhalten wir einen ganzzahligen Wert 1489113000. Im ISO-8601-Format wird ein Zeichenfolgewert erhalten 2017–03–10T11:30:00+09:00.

Wenn Sie in Ihrer Browser-Umgebung JavaScript verwenden, müssen Sie den eingegebenen Wert wie oben beschrieben konvertieren und anschließend wieder in Ihre benutzerdefinierte Zeitzone konvertieren. Wir müssen beide Probleme lösen. Aus Sicht einer Programmiersprache wird der erste Vorgang als "Parsing" und der zweite als "Formatierung" bezeichnet. Nun sehen wir uns an, wie das in Javascript gemacht wird.

Selbst wenn Sie mit JS in einer Serverumgebung mit Node.js arbeiten, müssen Sie möglicherweise die vom Client erhaltenen Daten analysieren. Da jedoch die Zeitzonen von Servern und Datenbanken normalerweise synchronisiert werden und die Formatierung für Clients gilt, müssen Sie in einer Browser-Umgebung mehrere Faktoren festlegen. Weitere werde ich anhand der Browserumgebung erläutern.

Javascript-Datumsobjekt


Aufgaben, bei denen mit einer bestimmten oder einer Zeit gearbeitet wird, werden mit einem Objekt gelöst Date. Dies ist ein in ECMAScript definiertes systemeigenes Objekt wie Arrayoder Function. Das heißt, es wird zum größten Teil mit nativem Code wie C ++ implementiert. Die API ist in der MDN-Dokumentation gut beschrieben . Das Objekt wurde stark von der Klasse java.util.Date aus Java beeinflusst, so dass es einige unerwünschte Eigenschaften geerbt hat, z month.

Unter der Haube arbeitet ein Objekt Date in JavaScript mit der Zeit und verwendet absolute Werte im Unix-Zeitformat. Aber auf den Konstrukteuren und Methoden wie Features parse(), getHour(),setHour()Andere wiederum sind von der Zeitzone des Clients betroffen (genauer gesagt vom Gürtel, der in dem Betriebssystem angegeben ist, in dem der Browser ausgeführt wird). Wenn Sie also ein Objekt Datedirekt mit den vom Benutzer eingegebenen Daten erstellen , wird die lokale Zeitzone des Clients in diesen Daten angezeigt.

Wie bereits erwähnt, bietet JavaScript keine Möglichkeit, die Zeitzone willkürlich zu ändern. Daher gehen wir davon aus, dass wir den im Browser angegebenen Wert der Zeitzone direkt verwenden können.

Erstellen eines Date-Objekts mit vom Benutzer eingegebenen Daten


Kommen wir zum ersten Beispiel zurück. Angenommen, ein Benutzer hat am 11. März 2017 um 11:30 Uhr Ortszeit in Seoul eingegeben. Diese Daten werden als fünf Zahlen gespeichert: 2017, 2, 11, 11 und 30 Jahre, Monat, Tag, Stunde und Minute (da der Monat bei 0 beginnt, ist es 0 Uhr) Der Wert sollte 3–1 = 2) sein. Mit dem Konstruktor können Sie leicht ein Objekt erstellen Date:

const d1 = new Date(2017, 2, 11, 11, 30);
d1.toString(); // Sat Mar 11 2017 11:30:00 GMT+0900 (KST)

Wenn Sie den zurückgegebenen Wert betrachten d1.toString(), werden Sie feststellen, dass der absolute Wert des erstellten Objekts am 11. März 2017 +09:0011:00 Uhr beträgt. Er wird mithilfe von KST (KST) berechnet .

Sie können im Konstruktor und in String-Daten verwenden. Wenn Sie sie anwenden Date, ruft das Objekt intern Date.parse()den korrekten Wert auf und berechnet diesen. Diese Funktion unterstützt die Spezifikationen von RFC2888 und ISO-8601 . Die MDN-Dokumentation für Date.parse () besagt jedoch, dass der von dieser Methode zurückgegebene Wert vom Browser abhängt und das Format des Zeichenfolgentyps den genauen endgültigen Wert beeinflussen kann. Daher ist es besser, diese Methode nicht zu verwenden. In Safari und Internet Explorer scheint zum Beispiel ein String-Wert 2015–10–12 12:00:00zurückzukehrenNaN, und in Chrome und Firefox wird die lokale Zeitzone zurückgegeben. In einigen Situationen wird ein UTC-basierter Wert zurückgegeben.

Date-Objekt mit Serverdaten erstellen


Angenommen, Sie möchten Daten von einem Server erhalten. Wenn sie in Form einer numerischen Unix-Zeit vorliegen, Datekönnen Sie einfach einen Konstruktor verwenden , um ein Objekt zu erstellen . Ich habe nicht erwähnt, dass ein Konstruktor, wenn er einen Dateeinzigen Wert als einen einzigen Parameter verwendet, den Unix-Zeitwert in Millisekunden berechnet (Hinweis: JS verarbeitet die Unix-Zeit in Millisekunden. Das bedeutet, dass der zweite Wert mit 1000 multipliziert werden muss). Bei der Ausführung des folgenden Codes erhalten wir denselben Wert wie im vorherigen Beispiel:


const d1 = new Date(1489199400000);
d1.toString(); // Sat Mar 11 2017 11:30:00 GMT+0900 (KST)

Und wenn anstelle der Unix-Zeit der String-Typ ISO-8601 verwendet werden? Wie ich oben erklärt habe, wird die Methode Date.parse()unzuverlässig und es ist besser, sie nicht zu verwenden. Ab ECMAScript 5 können Sie jedoch im Designer Datein Internet Explorer 9.0 und höher eine Zeichenfolge im ISO-8601-Format verwenden.

Wenn Sie nicht den neuesten Browser verwenden, stellen Sie sicher, dass sich Zam Ende der Werte ein Buchstabe befindet . Andernfalls kann Ihr alter Browser den Wert basierend auf der Ortszeit und nicht in UTC interpretieren. Hier ein Beispiel für die Verwendung von Internet Explorer 10:

const d1 = new Date('2017-03-11T11:30:00');
const d2 = new Date('2017-03-11T11:30:00Z');
d1.toString(); // "Sat Mar 11 11:30:00 UTC+0900 2017"
d2.toString(); // "Sat Mar 11 20:30:00 UTC+0900 2017"

Gemäß der Spezifikation sollte in beiden Fällen derselbe Wert erhalten werden. Aber sie sind anders. In einem späteren Browser sind die Werte gleich. Um dieses Problem zu vermeiden, fügen Sie immer Zam Ende der Zeile hinzu, wenn keine Informationen zur Zeitzone vorhanden sind.

Erstellen eines Datums zum Senden an den Server


Jetzt können Sie die zuvor erstellte Funktion verwenden Date, die Zeit basierend auf lokalen Zeitzonen frei abrufen oder hinzufügen. Vergessen Sie nicht, die Daten erst am Ende der Verarbeitung in das vorherige Format zu konvertieren, bevor Sie zum Server zurückkehren.

Wenn dies die Unix-Zeit ist, können Sie die Methode verwenden getTime()(Millisekunden nicht vergessen).

const d1 = new Date(2017, 2, 11, 11, 30);
d1.getTime(); // 1489199400000

Was ist mit dem String-Wert im ISO-8601-Format? Wie gesagt, Internet Explorer 9.0 und höher unterstützen ECMAScript 5 und spätere Versionen unterstützen ISO-8601. Daher können Sie mit den Methoden toISOString()oder toJSON()einen String in ISO-8601 erstellen ( toJSON()kann für rekursive Aufrufe mit JSON.stringify()und anderen verwendet werden). Beide Methoden liefern das gleiche Ergebnis, außer wenn falsche Daten verarbeitet werden:

const d1 = new Date(2017, 2, 11, 11, 30);
d1.toISOString(); // "2017-03-11T02:30:00.000Z"
d1.toJSON();      // "2017-03-11T02:30:00.000Z"
const d2 = new Date('Hello');
d2.toISOString(); // Error: Invalid Date
d2.toJSON();      // null

Um eine Zeichenfolge im UTC-Format zu erstellen, können Sie die Methode toGMTString()oder verwenden toUTCString(). Dies führt zu einem Wert, der den Anforderungen von RFC-1123 entspricht .

Ein Objekt Dateenthält toString(), toLocaleString()und ihre Erweiterungsmethoden. Der Nutzen ist jedoch gering, da sie hauptsächlich dazu verwendet werden, Zeilen basierend auf der lokalen Zeitzone zurückzugeben, und die Rückgabewerte von Browser und Betriebssystem abhängen.

Ändern der lokalen Zeitzone


Wie Sie sehen, unterstützt JS einige Zeitzonen. Und wenn Sie in der Anwendung den lokalen Gürtel wechseln müssen, ohne den im Betriebssystem angegebenen Wert zu berücksichtigen? Oder wenn Sie mehrere Zeitzonen gleichzeitig in einer Anwendung anzeigen müssen? Wie bereits mehrfach gesagt, erlaubt JS nicht, die lokale Zeitzone manuell zu ändern. Die einzige Lösung wäre das Hinzufügen oder Entfernen eines Versatzes ab dem Datum, für den Sie bereits den Versatzwert des gewünschten Riemens kennen. Aber sei nicht verärgert. Vielleicht gibt es einen anderen Weg.

Kehren wir zu unserem Beispiel mit Seoul zurück. Diese Zeitzone sollte im Browser angegeben werden. Der Benutzer gibt am 11. März 2017 um 11.30 Uhr die Uhrzeit in Seoul ein und möchte sie als lokale Zeit in New York ansehen. Der Server sendet das Datum in Unix-Zeit in Millisekunden und benachrichtigt den New Yorker Offset-05:00. Jetzt können Sie die Daten konvertieren, wenn Sie den lokalen Zeitzonenversatz kennen.

In diesem Szenario können Sie die Methode verwenden getTimeZoneOffset(). Dies ist die einzige API in JavaScript, mit der Sie Informationen zur lokalen Zeitzone abrufen können. Die Methode gibt den aktuellen Zonenversatzwert in Minuten zurück:

const seoul = new Date(1489199400000);
seoul.getTimeZoneOffset(); // -540

Der Wert -540bedeutet, dass die Zeitzone 540 Minuten vor dem Ziel liegt. Achten Sie auf das Minus, obwohl der Seoul-Offset ein Plus ( +09:00) enthält. Ich weiß nicht warum, aber es wird so angezeigt. Wenn wir diese Methode verwenden, um den Versatz für New York zu berechnen, erhalten wir 60 * 5 = 300. Wandeln Sie die Differenz 840in Millisekunden um und erstellen Sie ein neues Objekt Date. Jetzt verwenden wir diese Methode getXX, um den Wert in das gewünschte Format zu konvertieren. Erstellen Sie eine einfache Formatierungsfunktion, um die Ergebnisse zu vergleichen:

function formatDate(date) {
   return date.getFullYear() + '/' +
      (date.getMonth() + 1) + '/' +
      date.getDate() + ' ' +
      date.getHours() + ':' + 
      date.getMinutes();
   }
const seoul = new Date(1489199400000);
const ny = new Date(1489199400000 - (840 * 60 * 1000));
formatDate(seoul);  // 2017/3/11 11:30
formatDate(ny);     // 2017/3/10 21:30

formatDate()zeigt das korrekte Datum und die Uhrzeit entsprechend dem Zeitunterschied zwischen Seoul und New York an. Sieht so aus, als hätten wir eine einfache Lösung gefunden. Ist es möglich, in die lokale Zeitzone zu konvertieren, wenn wir den Versatz der gewünschten Region kennen? Leider gibt es keine. Ich habe bereits gesagt, dass Zeitzonendaten eine Datenbank sind, die alle historischen Änderungen in Offsets speichert. Um den korrekten Zeitzonenwert zu erhalten, müssen Sie den Versatz zum gewünschten Datum (nicht zum aktuellen Datum) kennen.

Konvertierungsproblem der lokalen Zeitzone


Wenn Sie mit dem obigen Beispiel etwas mehr arbeiten, werden Sie bald auf ein Problem stoßen. Angenommen, ein Benutzer möchte die Ortszeit in New York überprüfen und dann das Datum von 11 auf 15 ändern. Wenn Sie die Methode setDate()aus dem Objekt verwenden Date, können Sie das Datum ändern, ohne die anderen Werte zu beeinflussen.

ny.setDate(15);
formatDate(ny);   // 2017/3/15 21:30

Es sieht einfach aus, aber es gibt eine versteckte Falle. Was passiert, wenn Sie Daten an den Server zurücksenden müssen? Sie sind geändert, so dass Sie nicht verwenden können , Methoden getTime()oder getISOString(). Daher ist es notwendig, die inverse Transformation durchzuführen, bevor Daten an den Server gesendet werden.

const time = ny.getTime() + (840 * 60 * 1000);  // 1489631400000

Einige fragen sich vielleicht, warum ich die Verwendung von transformierten Daten hinzugefügt habe, weil sie vor der Rückkehr immer noch konvertiert werden müssen. Sie können Daten auch ohne Konvertierung verarbeiten und ein transformiertes Objekt Datenur während der Formatierung temporär erstellen . Nein. Wenn das Objekt Date auf der Zeit von Seoul basiert, um das Datum vom 11. bis zum 15. zu ändern, werden 4 Tage hinzugefügt ( 24 * 4 * 60 * 60 * 1000). Im Fall der lokalen New Yorker Zeit änderte sich das Datum von 10 auf 15, dh es wurden 5 Tage hinzugefügt ( 24* 5 * 60 * 60 * 1000). Um ein genaues Ergebnis zu erhalten, müssen Sie die Daten basierend auf dem lokalen Versatz berechnen.

Die Probleme enden nicht dort. Sie erhalten den gewünschten Wert nicht einfach durch Addition oder Subtraktion des Offsets. Da für New York die Sommerzeit am 12. März beginnt, ist der Offset für den 15. März 2017 gleich-04:00und nicht -05:00. Wenn Sie die inverse Transformation durchführen, müssen Sie 780 Minuten hinzufügen, 60 Minuten weniger als zuvor.

const time = ny.getTime() + (780 * 60 * 1000);  // 1489627800000

Wenn sich die lokale Zeitzone des Benutzers auf New York bezieht und Sie die Uhrzeit in Seoul kennen müssen, führt die unnötige Nutzung der Sommerzeit zu einem anderen Problem.

Einfach ausgedrückt, Sie können den Versatz alleine nicht verwenden, um genaue Vorgänge basierend auf der ausgewählten Zeitzone auszuführen. Wenn wir alles, was wir bereits besprochen haben, zusammenstellen, wird deutlich, dass es in der Sommerzeit noch Schwierigkeiten gibt. Um den genauen Wert zu erhalten, benötigen Sie eine Datenbank, die den gesamten Verlauf der sich ändernden Offsets enthält, z. B. dieselbe IANA-Datenbank .

Um dieses Problem zu lösen, müssen Sie die gesamte Datenbank speichern und das Datum oder die Uhrzeit aus dem Objekt extrahierenDateFinden Sie dieses Datum und den entsprechenden Versatz und konvertieren Sie den Wert entsprechend dem oben beschriebenen Prozess. Theoretisch ist das alles realisierbar. Tatsächlich müssen Sie jedoch zu viel Energie aufwenden und die Zuverlässigkeit der konvertierten Daten nicht testen. Obwohl es nicht eilig ist, sich aufzuregen. Bisher haben wir nur einige der Probleme von JS und deren Lösung diskutiert. Jetzt können Sie eine gute Bibliothek verwenden.

Moment Zeitzone


Moment ist eine ausgereifte JavaScript-Bibliothek, die fast zum Standard geworden ist. Es bietet verschiedene APIs für Datumsangaben und deren Formatierung. Viele Benutzer finden die Bibliothek für stabil und zuverlässig. Es gibt auch das Moment-Timezone- Erweiterungsmodul , das die oben genannten Probleme löst. Es enthält IANA-Datenbankdaten für die genaue Berechnung von Offsets und bietet eine Reihe von APIs, die Sie zum Ändern und Formatieren von Zeitzonen verwenden können.

Ich werde nicht ausführlich über die Verwendung der Bibliothek oder deren Struktur sprechen. Zeigen Sie Ihnen einfach, wie Sie die oben beschriebenen Probleme lösen können. Für Details senden Sie bitte die Dokumentation .

Verwenden Sie also Moment-Zeitzone:

const seoul = moment(1489199400000).tz('Asia/Seoul');
const ny = moment(1489199400000).tz('America/New_York');
seoul.format(); // 2017-03-11T11:30:00+09:00
ny.format();    // 2017-03-10T21:30:00-05:00
seoul.date(15).format();  // 2017-03-15T11:30:00+09:00
ny.date(15).format();     // 2017-03-15T21:30:00-04:00

Der Versatz seoulbleibt gleich und der Versatz nyhat sich von -05:00in geändert -04:00. Und wenn Sie die Funktion verwenden format(), können Sie einen String im ISO-8601-Format erhalten, in dem der Versatz sauber angewendet wird. Es stellt sich viel einfacher heraus als die oben von mir gegebene Lösung.

Fazit


Wir haben die in JavaScript unterstützten Zeitzonen-APIs und die damit verbundene Komplexität besprochen. Wenn Sie Ihre lokale Zeitzone nicht manuell ändern müssen, können Sie die erforderlichen Funktionen auch mithilfe grundlegender APIs implementieren, die die Verwendung von Internet Explorer 9 und höher erfordern. Wenn Sie manuell wechseln müssen, wird alles sehr kompliziert. In einer Region ohne Sommerzeit und gelegentlichen Änderungen in der Zeitzone können Sie die erforderliche Funktionalität teilweise implementieren, indem Sie die Daten mit transformieren getTimezoneOffset(). Wenn Sie jedoch eine vollständige Zeitzonenunterstützung benötigen, tun Sie dies nicht von Grund auf. Verwenden Sie besser eine Bibliothek wie Moment Timezone.

Ich habe versucht, alles alleine zu machen, konnte es aber nicht, was nicht überraschend ist. Nach zahlreichen Versuchen kann ich Rat geben: Benutze die Bibliothek. Ich begann einen Artikel zu schreiben und wusste nicht, was ich zum Schluss sagen sollte, aber jetzt weiß ich es. Ich empfehle nicht, Fremdbibliotheken nicht blind zu verwenden, ohne zu wissen, welche Funktionen von JavaScript sie unterstützen, und mögliche Fallstricke. Wählen Sie wie immer das richtige Werkzeug für Ihre Situation.

Nützliche Links



Jetzt auch beliebt: