Analizza la data senza fuso orario javascript


147

Voglio analizzare la data senza fuso orario in JavaScript. Ho provato:

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

Resi ven 08 lug 2005 02:00:00 GMT + 0200 (ora legale dell'Europa centrale)

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

Restituisce lo stesso risultato

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

Restituisce lo stesso risultato

Voglio analizzare il tempo:

  1. Senza fuso orario.

  2. Senza chiamare il costruttore Date.UTC o la nuova data (anno, mese, giorno).

  3. Basta passare una stringa nel costruttore Date (senza approcci prototipo).

  4. Devo Dateobiettare sul prodotto , no String.


3
Potresti semplicemente omettere il Date.parsebtw e passare direttamente la stringa al Datecostruttore.
Bergi,

1
Non sono sicuro del motivo per cui ne hai bisogno, ma sono abbastanza sicuro che Date abbia sempre il fuso orario locale dell'utente. Se vuoi che il tuo JavaScript funzioni con fusi orari diversi da quelli che dovrai utilizzare un oggetto wrapper per Date, forse questo funzionerà per te: github.com/mde/timezone-js
HMR

1
Sfortunatamente, ho dovuto copiare l' Dateoggetto per ottenere l'oggetto corretto per confrontare le date in MongoDB:new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())
Athlan

Se si desidera analizzare una data senza un orario, è necessario specificare quale fuso orario si desidera assumere, perché "2005-07-08" significa cose diverse in fusi orari diversi. A partire da maggio 2020, la documentazione MDN sconsiglia qualsiasi funzionalità di analisi della data di acquisto a causa delle differenze di implementazione. Tuttavia, l'utilizzo di Date.parse ("2005-07-08") restituirà probabilmente un'ora di 00:00 UTC. L'analisi date-fns invece restituirà le 00:00 ora locale quando analizza la stessa stringa di date
Andy

Risposte:


106

La data viene analizzata correttamente, è solo ToString che la converte nel fuso orario locale:

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 object sono timestamp - contengono semplicemente un numero di millisecondi dall'epoca. Non ci sono informazioni sul fuso orario in un oggetto Date. La data del calendario (giorno, minuti, secondi) rappresentata da questo timestamp è una questione di interpretazione (uno dei to...Stringmetodi).

L'esempio sopra mostra che la data viene analizzata correttamente, ovvero contiene effettivamente una quantità di millisecondi corrispondente a "2005-07-08T11: 22: 33" in GMT.


4
Sfortunatamente devo produrre l'oggetto Date, non String.
Athlan,

@Athlan: aggiunte alcune spiegazioni.
Georg

1
L'avevo controllato. Ho superato la data di interrogazione analizzato in MongoDB new Date(Date.parse("2005-07-08T11:22:33+0000")), e la data copiato tramite costruttore: new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate()). Entrambe le soluzioni, risultati diversi, secondo corretto! La tua risposta è stata utile, appena menzionata in hunlock.com/blogs/Javascript_Dates-The_Complete_Reference . Su.
Athlan,

Ha funzionato perfettamente per me - .toUTCString () è stato il ticket che mi ha restituito l'ora corretta dalla stringa originale fornita. cioè nuova data ("22-08-2016T19: 45: 00.0000000"). toUTCString ()
Michael Giovanni Pumo,

38
La radice di tutto il male nelle date e nell'ora di JavaScript è contenuta nella tua prima frase ... È solo a String che CONVERTE il tuo fuso orario locale ... Dov'è la sola responsabilità in questo? Il metodo toString dovrebbe semplicemente restringere il risultato e non convertirlo. Se voglio che la data venga convertita, dovrei avere altri metodi per farlo.
ancora il

109

Ho lo stesso problema. Ricevo una data come stringa, ad esempio: '25-08-2016T00: 00: 00', ma ho bisogno di avere l'oggetto Date con l'ora corretta. Per convertire String in oggetto, utilizzo getTimezoneOffset:

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

getTimezoneOffset()restituirà etere valore negativo o positivo. Questo deve essere sottratto per funzionare in ogni luogo del mondo.


6
Ho lo stesso problema e l'ho trovato utile. Tuttavia, ho scoperto che questo non gestisce gli offset del fuso orario a causa dell'ora legale. Esempio: sono in PST, quindi il mio attuale offset (a marzo) dal GMT è -8: 00, ma a maggio sarebbe -7: 00. La mia soluzione era calcolarevar userTimezoneOffset = date.getTimezoneOffset()*60000;
mmh02

3
A meno che non sia un completo idiota, questo in realtà restituisce il momento sbagliato. getTimezoneOffset()restituisce il numero di minuti nella direzione opposta che si potrebbe pensare: il mio fuso orario è UTC-4 in questo momento ma getTimezoneOffset()restituisce un 240 positivo. Pertanto, è userTimezoneOffsetnecessario sottrarre date.getTime(), non aggiungere ad esso.
vaindil,

1
Concordo con @vaindil che dovresti sottrarre. La soluzione di Wakwa funziona solo quando si è sul lato corretto di Greenwich. Wakwas dovrebbe correggerlo.
Janne Harju,

1
Ah! parlato troppo presto. Non funziona per la maggior parte dei fusi orari. Posso confermare che restituisce una data errata quando si compensano gli orari AEST e CEST con l'ora GMT.
saran3h,

1
@vaindil ora il risultato è lo stesso di quello new Date('2016-08-25T00:00:00Z')che penso sia il punto da manipolare in new Date('2016-08-25T00:00:00Z')modo che l'ora locale venga visualizzata con l'ora 0:00 ma questo codice è mancatoZ
barbsan

14

