Analysieren Sie das Datum ohne Zeitzonen-Javascript

147

Ich möchte das Datum ohne Zeitzone in JavaScript analysieren. Ich habe versucht:

new Date(Date.parse("2005-07-08T00:00:00+0000"));

Rückgabe Fr 08.07.2005 02:00:00 GMT + 0200 (Mitteleuropäische Sommerzeit)

new Date(Date.parse("2005-07-08 00:00:00 GMT+0000"));

Gibt das gleiche Ergebnis zurück

new Date(Date.parse("2005-07-08 00:00:00 GMT-0000"));

Gibt das gleiche Ergebnis zurück

Ich möchte die Zeit analysieren:

  1. Ohne Zeitzone.

  2. Ohne den Konstruktor Date.UTC oder ein neues Datum (Jahr, Monat, Tag) aufzurufen.

  3. Einfache Übergabe eines Strings an den Date-Konstruktor (ohne Prototyp-Ansätze).

  4. Ich muss Produktobjekt Datenicht String.

Athlan
quelle
3
Sie können das Date.parseBTW einfach weglassen und die Zeichenfolge direkt an den DateKonstruktor übergeben.
Bergi
1
Ich bin mir nicht sicher, warum Sie das brauchen, aber ich bin mir ziemlich sicher, dass Date immer die lokale Zeitzone des Benutzers hat. Wenn Sie möchten, dass Ihr JavaScript mit anderen Zeitzonen funktioniert, als Sie ein Wrapper-Objekt für Date verwenden müssen, funktioniert dies möglicherweise für Sie: github.com/mde/timezone-js
HMR
1
Leider musste ich das DateObjekt kopieren , um das richtige Objekt zum Vergleichen der Daten in MongoDB zu erhalten:new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())
Athlan
Wenn Sie ein Datum ohne Uhrzeit analysieren möchten, müssen Sie angeben, welche Zeitzone Sie annehmen möchten, da "2005-07-08" verschiedene Dinge in verschiedenen Zeitzonen bedeutet. Ab Mai 2020 wird in der MDN-Dokumentation aufgrund von Unterschieden bei der Implementierung von den Funktionen zum Parsen von integrierten Datumsangaben abgeraten. Bei Verwendung von Date.parse ("2005-07-08") wird jedoch wahrscheinlich eine Zeit von 00:00 UTC zurückgegeben. date-fns parse hingegen gibt 00:00 Ortszeit zurück, wenn dieselbe Datumszeichenfolge analysiert wird
Andy

Antworten:

106

Das Datum wird korrekt analysiert. Nur toString konvertiert es in Ihre lokale Zeitzone:

let s = "2005-07-08T11:22:33+0000";
let d = new Date(Date.parse(s));

// this logs for me 
// "Fri Jul 08 2005 13:22:33 GMT+0200 (Central European Summer Time)" 
// and something else for you

console.log(d.toString()) 

// this logs
// Fri, 08 Jul 2005 11:22:33 GMT
// for everyone

console.log(d.toUTCString())

Javascript Date-Objekte sind Zeitstempel - sie enthalten lediglich eine Anzahl von Millisekunden seit der Epoche. In einem Datumsobjekt gibt es keine Zeitzoneninformationen. Welches Kalenderdatum (Tag, Minuten, Sekunden) dieser Zeitstempel darstellt, ist eine Frage der Interpretation (eine der to...StringMethoden).

Das obige Beispiel zeigt, dass das Datum korrekt analysiert wird - das heißt, es enthält tatsächlich eine Anzahl von Millisekunden, die "2005-07-08T11: 22: 33" in GMT entsprechen.

georg
quelle
4
Leider muss ich ein Date-Objekt erzeugen, keinen String.
Athlan
@Athlan: einige Erklärungen hinzugefügt.
Georg
1
Ich hatte es überprüft. Ich habe das analysierte Datum an die MongoDB-Abfrage übergeben new Date(Date.parse("2005-07-08T11:22:33+0000"))und das Datum über den Konstruktor kopiert : new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate()). Beide Lösungen, unterschiedliche Ergebnisse, zweitens richtig! Ihre Antwort war nützlich und wurde gerade in hunlock.com/blogs/Javascript_Dates-The_Complete_Reference erwähnt . Oben.
Athlan
Funktionierte perfekt für mich - .toUTCString () war das Ticket, das mir die richtige Zeit von der ursprünglich angegebenen Zeichenfolge zurückgab. dh neues Datum ("2016-08-22T19: 45: 00.0000000"). toUTCString ()
Michael Giovanni Pumo
38
Die Wurzel allen Übels in JavaScript-Daten und -Zeit ist in Ihrem ersten Satz enthalten ... Es ist nur toString, das es in Ihre lokale Zeitzone umwandelt ... Wo liegt die alleinige Verantwortung darin? Die toString-Methode sollte das Ergebnis nur stringifizieren und nicht konvertieren. Wenn ich möchte, dass das Datum konvertiert wird, sollte ich andere Methoden haben, um dies zu tun.
Anker
109

