Como obtenho um carimbo de data / hora UTC em JavaScript?

157

Ao escrever um aplicativo Web, faz sentido armazenar (lado do servidor) todas as datas no DB como registros de data e hora UTC.

Fiquei surpreso quando percebi que você não podia fazer muito nativamente em termos de manipulação de fuso horário no JavaScript.

Estendi um pouco o objeto Date. Essa função faz sentido? Basicamente, toda vez que eu enviar algo para o servidor, será um carimbo de data / hora formatado com esta função ...

Você vê algum problema grave aqui? Ou talvez uma solução de um ângulo diferente?

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

Parece um pouco complicado para mim. E também não tenho tanta certeza sobre o desempenho.

Merc
fonte
Sei que essa é uma pergunta antiga, mas tente não estender objetos nativos como o objeto Date. Promovido porque eu gosto da pergunta em si.
trysis
Date.parse (new Date (). ToUTCString ())
Sagi
25
Essa é uma pergunta antiga que surgiu no meu feed hoje e está cheia de informações erradas. O registro de data e hora está sempre no UTC. new Date().toString()mostrará a representação atual da hora do fuso horário, new Date().toUTCString()mostrará a reprovação da hora UTC, mas new Date().getTime()é sempre UTC , porque é assim que a hora Unix é definida como: "A hora Unix (também conhecida como hora POSIX ou hora da época) é um sistema para descrever instantes no tempo, definido como o número de segundos decorridos desde 00:00:00, hora universal coordenada (UTC), quinta-feira, 1 de janeiro de 1970, sem contar os segundos bissextos. "
Amadan

Respostas:

155
  1. As datas construídas dessa maneira usam o fuso horário local, tornando a data de construção incorreta. Definir o fuso horário de um determinado objeto de data é construí-lo a partir de uma sequência de datas que inclua o fuso horário. (Eu tive problemas para que isso funcionasse em um navegador Android mais antigo.)

  2. Observe que getTime()retorna milissegundos, não segundos simples.

Para um carimbo de data / hora UTC / Unix, o seguinte deve ser suficiente:

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

Ele fatorará o fuso horário atual compensado no resultado. Para uma representação em cadeia, a resposta de David Ellis funciona.

Esclarecer:

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

Essa entrada é tratada como hora local . Se a hora UTC for passada, os resultados serão diferentes. Observe (eu estou no GMT +02: 00 agora, e são 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

Observe também que getUTCDate()não pode ser substituído getUTCDay(). Isso ocorre porque getUTCDate()retorna o dia do mês ; enquanto que, getUTCDay()retorna o dia da semana .

DCoder
fonte
1
1) Não construí uma data ... Adicionei uma função de protótipo que funcionou nisso . 2) Bom ponto, eu deveria fazer o Math.floor / 1000 - mas ainda precisaria dessa função para ter o registro de data e hora UTC de um objeto de data existente ... certo?
Merc
@ Merc: 1) você está chamando new Date(), que cria uma nova data a partir da entrada UTC, mas a trata como data / hora local. 2) Sim, você deve usar Math.floor(this.getTime() / 1000)neste caso.
DCoder
Respondendo aqui, pois preciso atualizar o código ... Isso deve ter o registro de data e hora do Unix no UTC para uma data existente : function () {return Math.floor (new Date (this.getUTCFullYear (), this.getUTCMonth (), this.getUTCDate (), this.getUTCHours (), this.getUTCMinutes (), this.getUTCSeconds ()) .getTime () / 1000); } Isso significa que eu posso fazer: var n = new Date (2008,10,10) ... ... n.getUTCTime (); (Isso será DIFERENTE para n.getUTCTime ())
Merc
1
Graças Bro Seu arquivo de trabalho Math.floor ((new Date ()) getTime () / 1000.)
Manoj Patel
51

Você também pode fazer isso utilizando getTimezoneOffset e getTime,

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

console.log("UTCseconds", UTCseconds)

