Come posso ottenere un timestamp UTC in JavaScript?


158

Durante la scrittura di un'applicazione Web, ha senso archiviare (lato server) tutti i periodi di dati nel DB come timestamp UTC.

Sono rimasto stupito quando ho notato che non si poteva fare nativamente molto in termini di manipolazione del fuso orario in JavaScript.

Ho esteso un po 'l'oggetto Date. Questa funzione ha senso? Fondamentalmente, ogni volta che invio qualcosa al server, sarà un timestamp formattato con questa funzione ...

Riesci a vedere qualche grosso problema qui? O forse una soluzione da un'angolazione diversa?

Date.prototype.getUTCTime = function(){ 
  return new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime(); 
}

Mi sembra solo un po 'contorto. E non sono nemmeno così sicuro delle prestazioni.


So che questa è una specie di vecchia domanda, ma cerca di non estendere oggetti nativi come l'oggetto Date. È stato votato perché mi piace la domanda stessa.
trysis

Date.parse (new Date (). ToUTCString ())
Sagi,

26
Questa è una vecchia domanda che è emersa nel mio feed oggi, ed è piena di disinformazione. Il timestamp è sempre in UTC. new Date().toString()ti mostrerà la rappresentazione del fuso orario corrente, new Date().toUTCString()ti mostrerà il repr dell'ora UTC, ma new Date().getTime()è sempre UTC , perché è quello che il tempo Unix è definito come: "Il tempo Unix (noto anche come tempo POSIX o tempo di epoca) è un sistema per descrivere gli istanti nel tempo, definito come il numero di secondi trascorsi dalle 00:00:00 Coordinated Universal Time (UTC), giovedì 1 gennaio 1970, senza contare i secondi bisestili. "
Amadan,

Risposte:


155
  1. Le date costruite in questo modo utilizzano il fuso orario locale, rendendo la data costruita errata. Impostare il fuso orario di un determinato oggetto data significa costruirlo da una stringa di data che include il fuso orario. (Ho avuto problemi a farlo funzionare in un vecchio browser Android.)

  2. Nota che getTime()restituisce millisecondi, non semplici secondi.

Per un timestamp UTC / Unix, è sufficiente quanto segue:

Math.floor((new Date()).getTime() / 1000)

Fattorizzerà l'offset del fuso orario corrente nel risultato. Per una rappresentazione in formato stringa, la risposta di David Ellis funziona.

Chiarire:

new Date(Y, M, D, h, m, s)

Tale input viene trattato come ora locale . Se il tempo UTC viene passato, i risultati differiranno. Osserva (sono in GMT +02: 00 in questo momento, ed è 07:50):

> var d1 = new Date();
> d1.toUTCString();
"Sun, 18 Mar 2012 05:50:34 GMT" // two hours less than my local time
> Math.floor(d1.getTime()/ 1000)
1332049834 

> var d2 = new Date( d1.getUTCFullYear(), d1.getUTCMonth(), d1.getUTCDate(), d1.getUTCHours(), d1.getUTCMinutes(), d1.getUTCSeconds() );
> d2.toUTCString();
"Sun, 18 Mar 2012 03:50:34 GMT" // four hours less than my local time, and two hours less than the original time - because my GMT+2 input was interpreted as GMT+0!
> Math.floor(d2.getTime()/ 1000)
1332042634

Si noti inoltre che getUTCDate()non può essere sostituito getUTCDay(). Questo perché getUTCDate()restituisce il giorno del mese ; mentre, getUTCDay()restituisce il giorno della settimana .


1
1) Non ho costruito una data ... Ho aggiunto una funzione prototipo che ha funzionato su questo . 2) Bene, dovrei fare Math.floor / 1000 - ma avrei comunque bisogno di quella funzione per avere il timestamp UTC di un oggetto data esistente ... giusto?
Merc

@Merc: 1) che stai chiamando new Date(), che crea una nuova data dall'input UTC ma la considera come data / ora locale. 2) Sì, è necessario utilizzare Math.floor(this.getTime() / 1000)in questo caso.
DCoder

Rispondendo qui come ho bisogno di aggiornare il codice ... Questo deve avere il timestamp Unix in UTC per una data esistente : function () {return Math.floor (nuova data (this.getUTCFullYear (), this.getUTCMonth (), this.getUTCDate (), this.getUTCHours (), this.getUTCMinutes (), this.getUTCSeconds ()) .getTime () / 1000); } Ciò significa che posso fare: var n = new Date (2008,10,10) ... ... n.getUTCTime (); (Questo sarà DIVERSO da n.getUTCTime ())
Merc

1
Grazie Bro Il suo file di lavoro Math.floor ((nuova data ()). GetTime () / 1000)
Manoj Patel

