Formatta la data in un fuso orario specifico


177

Sto usando Moment.js per analizzare e formattare le date nella mia app Web. Come parte di un oggetto JSON, il mio server back-end invia le date in numero di millisecondi dall'epoca UTC (offset Unix).

L'analisi delle date in un fuso orario specifico è semplice: basta aggiungere l'identificatore del fuso orario RFC 822 alla fine della stringa prima di analizzare:

// 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>

Ma come posso formattare una data in un fuso orario specifico ?

Voglio risultati coerenti indipendentemente dall'ora corrente del browser, ma non voglio visualizzare le date in UTC.


2
Moment non lo supporta ancora, ma ci stanno lavorando. github.com/timrwood/moment/pull/671
Ben

5
Questo dovrebbe funzionare. Se passi momentaneamente una stringa temporale che include l'offset desiderato, allora dovrebbe conservare quell'offset e visualizzare l'ora locale come indicato, invece di adattarsi automaticamente all'ora locale del browser. Se volessi che si adattasse all'ora locale del browser, allora gli darei un orario UTC invece di dargli esplicitamente un offset da usare. Voglio dire ... gli do un offset esplicito, perché fondamentalmente lo sta mangiando e facendo la propria conversione all'offset del browser. Design terribile.
Triynko,

Gli offset di @Triynko sono soggetti all'ora legale quindi non sempre funziona come previsto.
pinkpanther,

1
A questo proposito, desidero stampare l'ora in un formato specifico, ad esempio il 15 marzo 2018, ma non riesco a trovare la stringa di formato per farlo. Il generico DD MMM, YYYYnon funziona, quando lo uso come mi piace moment.tz("2018-02-15T14:20:00.000+0530", "Asia/Bangkok").format("DD MMM, YYYY"). Qualcuno può indicarmi la documentazione in cui posso trovare tutte le chiavi per il tempo di formattazione quando utilizzo questo API.
pRmdk,

@PramodKumar Cosa c'è che non va? Questo dà "15 Feb, 2018". Intendevi usare la stringa di formato DD MMMM, YYYYper ottenere "15 February, 2018"?
quietmint

Risposte:


248