Shiplu Mokaddim
fonte
4
Obrigado, isso não é encontrado em nenhum lugar na internet!
Theofanis Pantelides
Eu testar os seguintes códigos: var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000. Parece que tt.getTime() - tt.getTimezoneOffset()está correto GMT+0800.
zangw 1/09/09
1
Isso é mais melhorvar UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya
Parece que isso não funciona como escrito .. Parece que você tem que passar na seqüência de tempo em new Date()que inclui um timezone..which derrotas meio o propósito de tentar fazê-lo em js ..
claudekennilol
Isso está simplesmente errado, o valor atribuído a UTCseconds não é UTC segundos. O valor da hora da Data é UTC, alterando-o por qualquer método que represente um momento diferente no tempo.
RobG 7/04
35

A maneira mais fácil de obter a hora UTC em um formato convencional é a seguinte:

new Date().toISOString()
"2016-06-03T23:15:33.008Z"
Tahsin Turkoz
fonte
3
Essa é a resposta correta. Muitas outras respostas fornecem uma "seqüência de tempo universal", mas não fornecem o "tempo coordenado universal" atual. Eu não entendo por que tudo é tão complicado aqui.
gburton
Obrigado @gburton. Aprecie que você vê o caminho simples para a verdade. :)
Tahsin Turkoz
1
Eu uso isso, junto com ".split ('T') [0]" para comparações fáceis com base em datas AAAA-MM-DD.
Sean O
Bom ter @SeanO
Tahsin Turkoz
Isso fornece uma seqüência de tempo UTC, mas OP está pedindo um UTC timestamp (época)
Jordi Nebot
13

Na verdade, acho que os valores de data em js são muito melhores do que os objetos C # DateTime. Os objetos C # DateTime possuem uma propriedade Kind, mas nenhum fuso horário subjacente estrito como tal e as conversões de fuso horário são difíceis de rastrear se você estiver convertendo entre dois horários não UTC e não locais. Em js, todos os valores de Data têm um valor UTC subjacente, que é transmitido e conhecido, independentemente das conversões ofensivas ou de fuso horário que você faz. Minha maior reclamação sobre o objeto Date é a quantidade de comportamento indefinido que os implementadores de navegador escolheram incluir, o que pode confundir as pessoas que atacam datas em js com tentativa e erro do que ler as especificações. Usar algo como iso8601.js resolve esse comportamento variável, definindo uma única implementação do objeto Date.

Por padrão, a especificação diz que você pode criar datas com um formato de data ISO 8601 estendido, como

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

Assim, você pode deduzir a hora exata do UTC dessa maneira.

Quando você deseja passar o valor Date de volta para o servidor, você chamaria

someDate.toISOString();

ou se você preferir trabalhar com um registro de data e hora em milissegundos (número de milissegundos a partir do 1º de janeiro de 1970 UTC)

someDate.getTime();

ISO 8601 é um padrão. Você não pode ficar confuso sobre o que significa uma sequência de datas se incluir o deslocamento da data. O que isso significa para você como desenvolvedor é que você nunca precisa lidar com as conversões da hora local . Os valores da hora local existem exclusivamente para o benefício do usuário, e os valores da data, por padrão, são exibidos na hora local. Todas as manipulações de horário local permitem exibir algo sensível ao usuário e converter seqüências de caracteres da entrada do usuário. É uma boa prática converter para UTC o mais rápido possível, e o objeto js Date torna isso bastante trivial.

Por outro lado, não há muito escopo para forçar o fuso horário ou a região para o cliente (que eu conheço), o que pode ser irritante para configurações específicas do site, mas acho que o motivo por trás disso é que é um usuário configuração que não deve ser tocada.

Portanto, em resumo, a razão pela qual não há muito suporte nativo para manipulação de fuso horário é porque você simplesmente não deseja fazê-lo.

Matt Esch
fonte
12

Geralmente, você não precisa fazer muita "manipulação de fuso horário" no lado do cliente. Como regra, tento armazenar e trabalhar com datas UTC, na forma de ticks" número de milissegundos desde meia-noite de 1º de janeiro de 1970 ". Isso realmente simplifica o armazenamento, a classificação, o cálculo de compensações e, acima de tudo, livra você da dor de cabeça dos ajustes "Horário de verão". Aqui está um pequeno código JavaScript que eu uso.