51

Puoi anche farlo utilizzando getTimezoneOffset e getTime,

x = new Date()
var UTCseconds = (x.getTime() + x.getTimezoneOffset()*60*1000)/1000;

console.log("UTCseconds", UTCseconds)


4
Grazie, questo non si trova da nessuna parte su Internet!
Theofanis Pantelides,

I test i seguenti codici: var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000. Sembra tt.getTime() - tt.getTimezoneOffset()corretto per GMT+0800.
zangw

1
Questo è megliovar UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya,

Sembra che questo non funzioni come scritto .. Sembra che tu debba passare una stringa temporale new Date()che include un fuso orario ... che in qualche modo sconfigge lo scopo di provare a farlo in js ..
claudekennilol,

Questo è semplicemente sbagliato, il valore assegnato a UTCseconds non è UTC secondi. Il valore di ora di una data è UTC, modificandolo con qualsiasi metodo significa che rappresenta un momento diverso nel tempo.
RobG

35

Il modo più semplice per ottenere l'ora UTC in un formato convenzionale è il seguente:

new Date().toISOString()
"2016-06-03T23:15:33.008Z"

3
Questa è la risposta corretta Molte altre risposte forniscono una "stringa di tempo universale" ma non forniscono l'attuale "tempo coordinato universale". Non capisco perché qui tutto sia così complicato.
Gburton,

Grazie @Gburton. Apprezzo di vedere il modo semplice per la verità. :)
Tahsin Turkoz,

1
Lo uso, insieme a ".split ('T') [0]" per facili confronti basati sulla data AAAA-MM-GG.
Sean O

Bello avere @SeanO
Tahsin Turkoz il

Ciò fornisce una stringa temporale UTC, ma OP richiede un timestamp UTC (epoca)
Jordi Nebot,

13

In realtà penso che i valori di Date in js siano molto meglio di dire gli oggetti DateTime di C #. Gli oggetti C # DateTime hanno una proprietà Kind, ma nessun fuso orario sottostante rigoroso in quanto tale e le conversioni di fuso orario sono difficili da tracciare se si esegue la conversione tra due orari non UTC e non locali. In js, tutti i valori di Data hanno un valore UTC sottostante che viene trasmesso e noto indipendentemente dalle conversioni di fuso orario o di offerta più frequenti. La mia più grande lamentela sull'oggetto Date è la quantità di comportamento indefinito che gli implementatori del browser hanno scelto di includere, il che può confondere le persone che attaccano le date in js con tentativi ed errori piuttosto che leggere le specifiche. L'uso di qualcosa di simile a iso8601.js risolve questo comportamento variabile definendo una singola implementazione dell'oggetto Date.

Per impostazione predefinita, la specifica dice che è possibile creare date con un formato di data ISO 8601 esteso come

var someDate = new Date('2010-12-12T12:00Z');

Quindi puoi dedurre l'ora UTC esatta in questo modo.

Quando si desidera restituire il valore della data al server che si chiama

someDate.toISOString();

o se preferisci lavorare con un timestamp di millisecondi (numero di millisecondi dal 1 ° gennaio 1970 UTC)

someDate.getTime();

ISO 8601 è uno standard. Non puoi essere confuso sul significato di una stringa di data se includi l'offset della data. Ciò che questo significa per te come sviluppatore è che non devi mai gestire da solo le conversioni di ora locale . I valori dell'ora locale esistono esclusivamente a beneficio dell'utente e i valori della data vengono visualizzati per impostazione predefinita nell'ora locale. Tutte le manipolazioni dell'ora locale consentono di visualizzare qualcosa di sensato per l'utente e di convertire le stringhe dall'input dell'utente. È buona norma convertirlo in UTC il prima possibile e l'oggetto js Date lo rende abbastanza banale.

Il rovescio della medaglia non c'è molto spazio per forzare il fuso orario o le impostazioni locali per il client (di cui sono a conoscenza), il che può essere fastidioso per le impostazioni specifiche del sito Web, ma immagino che il ragionamento alla base sia che si tratta di un utente configurazione che non deve essere toccata.

Quindi, in breve, il motivo per cui non c'è molto supporto nativo per la manipolazione del fuso orario è perché semplicemente non vuoi farlo.


12

In genere non è necessario eseguire gran parte della "manipolazione del fuso orario" sul lato client. Di norma provo a memorizzare e lavorare con le date UTC, sotto forma di ticks" numero di millisecondi dalla mezzanotte del 1 ° gennaio 1970 ". Ciò semplifica davvero l'archiviazione, l'ordinamento, il calcolo degli offset e, soprattutto, ti libera dal mal di testa delle regolazioni dell'ora legale. Ecco un piccolo codice JavaScript che utilizzo.