Mi sono imbattuto nello stesso problema e poi ho ricordato qualcosa di strano in un progetto legacy a cui stavo lavorando e come hanno gestito questo problema. Non l'ho capito al momento e non mi importava fino a quando non ho riscontrato il problema da solo

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

Per qualsiasi motivo, passare la data come '01 -02-2014 'imposta il fuso orario su zero e ignora il fuso orario dell'utente. Questo potrebbe essere un colpo di fortuna nella classe Date, ma esisteva qualche tempo fa ed esiste oggi. E sembra funzionare su più browser. Provalo tu stesso.

Questo codice è implementato in un progetto globale in cui i fusi orari contano molto ma alla persona che guarda la data non importava il momento esatto in cui è stata introdotta.


Penso che sia intenzionale perché la "Z" designa UTC che JS converte, ma dato il fuso orario non può convertirlo, quindi assume essenzialmente il fuso orario dell'utente. Mi piacerebbe avere qualche conferma o spiegazione migliore però.
dlsso,

7
Il comportamento traballante è dovuto ai trattini. Chrome, Firefox e IE11 interpretano tutti 2014/5/31e 2014/05/31come sabato 31 maggio 2014 00:00:00 GMT-0600 (Mountain Daylight Time) `(MDT è il mio fuso orario corrente). Con trattini ... tutti i browser interpretano 2014-05-31come ven 30 maggio 2014 18:00:00 GMT-0600 (Mountain Daylight Time). Stranamente, con 2014-5-31Chrome ritorna sabato, Firefox ritorna venerdì e IE11 afferma che la data non è valida. Sembra che date.replace('-','/')potrebbe fare il trucco.
Atene,

6

L' Dateoggetto stesso conterrà comunque il fuso orario e il risultato restituito è l'effetto di convertirlo in stringa in modo predefinito. Cioè non è possibile creare un oggetto data senza fuso orario. Ma quello che puoi fare è imitare il comportamento Datedell'oggetto creando il tuo. Questo, tuttavia, è meglio essere consegnato a biblioteche come moment.js .


2
Sfortunatamente devo produrre l'oggetto Date, non String.
Athlan,

3

soluzione semplice

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);

3

La data in javascript è semplicemente semplice all'interno. quindi i dati di data e ora sono memorizzati in epoca unix UTC (millisecondi o ms).

Se vuoi avere un orario "fisso" che non cambi in qualunque fuso orario ti trovi sulla terra, puoi regolare l'ora in UTC in modo che corrisponda al tuo fuso orario locale attuale e salvarlo. E quando lo si recupera, in qualunque fuso orario locale ci si trovi, mostrerà l'ora UTC regolata in base a chi l'ha salvato e aggiungerà l'offset del fuso orario locale per ottenere l'ora "fissa".

Per salvare la data (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
}

Per recuperare / mostrare la data (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
}

Allora puoi:

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

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

2

Puoi usare questo codice

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);

1
Non credo che ciò tenga conto dell'ora legale
Daniel Thompson del

2

Dal momento che è davvero un problema di formattazione quando si visualizza la data (ad esempio, visualizza l'ora locale), mi piace usare il nuovo oggetto (ish) Intl.DateTimeFormat per eseguire la formattazione poiché è più esplicito e offre più opzioni di output:

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"

Come mostrato, impostando timeZone su 'UTC' non eseguirà conversioni locali. Come bonus, ti consente anche di creare output più raffinati. Puoi leggere ulteriori informazioni sull'oggetto Intl.DateTimeFormat da Mozilla - Intl.DateTimeFormat .

Modificare:

La stessa funzionalità può essere raggiunta senza creare un nuovo Intl.DateTimeFormatoggetto. Passa semplicemente le impostazioni locali e la data direttamente nella toLocaleDateString()funzione.

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"

1

Solo una nota generica. un modo per mantenerlo flessibile.

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

Possiamo usare getMinutes (), ma restituisce un solo numero per i primi 9 minuti.

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. 

-1

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

Ciò avrà prodotto: mar 10 lug 2018 19:07:11

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

Questo avrà output: Ven 08 Lug 2005 04:22:33

Nota: il tempo restituito dipenderà dal fuso orario locale


-1

Questa è la soluzione che mi è venuta in mente per questo problema che funziona per me.


libreria utilizzata: momentjs con javascript semplice Classe di date.

Passaggio 1. Converti l'oggetto String date in moment (PS: moment mantiene la data e l'ora originali finché toDate()non viene chiamato il metodo):

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

Passaggio 2. Estrazione hourse minutesvalori dall'oggetto moment creato in precedenza:

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

Passaggio 3. Converti il ​​momento in Data (PS: questo cambierà la data originale in base al fuso orario del tuo browser / macchina, ma non preoccuparti e leggi il passaggio 4.):

  const dateObj = dateMoment.toDate();

Passaggio 4. Impostare manualmente le ore e i minuti estratti nel passaggio 2.

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

Il passaggio 5. dateObjora mostrerà la data originale senza alcuna differenza di fuso orario. Anche le modifiche dell'ora legale non avranno alcun effetto sull'oggetto data poiché stiamo impostando manualmente le ore e i minuti originali.

Spero che questo ti aiuti.


-7

Ci sono alcuni problemi intrinseci con l'analisi della data che purtroppo non vengono risolti bene per impostazione predefinita.

-Le date leggibili dall'uomo hanno un fuso orario implicito in esse
-Ci sono molti formati di data ampiamente usati nel web che sono ambigui

Per risolvere questi problemi in modo semplice e pulito, sarebbe necessaria una funzione come questa:

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

Ho cercato questo, ma non ho trovato nulla del genere!

Così ho creato: https://github.com/zsoltszabo/timestamp-grabber

Godere!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.