Come sottolineato nella risposta di Manto , .utcOffset()è il metodo preferito al momento 2.9.0. Questa funzione utilizza l'offset reale da UTC, non l'offset inverso (ad es. -240 per New York durante l'ora legale). Le stringhe di offset come "+0400" funzionano come prima:

// 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')

Il più vecchio .zone()come setter era deprecato in Moment.js 2.9.0. Ha accettato una stringa contenente un identificatore del fuso orario (ad esempio, "-0400" o "-04: 00" per -4 ore) o un numero che rappresenta i minuti dietro UTC (ad esempio, 240 per New York durante l'ora legale).

// 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')

Per lavorare con fusi orari denominati anziché offset numerici, includere Moment Timezone e utilizzare .tz()invece:

// 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')

Ho avuto problemi con questo tramite un errore "TypeError: Object 240 non ha alcun metodo" formato "". Ho realizzato che zone è disponibile solo come setter dalla versione 2.1.0 e successive di Moment.js (ed ero su una versione precedente). Grazie!
Melinda Weathers,

5
@ebi Per impostazione predefinita utilizza già il fuso orario del browser. Per accedere all'offset del fuso orario del browser, utilizzare .zone()come getter, che restituisce minuti da UTC (ad esempio, restituisce 300 per New York durante l'ora standard).
quietmint

1
@EricCope No, non del tutto. È possibile utilizzare .tz("America/Phoenix")se si include momentjs.com/timezone pure, però. Ho aggiornato la risposta con un esempio.
quietmint

1
Si noti che l'utilizzo dell'offset non funzionerà come previsto se il fuso orario ha offset diversi a causa dell'ora legale.
pinkpanther,

1
.UtcOffset () gestirà automaticamente l'ora legale? come quando imposto UTC +1 CET in inverno scommetterà UTC +2 CEST durante l'ora legale? Perché questo lo rende utilizzabile o no!
Avere

61

Usa il fuso orario del momento

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

Prima di poter accedere a un determinato fuso orario, dovrai caricarlo in questo modo (o utilizzando metodi alternativi descritti qui )

moment.tz.add('Europe/Berlin|CET CEST CEMT|-10 -20 -30')

Non credo che il momento in cui tz era disponibile quando è stata posta la domanda, ma penso che potrebbe essere la strada da percorrere. Attualmente sto lavorando a un problema simile con tutti i timestamp memorizzati come UTC in MySQL, ma per essere visualizzato in una zona specifica dipendente dalla configurazione dell'utente e non dal fuso orario del client.
Nickdnk,

47

Un paio di risposte menzionano già che il fuso orario momento è la strada da percorrere con il fuso orario nominato. Voglio solo chiarire qualcosa su questa biblioteca che mi ha confuso. C'è una differenza tra queste due affermazioni:

moment.tz(date, format, timezone)

moment(date, format).tz(timezone)

Supponendo che un fuso orario non sia specificato nella data passata:

Il primo codice accetta la data e presuppone che il fuso orario sia quello passato. Il secondo prenderà la data, assumerà il fuso orario dal browser e quindi cambierà l'ora e il fuso orario in base al fuso orario passato.

Esempio:

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"

Il mio fuso orario è +5 da utc. Quindi nel primo caso non cambia e imposta la data e l'ora per avere il fuso orario utc.

Nel secondo caso, presuppone che la data passata sia in -5, quindi la trasforma in UTC ed è per questo che sputa la data "2018-07-18T00: 00: 00Z"

NOTA: il parametro format è davvero importante. Se il momento omesso potrebbe ricadere nella classe Date che può comportare comportamenti imprevedibili


Supponendo che il fuso orario sia specificato nella data passata:

In questo caso entrambi si comportano allo stesso modo


Anche se ora capisco perché funziona in questo modo, ho pensato che fosse una caratteristica piuttosto confusa e che valesse la pena spiegare.


1
momento (...) .z non è una funzione
K - La tossicità in SO sta crescendo.

5
Hai installato il fuso orario del momento?
Nicola Pedretti,

c'è un modo per recuperare il momento analizzato e convertito senza formattazione? Ad esempio, se voglio formattare modi diversi senza analizzarlo di nuovo.
jEremyB,

Grazie per aver chiarito questo: ho avuto problemi durante l'impostazione di un fuso orario diverso rispetto al fuso orario del browser dell'utente, e questo era il problema esatto.
Robin Schaaf,

20

.zone () è stato deprecato e dovresti usare invece utcOffset:

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

8

Stavo riscontrando lo stesso problema con Moment.js. Ho installato il fuso orario momentaneo, ma il problema non è stato risolto. Quindi, ho fatto esattamente ciò che è esposto, ho impostato il fuso orario e funziona come un incantesimo:

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

Molte grazie!


16
Non dovresti usare il new Date()costruttore. Moment fornisce tutto ciò di cui potresti aver bisogno per analizzare le date. Vedi Analisi dei documenti.
quietmint,

Sì, ma se non lo faccio, ricevo un avviso da Moment, che è deprecato per qualcosa del genere
facundofarias,

7
L'avvertimento indica che Moment sta tornando internamente esattamente a ciò che stai facendo (usando new Date()internamente), ma questo è incoerente tra i browser . Invece, dovresti usare fornire il formato previsto come secondo argomento. Esempio: moment("12-25-1995", "MM-DD-YYYY").
quietmint

4

Mi sono appena imbattuto in questo e, dato che avevo lo stesso problema, avrei semplicemente pubblicato i risultati che mi venivano in mente

durante l'analisi, è possibile aggiornare l'offset (ovvero sto analizzando un dato (1.1.2014) e desidero solo la data, 1 gennaio 2014. Con GMT + 1 otterrei il 31.12.2013, quindi prima compenso il valore.

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

Bene, mi è stato utile supportarmi attraverso i fusi orari

B


-7

Puoi provare questo,

Qui è possibile ottenere la data in base al fuso orario client (browser).

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

Fondamentalmente la regex ti dà il valore di offset.

Saluti!!


Di solito, moment ti offre tutto ciò di cui hai bisogno. Non devi mai abbinare nulla di personalizzato.
Mahesh Samudra,
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.