Para obter a hora UTC atual:

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

Em geral, o que você precisa é formatar a data / hora do usuário final para o fuso horário local e o formato. A seguir, cuida de todas as complexidades dos formatos de data e hora no computador cliente:

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

Então, o seguinte exemplo:

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

Retorna o seguinte (para minha localidade em inglês dos EUA):

ticks = 1409103400661, DateTime = 26/08/2014 18:36:40, Data = 26/08/2014, Hora = 18: 36: 40 PM

ahmd0
fonte
1
Ao adicionar o getTimezoneOffsetvalor em sua getCurrentTimeUTCfunção, você está retornando um momento diferente. O resultado de getTime está no UTC.
Matt Johnson-Pint
1
@ MattJohnson: Isso está incorreto. O resultado de tmLoc.getTime()é um deslocamento em relação à hora local. É fácil verificar se você tem acesso a qualquer coisa que execute JavaScript.
ahmd0
2
Desculpe, mas isso não é verdade. Veja a referência MDN . Você também pode ver isso na especificação do ECMAScript. §15.9.3.3 descrevegetTime , que aponta para o "valor de tempo" definido em §15.9.5 , que é a PrimitiveValue, conforme definido em §15.9.3.3 explicitamente como UTC.
Matt Johnson-Pint
2
Bem, desde que você obtém tmLocvia new Date(), é a mesma coisa. O fuso horário afetará a saída da string tmLoc.toString()e itens semelhantes, mas não afetará tmLoc.getTime() Isso é sempre apenas um número de milissegundos desde a meia-noite de 1970-01-01 no UTC.
Matt Johnson-Pint
1
@StefansArya://The offset is in minutes -- convert it to ms
ahmd0
5

Eu acho que essa é uma solução melhor

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

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0
koalex
fonte
Outra resposta errada, getTime retorna um deslocamento UTC, adicionando o deslocamento do fuso horário local completamente o atrapalha. As compensações do ECMAScript são + ve para oeste e -ve para leste, portanto, elas devem ser subtraídas do UTC para obter local. Mas como o valor do tempo é UTC, para começar, adicioná-lo essencialmente o desloca do UTC na direção oposta ao deslocamento local.
RobG 7/04
4

Se você deseja um liner , o Registro de data e hora UTC Unix pode ser criado em JavaScript como:

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

Isso levará em consideração o fuso horário do sistema. É basicamente o tempo decorrido em segundos desde a época.

Como funciona:

  • Criar objeto de data: new Date().
  • Converta em timestamp adicionando unary +antes da criação do objeto para convertê-lo timestamp integer. : +new Date().
  • Converta milissegundos em segundos: +new Date() / 1000
  • Use tildes duplos para arredondar o valor para número inteiro. :~~(+new Date())
Kushal Likhi
fonte
7
é tilde, não tilda(sic). Infelizmente, isso não me permite remover um erro de digitação, tenho que fazer pelo menos 6 edições de caracteres. Smooth, Stackexchange, smooth #
Fred Fred
3
Não use isso . Com a especificação atual do ecma, as operações bit a bit (como o til - bit a bit não) manipulam valores inteiros assinados de 32 bits. Isso significa que essa mágica til não funcionará após 19 de janeiro de 2038, quando o valor do carimbo de data / hora estiver acima do valor máximo de um número inteiro assinado de 32 bits. jsfiddle.net/phb20ymb
Sharky
3

Quero deixar claro que o novo Date (). GetTime () realmente retorna um valor UTC, portanto, é uma maneira realmente útil de armazenar e gerenciar datas de uma maneira que seja independente dos horários localizados.

Em outras palavras, não se preocupe com todas as funções javascript do UTC. Em vez disso, basta usar Date.getTime ().

Mais informações sobre a explicação estão aqui: Se o javascript "(nova Data ()). GetTime ()" for executado em 2 fusos horários diferentes.