Ich habe das gleiche Problem. Ich erhalte ein Datum als Zeichenfolge, zum Beispiel: '2016-08-25T00: 00: 00', aber ich muss ein Date-Objekt mit der richtigen Zeit haben. Um String in Objekt zu konvertieren, verwende ich getTimezoneOffset:

var date = new Date('2016-08-25T00:00:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);

getTimezoneOffset()gibt einen negativen oder positiven Ätherwert zurück. Dies muss abgezogen werden, um an jedem Ort der Welt zu funktionieren.

wawka
quelle
6
Ich habe das gleiche Problem und fand dies hilfreich. Ich habe jedoch festgestellt, dass dies aufgrund der Sommerzeit keine Zeitzonenversätze behandelt. Beispiel: Ich bin in PST, daher beträgt mein aktueller Offset (im März) von GMT -8: 00, im Mai jedoch -7: 00. Meine Lösung war zu berechnenvar userTimezoneOffset = date.getTimezoneOffset()*60000;
mmh02
3
Wenn ich kein kompletter Idiot bin, gibt dies tatsächlich die falsche Zeit zurück. getTimezoneOffset()Gibt die Anzahl der Minuten in die entgegengesetzte Richtung zurück, die Sie denken würden - meine Zeitzone ist momentan UTC-4, getTimezoneOffset()gibt aber eine positive 240 zurück. Daher userTimezoneOffsetsollte von abgezogen date.getTime()und nicht addiert werden.
Vaindil
1
Ich werde @vaindil zustimmen, dass Sie subtrahiert werden sollten. Die Lösung von wakwa funktioniert nur, wenn Sie die richtige Seite von Greenwich sind. Wakwas sollte es korrigieren.
Janne Harju
1
Ah! sprach zu früh. Es funktioniert in den meisten Zeitzonen nicht. Ich kann bestätigen, dass ein falsches Datum zurückgegeben wird, wenn AEST & CEST-Zeiten mit GMT-Zeit versetzt werden.
Saran3h
1
@vaindil jetzt ist das Ergebnis das gleiche, wie new Date('2016-08-25T00:00:00Z')ich denke, der Punkt war zu manipulieren, new Date('2016-08-25T00:00:00Z')so dass die Ortszeit mit der Zeit 0:00 angezeigt wird, aber dieser Code fehlteZ
Barbsan
14

Ich stieß auf dasselbe Problem und erinnerte mich dann an etwas Wackeliges an einem Legacy-Projekt, an dem ich arbeitete, und daran, wie sie mit diesem Problem umgingen. Ich habe es damals nicht verstanden und es war mir egal, bis ich selbst auf das Problem stieß

var date = '2014-01-02T00:00:00.000Z'
date = date.substring(0,10).split('-')
date = date[1] + '-' + date[2] + '-' + date[0]

new Date(date) #Thu Jan 02 2014 00:00:00 GMT-0600

Aus irgendeinem Grund setzt das Übergeben des Datums als '01 -02-2014 'die Zeitzone auf Null und ignoriert die Zeitzone des Benutzers. Dies mag ein Zufall in der Date-Klasse sein, aber es existierte vor einiger Zeit und existiert heute. Und es scheint browserübergreifend zu funktionieren. Probieren Sie es aus.

Dieser Code wird in einem globalen Projekt implementiert, in dem Zeitzonen eine große Rolle spielen, die Person, die das Datum betrachtet, sich jedoch nicht um den genauen Zeitpunkt der Einführung kümmerte.

Iwnnay
quelle
Ich denke, es ist beabsichtigt, weil das "Z" UTC bezeichnet, das JS dann konvertiert, aber wenn es keine Zeitzone gibt, kann es es nicht konvertieren, so dass es im Wesentlichen die Zeitzone des Benutzers annimmt. Würde gerne eine Bestätigung oder eine bessere Erklärung bekommen.
dlsso
7
Das wackelige Verhalten ist auf die Striche zurückzuführen. Chrome, Firefox und IE11 interpretieren alle 2014/5/31und 2014/05/31als Sa 31. Mai 2014 00:00:00 GMT-0600 (Mountain Daylight Time) `(MDT ist meine aktuelle Zeitzone). Mit Bindestrichen ... werden alle Browser 2014-05-31als Fr 30 Mai 2014 18:00:00 GMT-0600 (Mountain Daylight Time) interpretiert . Seltsamerweise gibt 2014-5-31Chrome mit Samstag zurück, Firefox gibt Freitag zurück und IE11 sagt, dass das Datum ungültig ist. Scheint, als würde ein date.replace('-','/')Trick den Trick machen.
Atheaos
6

Das DateObjekt selbst enthält ohnehin eine Zeitzone, und das zurückgegebene Ergebnis ist der Effekt, dass es standardmäßig in einen String konvertiert wird. Das heißt, Sie können kein Datumsobjekt ohne Zeitzone erstellen . Sie können jedoch das Verhalten eines DateObjekts nachahmen, indem Sie ein eigenes erstellen. Dies ist jedoch besser an Bibliotheken wie moment.js zu übergeben .

Mischik
quelle
2
Leider muss ich ein Date-Objekt erzeugen, keinen String.
Athlan
3

einfache Lösung

const handler1 = {
  construct(target, args) {
    let newDate = new target(...args);
    var tzDifference = newDate.getTimezoneOffset();
    return new target(newDate.getTime() + tzDifference * 60 * 1000);
  }
};

Date = new Proxy(Date, handler1);
alexey
quelle
3

Das Datum in Javascript hält es einfach im Inneren. Daher werden die Datums- und Uhrzeitdaten in der UTC-Unix-Epoche (Millisekunden oder ms) gespeichert.

Wenn Sie eine "feste" Zeit haben möchten, die sich in der Zeitzone auf der Erde nicht ändert, können Sie die Zeit in UTC an Ihre aktuelle lokale Zeitzone anpassen und speichern. Und wenn Sie es erneut abrufen, wird in jeder lokalen Zeitzone, in der Sie sich befinden, die angepasste UTC-Zeit basierend auf der Person angezeigt, die es gespeichert hat, und der lokale Zeitzonenversatz hinzugefügt, um die "feste" Zeit zu erhalten.

Datum speichern (in ms)

toUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC - offset; // UTC - OFFSET
}

Datum abrufen / anzeigen (in ms)

fromUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC + offset; // UTC + OFFSET
}

Dann kannst du:

const saveTime = new Date(toUTC(Date.parse("2005-07-08T00:00:00+0000")));
// SEND TO DB....

// FROM DB...
const showTime = new Date(fromUTC(saveTime));
DRBendanillo
quelle
2

Sie können diesen Code verwenden

var stringDate = "2005-07-08T00:00:00+0000";
var dTimezone = new Date();
var offset = dTimezone.getTimezoneOffset() / 60;
var date = new Date(Date.parse(stringDate));
date.setHours(date.getHours() + offset);
deype0
quelle
1
Ich glaube nicht, dass dies die Sommerzeit berücksichtigt
Daniel Thompson
2

Da es sich bei der Anzeige des Datums wirklich um ein Formatierungsproblem handelt (z. B. Anzeige in Ortszeit), verwende ich gerne das neue (ish) Intl.DateTimeFormat- Objekt, um die Formatierung durchzuführen, da sie expliziter ist und mehr Ausgabeoptionen bietet:

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };

const dateFormatter = new Intl.DateTimeFormat('en-US', dateOptions);
const dateAsFormattedString = dateFormatter.format(new Date('2019-06-01T00:00:00.000+00:00'));

console.log(dateAsFormattedString) // "June 1, 2019"

Wie gezeigt, werden durch Setzen der Zeitzone auf 'UTC' keine lokalen Konvertierungen durchgeführt. Als Bonus können Sie damit auch poliertere Ausgaben erstellen. Weitere Informationen zum Intl.DateTimeFormat- Objekt finden Sie in Mozilla - Intl.DateTimeFormat .

Bearbeiten:

Die gleiche Funktionalität kann erreicht werden, ohne ein neues Intl.DateTimeFormatObjekt zu erstellen . Übergeben Sie einfach die Optionen für Gebietsschema und Datum direkt an die toLocaleDateString()Funktion.

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };
const myDate = new Date('2019-06-01T00:00:00.000+00:00');
today.toLocaleDateString('en-US', dateOptions); // "June 1, 2019"
John Galt
quelle
1

Nur eine allgemeine Anmerkung. eine Möglichkeit, es flexibel zu halten.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Wir können getMinutes () verwenden, aber in den ersten 9 Minuten wird nur eine Zahl zurückgegeben.

let epoch = new Date() // Or any unix timestamp

let za = new Date(epoch),
    zaR = za.getUTCFullYear(),
    zaMth = za.getUTCMonth(),
    zaDs = za.getUTCDate(),
    zaTm = za.toTimeString().substr(0,5);

console.log(zaR +"-" + zaMth + "-" + zaDs, zaTm)

Date.prototype.getDate()
    Returns the day of the month (1-31) for the specified date according to local time.
Date.prototype.getDay()
    Returns the day of the week (0-6) for the specified date according to local time.
Date.prototype.getFullYear()
    Returns the year (4 digits for 4-digit years) of the specified date according to local time.
Date.prototype.getHours()
    Returns the hour (0-23) in the specified date according to local time.
Date.prototype.getMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to local time.
Date.prototype.getMinutes()
    Returns the minutes (0-59) in the specified date according to local time.
Date.prototype.getMonth()
    Returns the month (0-11) in the specified date according to local time.
Date.prototype.getSeconds()
    Returns the seconds (0-59) in the specified date according to local time.
Date.prototype.getTime()
    Returns the numeric value of the specified date as the number of milliseconds since January 1, 1970, 00:00:00 UTC (negative for prior times).
Date.prototype.getTimezoneOffset()
    Returns the time-zone offset in minutes for the current locale.
Date.prototype.getUTCDate()
    Returns the day (date) of the month (1-31) in the specified date according to universal time.
Date.prototype.getUTCDay()
    Returns the day of the week (0-6) in the specified date according to universal time.
Date.prototype.getUTCFullYear()
    Returns the year (4 digits for 4-digit years) in the specified date according to universal time.
Date.prototype.getUTCHours()
    Returns the hours (0-23) in the specified date according to universal time.
Date.prototype.getUTCMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to universal time.
Date.prototype.getUTCMinutes()
    Returns the minutes (0-59) in the specified date according to universal time.
Date.prototype.getUTCMonth()
    Returns the month (0-11) in the specified date according to universal time.
Date.prototype.getUTCSeconds()
    Returns the seconds (0-59) in the specified date according to universal time.
Date.prototype.getYear()
    Returns the year (usually 2-3 digits) in the specified date according to local time. Use getFullYear() instead. 
NVRM
quelle
-1

(new Date().toString()).replace(/ \w+-\d+ \(.*\)$/,"")

Dies wird ausgegeben: Di Jul 10 2018 19:07:11

(new Date("2005-07-08T11:22:33+0000").toString()).replace(/ \w+-\d+ \(.*\)$/,"")

Dies wird ausgegeben: Fri Jul 08 2005 04:22:33

Hinweis: Die zurückgegebene Zeit hängt von Ihrer lokalen Zeitzone ab

xxnations
quelle
-1

Dies ist die Lösung, die ich für dieses Problem gefunden habe, das für mich funktioniert.


verwendete Bibliothek: momentjs mit einfacher Javascript-Datumsklasse.

Schritt 1. Konvertieren Sie das String-Datum in ein Moment-Objekt (PS: Moment behält das ursprüngliche Datum und die ursprüngliche Uhrzeit bei, solange die toDate()Methode nicht aufgerufen wird):

const dateMoment = moment("2005-07-08T11:22:33+0000");

Schritt 2. Extrahieren hoursund minutesWerte aus dem zuvor erstellten Momentobjekt:

  const hours = dateMoment.hours();
  const mins = dateMoment.minutes();

Schritt 3. Moment in Datum konvertieren (PS: Dadurch wird das ursprüngliche Datum basierend auf der Zeitzone Ihres Browsers / Computers geändert. Machen Sie sich jedoch keine Sorgen und lesen Sie Schritt 4.):

  const dateObj = dateMoment.toDate();

Schritt 4. Stellen Sie die in Schritt 2 extrahierten Stunden und Minuten manuell ein.

  dateObj.setHours(hours);
  dateObj.setMinutes(mins);

In Schritt 5 dateObjwird nun das ursprüngliche Datum ohne Zeitzonenunterschied angezeigt. Selbst die Änderungen der Sommerzeit haben keine Auswirkungen auf das Datumsobjekt, da wir die ursprünglichen Stunden und Minuten manuell einstellen.

Hoffe das hilft.

saran3h
quelle
-7

Es gibt einige inhärente Probleme bei der Datumsanalyse, die leider standardmäßig nicht gut behoben werden.

- Von Menschen lesbare Daten enthalten implizite Zeitzonen -
Es gibt viele weit verbreitete Datumsformate im Internet, die nicht eindeutig sind

Um diese Probleme einfach und sauber zu lösen, würde man eine Funktion wie diese benötigen:

>parse(whateverDateTimeString,expectedDatePattern,timezone)
"unix time in milliseconds"

Ich habe danach gesucht, aber nichts dergleichen gefunden!

Also habe ich erstellt: https://github.com/zsoltszabo/timestamp-grabber

Genießen!

user2667976
quelle