Come posso ottenere un Timestamp UTC in JavaScript?

Durante la scrittura di un’applicazione Web, è opportuno archiviare (lato server) tutti i datatempo nel DB come timestamp UTC.

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

Ho esteso un po ‘l’object 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 una diversa angolazione?

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

Mi sembra un po ‘complicato. E non sono altrettanto sicuro delle prestazioni.

  1. Le date costruite in questo modo utilizzano il fuso orario locale, rendendo errata la data di costruzione. Per impostare il fuso orario di un certo object data è costruirlo da una stringa di data che include il fuso orario. (Ho avuto problemi nel farlo funzionare su un browser Android precedente.)

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

Per un timestamp UTC / Unix, il seguente dovrebbe essere sufficiente:

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

Tratterà l’offset del fuso orario corrente nel risultato. Per una rappresentazione delle stringhe, la risposta di David Ellis funziona.

Chiarire:

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

Tale input viene considerato come ora locale . Se viene passato il tempo UTC , i risultati saranno diversi. 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 con getUTCDay() . Questo perché getUTCDate() restituisce il giorno del mese ; mentre getUTCDay() restituisce il giorno della settimana .

Puoi anche farlo utilizzando getTimezoneOffset e getTime,

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

Sì, non hai bisogno di fare così tanto; supponendo che ti capisco correttamente, vuoi solo il metodo toUTCString .

 var UTCstring = (new Date()).toUTCString(); 

Tuttavia, ricorda che i valori di data che ottieni sono basati sull’orologio della macchina del cliente, non sul tuo server. Se hai bisogno di valori precisi per queste date (ad esempio, per ordinare correttamente quando questa o quella azione è stata fatta rispetto all’azione di un altro utente), non puoi fare affidamento sulla libreria di date lato client, comunque, e devi calcolare date lato server in base a quando il cliente ti ha contattato.

Ricorda inoltre che in pratica tutto il codice lato client può essere modificato dal client e restituire invece valori malevoli, puoi solo garantire il codice sul lato server – trattare il lato client come un ansible aggressore.

Generalmente non è necessario fare molta “manipolazione del fuso orario” sul lato client. Di norma cerco di memorizzare e lavorare con le date UTC, sotto forma di ticks o ” numero di millisecondi dalla mezzanotte del 1 ° gennaio 1970 “. Ciò semplifica davvero lo stoccaggio, l’ordinamento, il calcolo degli offset e, soprattutto, ti libera dal mal di testa delle regolazioni “Ora legale”. Ecco un piccolo codice JavaScript che uso.

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ò che è generalmente necessario è formattare data / ora per l’utente finale per il fuso orario locale e il formato. 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("" + __s + ""); 

Restituisce quanto segue (per le mie impostazioni locali in inglese):

tick = 1409103400661, DateTime = 8/26/2014 6:36:40 PM, Data = 8/26/2014, Tempo = 6: 36: 40 PM

In realtà penso che i valori di Date in js siano di gran lunga migliori di quelli degli oggetti Date Date di C #. Gli oggetti C # DateTime hanno una proprietà Kind, ma non esiste un fuso orario di base rigoroso in quanto tale e le conversioni del fuso orario sono difficili da tracciare se si effettua la conversione tra due orari non UTC e non locali. In js, tutti i valori Date hanno un valore UTC sottostante che viene passato in giro e conosciuto indipendentemente dalle conversioni del fuso orario o del fuso orario. La mia più grande lamencanvas sull’object Date è la quantità di comportamento indefinito che gli implementatori di browser hanno scelto di includere, che può confondere le persone che attaccano le date in js con tentativi ed errori rispetto alla lettura delle specifiche. L’uso di qualcosa come iso8601.js risolve questo comportamento variabile definendo una singola implementazione dell’object Date.

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

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

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

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

 someDate.toISOString(); 

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

 someDate.getTime(); 

ISO 8601 è uno standard. Non puoi essere confuso su cosa significa una stringa di data se includi l’offset di data. Ciò che questo significa per te come sviluppatore è che non devi mai occuparti delle conversioni temporali locali . I valori di ora locale esistono esclusivamente a vantaggio dell’utente e i valori di data per impostazione predefinita vengono visualizzati nell’ora locale. Tutte le manipolazioni temporali locali consentono di visualizzare qualcosa di sensato per l’utente e di convertire stringhe dall’input dell’utente. È buona norma eseguire la conversione in UTC il prima ansible e l’object Date js lo rende abbastanza semplice.

Sul lato negativo non c’è molto spazio per forzare il fuso orario o le impostazioni locali per il client (di cui sono a conoscenza), che può essere fastidioso per le impostazioni specifiche del sito Web, ma suppongo che il ragionamento alla base di questo sia che si tratta di un utente configurazione che non dovrebbe essere toccata.

Quindi, in breve, la ragione per cui non esiste un supporto nativo per la manipolazione del fuso orario è perché semplicemente non si vuole farlo.

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

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

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

Se si desidera un solo rivestimento , è ansible creare UTC Unix Timestamp in JavaScript come:

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

Ciò terrà conto del fuso orario del sistema. È praticamente il tempo trascorso in secondi dall’epoca.

Come funziona:

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

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 

EDIT: il codice qui sotto NON funziona. Supponevo sempre che il nuovo Date (). GetTime () restituisse il numero di secondi dal 1 ° gennaio 1970 NELL’ORARIO ATTUALE. Questo non è il caso: getTime () restituisce il numero di secondi in UTC. Quindi, il codice qui sotto fa una sovra-regolazione lorda. Grazie a tutti!]

Prima di tutto, grazie per le tue fantastiche idee. Credo che la mia domanda avesse il titolo sbagliato … avrebbe dovuto essere “Prendi il timestamp UTC Unix per una data esistente”.

Quindi, se ho un object data:

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

Ero in cerca di una funzione che mi dicesse “Timestamp UTC Unix”.

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

Nota 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 al tempo Unix. Destra?

È un po ‘folle, per me, che Javascript memorizzi tutto in tempo UTC, ma poi per ottenere quel numero devo creare un nuovo object Date che passa i singoli getter UTC e poi chiamare getTime () per quello …

Merc.

Sono stupito di quanto sia diventata complessa questa domanda.

Sono tutti identici e il loro valore intero è tutto === EPOCH time: D

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

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

Voglio chiarire che il nuovo Date (). GetTime () restituisce di fatto un valore UTC, quindi è un modo davvero utile per archiviare e gestire le date in modo agnostico rispetto ai tempi localizzati.

In altre parole, non preoccuparti di tutte le funzioni JavaScript di UTC. Invece, basta usare Date.getTime ().

Maggiori informazioni sulla spiegazione sono qui: Se javascript “(new Date ()). GetTime ()” viene eseguito da 2 diversi Fusi orari.

Poiché new Date().toUTCString() restituisce una stringa come "Wed, 11 Oct 2017 09:24:41 GMT" puoi 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) 

Penso che questo 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 

Ciò restituirà il timestamp in UTC:

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