Per ottenere l'ora UTC corrente:

function getCurrentTimeUTC()
{
    //RETURN:
    //      = number of milliseconds between current UTC time and midnight of January 1, 1970
    var tmLoc = new Date();
    //The offset is in minutes -- convert it to ms
    return tmLoc.getTime() + tmLoc.getTimezoneOffset() * 60000;
}

Quindi ciò di cui avresti generalmente bisogno è formattare la data / ora per l'utente finale in base al fuso orario e al formato locali . Quanto segue si occupa di tutte le complessità dei formati di data e ora sul computer client:

function formatDateTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date/time
    return new Date(nTicks).toLocaleString();
}

function formatDateFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date
    return new Date(nTicks).toLocaleDateString();
}

function formatTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted time
    return new Date(nTicks).toLocaleTimeString();
}

Quindi il seguente esempio:

var ticks = getCurrentTimeUTC();  //Or get it from the server

var __s = "ticks=" + ticks + 
    ", DateTime=" + formatDateTimeFromTicks(ticks) +
    ", Date=" + formatDateFromTicks(ticks) +
    ", Time=" + formatTimeFromTicks(ticks);

document.write("<span>" + __s + "</span>");

Restituisce il seguente (per la mia locale inglese inglese):

ticks = 1409103400661, DateTime = 8/26/2014 18:36:40 PM, Data = 8/26/2014, Ora = 6: 36: 40 PM


1
Aggiungendo il getTimezoneOffsetvalore nella tua getCurrentTimeUTCfunzione, stai effettivamente restituendo un diverso punto nel tempo. Il risultato di getTimeè già in UTC.
Matt Johnson-Pint,

1
@MattJohnson: non è corretto. Il risultato di tmLoc.getTime()è un offset rispetto all'ora locale. È facile controllare se hai accesso a qualsiasi cosa che esegue JavaScript.
ahmd0

2
Scusa, ma non è vero. Vedi il riferimento MDN . Puoi anche vedere questo nelle specifiche ECMAScript. Descrive il §15.9.3.3getTime , che indica il "valore temporale" definito nel § 15.9.5 , che è un PrimitiveValue, come indicato nel § 15.9.3.3 esplicitamente come UTC.
Matt Johnson-Pint,

2
Bene, dal momento che ottieni tmLocvia new Date(), allora è la stessa cosa. Il fuso orario influenzerà l'output della stringa di tmLoc.toString()e simili elementi, ma non influenzerà tmLoc.getTime() Questo è sempre solo un numero di millisecondi dalla mezzanotte 1970-01-01 in UTC.
Matt Johnson-Pint,

1
@StefansArya://The offset is in minutes -- convert it to ms
ahmd0

5

Penso che questa sia una soluzione migliore

// UTC milliseconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0

Un'altra risposta sbagliata, getTime restituisce un offset UTC, aggiungendo che l'offset del fuso orario locale lo rovina completamente. Gli offset ECMAScript sono + ve per ovest e -ve per est, quindi dovrebbero essere sottratti da UTC per ottenere locali. Ma poiché il valore temporale è UTC per cominciare, aggiungendolo si sposta sostanzialmente da UTC nella direzione opposta all'offset locale.
RobG

4

Se si desidera un solo liner , il timestamp Unix UTC può essere creato in JavaScript come:

var currentUnixTimestap = ~~(+new Date() / 1000);

Ciò terrà conto del fuso orario del sistema. Fondamentalmente è trascorso il tempo in secondi dall'epoca.

Come funziona:

  • Creare data di oggetto: new Date().
  • Converti in timestamp aggiungendo unary +prima della creazione dell'oggetto per convertirlo in timestamp integer. : +new Date().
  • Converti millisecondi in secondi: +new Date() / 1000
  • Usa le doppie tilde per arrotondare il valore all'intero. :~~(+new Date())

7
è tilde, non tilda(sic). Purtroppo non mi consente di rimuovere un refuso, devo apportare almeno 6 modifiche al carattere. Smooth, Stackexchange, smooth
Fred

3
Non usare questo . Con l'attuale specifica ecma, le operazioni bit a bit (come la tilde - bit a bit no) gestiscono valori interi con segno di 32 bit. Ciò significa che questa magia tilde non funzionerà dopo il 19 gennaio 2038 quando il valore del timestamp sarà superiore al valore massimo di un intero con segno a 32 bit. jsfiddle.net/phb20ymb
Sharky


3

Io uso il seguente:

Date.prototype.getUTCTime = function(){ 
  return this.getTime()-(this.getTimezoneOffset()*60000); 
};

Una volta definito questo metodo puoi fare:

var utcTime = new Date().getUTCTime();