Stan Lin
fonte
3

Eu uso o seguinte:

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

Depois de definido esse método, você pode fazer:

var utcTime = new Date().getUTCTime();
jlbofh
fonte
Solução mais limpa. THX!
avalanche1
Mas essa não é uma solução limpa para enviar datas, porque os TimeStamps são sempre UTC. A melhor solução para mim ao enviar datas é usar uma representação de seqüência de caracteres como "dd / MM / aaaa HH: mm: ss" e depois analisá-la no lado do servidor com o fuso horário padrão do servidor para obter um carimbo de data / hora UTC ou o que for. Veja esta resposta
jlbofh
2
analisando uma string - você está chamando isso de limpo? meh
avalanche1
Certifique-se de que existem métodos para gerar uma data no formato de sequência de acordo com as especificações ISO. O método é toISOString (). Você pode analisá-lo de forma limpa em Java usando algo como:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh
Outra resposta incorreta this.getTime()retorna um deslocamento UTC, subtraindo o deslocamento do fuso horário local, tornando-o local, não o UTC, portanto, getUTCTime retorna um deslocamento local, não o UTC.
RobG 7/04
2

Estou impressionado com a complexidade dessa questão.

Todos são idênticos e todos os seus valores inteiros === EPOCH time: D

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

Não acredite em mim, checkout: http://www.epochconverter.com/

fliptopbox
fonte
2

Como new Date().toUTCString()retorna uma sequência como "Wed, 11 Oct 2017 09:24:41 GMT"você pode cortar os três últimos caracteres e passar a sequência fatiada para 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)
Maurice Wipf
fonte
1

EDIT: O código abaixo NÃO funciona. Eu estava sempre assumindo que o novo Date (). GetTime () retornou o número de segundos desde o 1º de janeiro de 1970 NO FUSO FUSO ATUAL. Este não é o caso: getTime () retorna o número de segundos no UTC. Portanto, o código abaixo faz um superajuste bruto. Obrigado a todos!]

Primeiro de tudo, obrigado por suas ideias fantásticas. Eu acho que minha pergunta tinha o título errado ... deveria ter sido "Obtenha o carimbo de data / hora UTC Unix para uma data existente".

Então, se eu tiver um objeto de data:

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

Eu estava atrás de uma função que me dizia "The UTC Unix Timestamp".

Esta função parece ser o verdadeiro truque:

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

Observe que funciona em "this" Isso significa que eu posso fazer:

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

n.getUTCUnixTime();

E obtenha o número de segundos desde 1º de janeiro de 1970 no horário Unix. Certo?

É um pouco insano, para mim, que o Javascript armazene tudo em horários UTC, mas para obter esse número, tenho que criar um novo objeto Date passando os getters UTC individuais e, finalmente, chamar getTime () para isso ...

Merc.

Merc
fonte
1
você viu a atualização do @ DCoder para sua resposta? Seu método getUTCUnixTimeobtém a hora errada, e JavaScript faz fornecem uma maneira simples para obter o timestamp de um Dateobjeto - usando o getTimemétodo. Veja todas as outras respostas.
Anurag
1
Ugh, você está certo, apenas os vi. (Batendo a cabeça contra a parede)
Merc
1

Eu acho que é isso que você está esperando ...

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

Agora,

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

Depois de fazer isso

new Date(dateString).getTime() / 1000

Já é hora UTC

   const getUnixTimeUtc = (dateString = new Date()) => Math.round(new Date(dateString).getTime() / 1000)

Eu testei em https://www.unixtimestamp.com/index.php

mais violento
fonte
0

Usando day.js

No navegador:

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>

No node.js:

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

Você recebe um registro de data e hora UTC unix sem milissegundos.

Ilyich
fonte
-2

Isso retornará o registro de data e hora no UTC:

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

Yash Pandya
fonte
2
Isso não retorna o tempo no UTC: new Date(new Date().toUTCString())dá a Qua 04 de outubro de 2017 07:20:14 GMT + 0200 (GMT + 02: 00)
Bas van Dijk