Soluzione più pulita. GRAZIE!
valanga1

Ma questa non è una soluzione pulita per inviare le date, perché i TimeStamp sono sempre UTC. La migliore soluzione per me quando invio le date è quella di utilizzare una rappresentazione di stringa come "gg / MM / aaaa HH: mm: ss" e quindi analizzarla sul lato server con la TimeZone predefinita del server per ottenere un timestamp UTC o altro. Vedi questa risposta
jlbofh,

2
analizzare una stringa - la chiami così pulita? meh
valanga1

Assicurati, ci sono metodi per generare una data in formato stringa in base alle specifiche ISO. Il metodo è toISOString (). Puoi analizzarlo in modo pulito in Java usando qualcosa del tipo:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh

Un'altra risposta errata, this.getTime()restituisce un offset UTC, sottraendo l'offset del fuso orario locale lo rende locale, non UTC, quindi getUTCTime restituisce un offset locale, non UTC.
RobG

2

Sono sorpreso da quanto sia diventata complessa questa domanda.

Questi sono tutti identici e i loro valori interi tutti === Tempo EPOCH: D

console.log((new Date()).getTime() / 1000, new Date().valueOf() / 1000, (new Date() - new Date().getTimezoneOffset() * 60 * 1000) / 1000);

Non credermi, controlla: http://www.epochconverter.com/


2

Poiché new Date().toUTCString()restituisce una stringa come "Wed, 11 Oct 2017 09:24:41 GMT"se fosse possibile tagliare gli ultimi 3 caratteri e passare la stringa tagliata a new Date():

new Date()
// Wed Oct 11 2017 11:34:33 GMT+0200 (CEST)

new Date(new Date().toUTCString().slice(0, -3))
// Wed Oct 11 2017 09:34:33 GMT+0200 (CEST)

1

EDIT: il codice seguente NON funziona. Ho sempre supposto che il nuovo Date (). GetTime () restituisse il numero di secondi dal 1 ° gennaio 1970 IN THE TIMERONE ATTUALE. Questo non è il caso: getTime () restituisce il numero di secondi in UTC. Pertanto, il codice riportato di seguito esegue una regolazione eccessiva lorda. Grazie a tutti!]

Prima di tutto, grazie per le tue fantastiche intuizioni. Immagino che la mia domanda avesse il titolo sbagliato ... avrebbe dovuto essere "Ottieni il timestamp Unix UTC per una data esistente".

Quindi, se ho un oggetto data:

var d = new Date(2009,01,31)

Cercavo una funzione che mi dicesse "Il timestamp Unix UTC".

Questa funzione sembra essere il vero trucco:

Date.prototype.getUTCUnixTime =  function (){
  return Math.floor( new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime() / 1000); 
}

Si noti che funziona su "questo" Ciò significa che posso fare:

var n = new Date(2008,10,10)
...
...

n.getUTCUnixTime();

E ottieni il numero di secondi dal 1 gennaio 1970 in tempo Unix. Destra?

È un po 'folle, per me, che Javascript memorizzi tutto nei tempi UTC, ma per ottenere quel numero devo creare un nuovo oggetto Date passando i singoli getter UTC e infine chiamare getTime () per quello ...

Merc.


1
hai visto l'aggiornamento di @ DCoder alla sua risposta? Il tuo metodo getUTCUnixTimeottiene il momento sbagliato, e JavaScript non fornire un modo semplice per ottenere il timestamp UNIX da un Dateoggetto - utilizzando il getTimemetodo. Vedi tutte le altre risposte.
Anurag

1
Hai ragione, li ho appena visti. (Sbattere la testa contro il muro)
Merc

1

Penso che sia quello che ti aspetti ...

var currTimestamp = Date.now(), //1482905176396
    utcDateString = (new Date(currTimestamp)).toUTCString(); //"Wed, 28 Dec 2016 06:06:50 GMT"

Adesso,

new Date(utcDateString).getTime(); //This will give you UTC Timestamp in JavaScript


0

Utilizzando day.js

Nel browser:

dayjs.extend(dayjs_plugin_utc)
console.log(dayjs.utc().unix())
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/plugin/utc.js"></script>

In node.js:

import dayjs from 'dayjs'
dayjs.extend(require('dayjs/plugin/utc'))
console.log(dayjs.utc().unix())

Ottieni un timestamp unix UTC senza millisecondi.


-2

Ciò restituirà il timestamp in UTC:

var utc = new Date(new Date().toUTCString()).getTime();


2
Questo non restituisce l'ora in UTC: new Date(new Date().toUTCString())dà mer 04 ott 2017 07:20:14 GMT + 0200 (GMT + 02:00)
Bas van Dijk
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.