¿Cómo obtengo una marca de tiempo UTC en JavaScript?

158

Al escribir una aplicación web, tiene sentido almacenar (lado del servidor) todas las fechas en el DB como marcas de tiempo UTC.

Me sorprendió cuando noté que no se podía hacer mucho de forma nativa en términos de manipulación de zona horaria en JavaScript.

Extendí el objeto Fecha un poco. ¿Tiene sentido esta función? Básicamente, cada vez que envíe algo al servidor, será una marca de tiempo formateada con esta función ...

¿Puedes ver algún problema importante aquí? ¿O tal vez una solución desde un ángulo diferente?

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

Simplemente me parece un poco complicado. Y tampoco estoy tan seguro sobre el rendimiento.

Merc
fuente
Sé que esta es una pregunta vieja, pero trata de no extender los objetos nativos como el objeto Date. Votado porque me gusta la pregunta en sí.
trysis
Date.parse (new Date (). ToUTCString ())
Sagi
26
Esta es una vieja pregunta que apareció en mi feed hoy, y está llena de información errónea. La marca de tiempo siempre está en UTC. new Date().toString()le mostrará la representación horaria actual de la zona horaria, new Date().toUTCString()le mostrará la reproducción de la hora UTC, pero siemprenew Date().getTime() es UTC , porque eso es lo que la hora Unix se define como: "La hora Unix (también conocida como hora POSIX o hora de época) es un sistema para describir instantes en el tiempo, definido como el número de segundos que han transcurrido desde las 00:00:00 hora universal coordinada (UTC), jueves 1 de enero de 1970, sin contar los segundos bisiestos ".
Amadan

Respuestas:

155
  1. Las fechas construidas de esa manera usan la zona horaria local, haciendo que la fecha construida sea incorrecta. Establecer la zona horaria de un determinado objeto de fecha es construirlo a partir de una cadena de fecha que incluya la zona horaria. (Tuve problemas para hacer que eso funcione en un navegador Android anterior).

  2. Tenga en cuenta que getTime()devuelve milisegundos, no segundos simples.

Para una marca de tiempo UTC / Unix, lo siguiente debería ser suficiente:

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

Factorizará el desplazamiento de la zona horaria actual en el resultado. Para una representación de cadena, la respuesta de David Ellis funciona.

Para aclarar:

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

Esa entrada se trata como hora local . Si se pasa la hora UTC , los resultados serán diferentes. Observar (estoy en GMT +02: 00 en este momento, y son las 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

También tenga en cuenta que getUTCDate()no se puede sustituir por getUTCDay(). Esto se debe a que getUTCDate()devuelve el día del mes ; mientras que, getUTCDay()devuelve el día de la semana .

DCoder
fuente
1
1) No construí una fecha ... Agregué una función prototipo que funcionó en esto . 2) Buen punto, debería hacer Math.floor / 1000, pero aún así necesitaría esa función para tener la marca de tiempo UTC de un objeto de fecha existente ... ¿verdad?
Merc
@ Merc: 1) está llamando new Date(), eso crea una nueva fecha a partir de su entrada UTC pero la trata como fecha / hora local. 2) Sí, debe usar Math.floor(this.getTime() / 1000)en este caso.
DCoder
Respondiendo aquí porque necesito actualizar el código ... Esto es para tener la marca de tiempo de Unix en UTC para una fecha existente : function () {return Math.floor (new Date (this.getUTCFullYear (), this.getUTCMonth (), this.getUTCDate (), this.getUTCHours (), this.getUTCMinutes (), this.getUTCSeconds ()) .getTime () / 1000); } Esto significa que puedo hacer: var n = new Date (2008,10,10) ... ... n.getUTCTime (); (Esto será DIFERENTE a n.getUTCTime ())
Merc
1
Gracias hermano Su archivo de trabajo Math.floor ((nueva fecha ()). GetTime () / 1000)
Manoj Patel
51

También podría hacerlo utilizando getTimezoneOffset y getTime,

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

console.log("UTCseconds", UTCseconds)

Shiplu Mokaddim
fuente
44
¡Gracias, esto no se puede encontrar en Internet!
Theofanis Pantelides
Pongo a prueba los siguientes 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 tt.getTime() - tt.getTimezoneOffset()correcto para GMT+0800.
zangw
1
Esto es más mejorvar UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya
Parece que esto no funciona como está escrito ... Parece que tienes que pasar una cadena de tiempo new Date()que incluye una zona horaria ... que
frustra
Esto es simplemente incorrecto, el valor asignado a UTCseconds no es UTC segundos. El valor de hora de una fecha es UTC, cambiándolo por cualquier método que signifique que representa un momento diferente en el tiempo.
RobG
35

La forma más fácil de obtener la hora UTC en un formato convencional es la siguiente:

new Date().toISOString()
"2016-06-03T23:15:33.008Z"
Tahsin Turkoz
fuente
3
Esta es la respuesta correcta. Muchas otras respuestas dan una "cadena de tiempo universal" pero no dan el "tiempo coordinado universal" actual. No entiendo por qué todo es tan complicado aquí.
gburton
Gracias @gburton. Aprecio que veas el camino simple a la verdad. :)
Tahsin Turkoz
1
Utilizo esto, junto con ".split ('T') [0]" para facilitar las comparaciones basadas en la fecha AAAA-MM-DD.
Sean O
Es bueno tener a @SeanO
Tahsin Turkoz
Esto proporciona una cadena de tiempo UTC, pero OP está pidiendo una marca de tiempo UTC (época)
Jordi Nebot
13

De hecho, creo que los valores de fecha en js son mucho mejores que decir los objetos C # DateTime. Los objetos C # DateTime tienen una propiedad Kind, pero no hay una zona horaria subyacente estricta como tal, y las conversiones de zona horaria son difíciles de rastrear si está convirtiendo entre dos horas no UTC y no locales. En js, todos los valores de fecha tienen un valor UTC subyacente que se transmite y se conoce independientemente de las conversiones de zona horaria o de desacuerdo que realice. Mi mayor queja sobre el objeto Date es la cantidad de comportamiento indefinido que los implementadores del navegador han elegido incluir, lo que puede confundir a las personas que atacan fechas en js con prueba y error que leer la especificación. El uso de algo como iso8601.js resuelve este comportamiento variable definiendo una única implementación del objeto Date.

Por defecto, la especificación dice que puede crear fechas con un formato de fecha ISO 8601 extendido como

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

Entonces puede inferir la hora UTC exacta de esta manera.

Cuando desee pasar el valor de la fecha al servidor, llame

someDate.toISOString();

o si prefiere trabajar con una marca de tiempo de milisegundos (número de milisegundos desde el 1 de enero de 1970 UTC)

someDate.getTime();

ISO 8601 es un estándar. No puede confundirse sobre lo que significa una cadena de fecha si incluye el desplazamiento de fecha. Lo que esto significa para usted como desarrollador es que nunca tiene que lidiar con las conversiones de hora local . Los valores de hora local existen exclusivamente para el beneficio del usuario, y los valores de fecha se muestran por defecto en su hora local. Todas las manipulaciones de hora local le permiten mostrar algo sensible al usuario y convertir cadenas de entrada del usuario. Es una buena práctica convertir a UTC tan pronto como sea posible, y el objeto js Date lo hace bastante trivial.

En el lado negativo, no hay mucho margen para forzar la zona horaria o la ubicación del cliente (que yo sepa), lo que puede ser molesto para la configuración específica del sitio web, pero supongo que el razonamiento detrás de esto es que es un usuario configuración que no debe ser tocada.

En resumen, la razón por la que no hay mucho soporte nativo para la manipulación de la zona horaria es porque simplemente no quieres hacerlo.

Matt Esch
fuente
12

Por lo general, no necesita hacer mucha "manipulación de la zona horaria" en el lado del cliente. Como regla, trato de almacenar y trabajar con fechas UTC, en forma de ticks" número de milisegundos desde la medianoche del 1 de enero de 1970 ". Esto realmente simplifica el almacenamiento, la clasificación, el cálculo de las compensaciones y, sobre todo, lo libera del dolor de cabeza de los ajustes del "horario de verano". Aquí hay un pequeño código JavaScript que uso.

Para obtener la hora UTC actual:

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

Entonces, lo que generalmente necesitaría es formatear la fecha / hora para el usuario final para su zona horaria y formato local . Lo siguiente se ocupa de todas las complejidades de los formatos de fecha y hora en la computadora 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();
}

Entonces el siguiente ejemplo:

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

Devuelve lo siguiente (para mi idioma inglés de EE. UU.):

ticks = 1409103400661, DateTime = 26/08/2014 6:36:40 PM, Date = 26/08/2014, Time = 6:36:40 PM

ahmd0
fuente
1
Al agregar el getTimezoneOffsetvalor en su getCurrentTimeUTCfunción, en realidad está devolviendo un punto en el tiempo diferente. El resultado de yagetTime está en UTC.
Matt Johnson-Pint
1
@ MattJohnson: Eso es incorrecto. El resultado de tmLoc.getTime()es una compensación con respecto a la hora local. Es fácil verificar si tiene acceso a cualquier cosa que ejecute JavaScript.
ahmd0
2
Lo siento, pero eso no es cierto. Ver la referencia de MDN . También puede ver esto en la especificación ECMAScript. §15.9.3.3 describegetTime , que lo señala al "valor de tiempo" definido en §15.9.5 , que es a PrimitiveValue, como se establece en §15.9.3.3 explícitamente como UTC.
Matt Johnson-Pint
2
Bueno, ya que obtienes tmLocvía new Date(), entonces es lo mismo. La zona horaria afectará la salida de la cadena tmLoc.toString()y elementos similares, pero no afectará tmLoc.getTime() Eso siempre es solo una cantidad de milisegundos desde la medianoche 1970-01-01 en UTC.
Matt Johnson-Pint
1
@StefansArya://The offset is in minutes -- convert it to ms
ahmd0
5

Creo que esta es una mejor solución.

// 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
fuente
Otra respuesta incorrecta, getTime devuelve un desplazamiento UTC, y agrega que el desplazamiento de la zona horaria local lo arruina por completo. Las compensaciones de ECMAScript son + ve para el oeste y -ve para el este, por lo que se deben restar de UTC para obtener local. Pero dado que el valor de tiempo es UTC para comenzar, agregarlo esencialmente lo aleja de UTC en la dirección opuesta al desplazamiento local.
RobG
4

Si desea una línea única , la marca de tiempo UTC Unix se puede crear en JavaScript como:

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

Esto tendrá en cuenta la zona horaria del sistema. Es básicamente el tiempo transcurrido en segundos desde la época.

Cómo funciona:

  • Crear objeto de fecha: new Date().
  • Convierta a marca de tiempo agregando unary +antes de la creación del objeto para convertirlo timestamp integer. : +new Date().
  • Convierte milisegundos a segundos: +new Date() / 1000
  • Use tildes dobles para redondear el valor a entero. :~~(+new Date())
Kushal Likhi
fuente
77
es tilde, no tilda(sic). Lamentablemente no me permite eliminar un error tipográfico, tengo que hacer al menos 6 ediciones de caracteres. Smooth, Stackexchange, smooth
Fred
3
No uses esto . Con la especificación ecma actual, las operaciones a nivel de bits (como la tilde, a nivel de bits no) manejan valores enteros con signo de 32 bits. Eso significa que esta magia de tilde no funcionará después del 19 de enero de 2038 cuando el valor de la marca de tiempo supere el valor máximo de un entero con signo de 32 bits. jsfiddle.net/phb20ymb
Sharky
3

Quiero dejar en claro que el nuevo Date (). GetTime () de hecho devuelve un valor UTC, por lo que es una forma realmente útil de almacenar y administrar fechas de una manera que sea independiente de los tiempos localizados.

En otras palabras, no te molestes con todas las funciones de JavaScript UTC. En su lugar, solo usa Date.getTime ().

Aquí encontrará más información sobre la explicación: si javascript "(new Date ()). GetTime ()" se ejecuta desde 2 zonas horarias diferentes.

Stan Lin
fuente
3

Yo uso lo siguiente:

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

Una vez definido este método puedes hacer:

var utcTime = new Date().getUTCTime();
jlbofh
fuente
Solución más limpia. ¡GRACIAS!
avalancha1
Pero esa no es una solución limpia para enviar fechas, porque TimeStamps siempre son UTC. La mejor solución para mí al enviar fechas es utilizar una representación de cadena como "dd / MM / aaaa HH: mm: ss" y luego analizarla en el lado del servidor con la zona horaria predeterminada del servidor para obtener una marca de tiempo UTC o lo que sea. Ver esta respuesta
jlbofh
2
analizando una cadena: ¿lo estás llamando limpio? meh
avalanche1
Asegúrese de que existen métodos para generar una fecha en formato de cadena de acuerdo con las especificaciones ISO. El método es toISOString (). Puede analizarlo limpiamente en Java usando algo como:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh
Otra respuesta incorrecta, this.getTime()devuelve un desplazamiento UTC, restando el desplazamiento de la zona horaria local lo hace local, no UTC, por lo que getUTCTime devuelve un desplazamiento local, no UTC.
RobG
2

Me sorprende lo compleja que se ha vuelto esta pregunta.

Todos estos son idénticos, y todos sus valores enteros === Tiempo EPOCH: D

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

No me creas, paga: http://www.epochconverter.com/

fliptopbox
fuente
2

Dado que new Date().toUTCString()devuelve una cadena como "Wed, 11 Oct 2017 09:24:41 GMT"puede, puede cortar los últimos 3 caracteres y pasar la cadena cortada 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)
Maurice Wipf
fuente
1

EDITAR: El siguiente código NO funciona. Siempre asumí que la nueva Fecha (). GetTime () devolvió el número de segundos desde el 1 de enero de 1970 EN LA TIEMPO ACTUAL. Este no es el caso: getTime () devuelve el número de segundos en UTC. Entonces, el siguiente código hace un sobreajuste bruto. ¡Gracias a todos!]

En primer lugar, gracias por sus fantásticas ideas. Supongo que mi pregunta tenía el título incorrecto ... debería haber sido "Obtener la marca de tiempo de UTC Unix para una fecha existente".

Entonces, si tengo un objeto de fecha:

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

Estaba buscando una función que me dijera "The UTC Unix Timestamp".

Esta función parece ser el verdadero truco:

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

Tenga en cuenta que funciona en "esto" Esto significa que puedo hacer:

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

n.getUTCUnixTime();

Y obtenga el número de segundos desde el 1 de enero de 1970 en tiempo Unix. ¿Correcto?

Para mí es un poco loco que Javascript almacene todo en tiempos UTC, pero luego para obtener ese número, tengo que crear un nuevo objeto Date que pase los captadores UTC individuales y finalmente llamar a getTime () para eso ...

Merc.

Merc
fuente
1
¿Viste la actualización de @ DCoder a su respuesta? Su método getUTCUnixTimeobtiene el momento equivocado, y JavaScript hace proporcionar una forma sencilla de obtener la marca de tiempo Unix de un Dateobjeto - utilizando el getTimemétodo. Ver todas las otras respuestas.
Anurag
1
Ugh tienes razón, acabo de verlos. (Golpeándose la cabeza contra la pared)
Merc
1

Creo que esto es lo que esperas ...

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

Ahora,

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

Una vez que hagas esto

new Date(dateString).getTime() / 1000

Ya es la marca de tiempo UTC

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

Lo probé en https://www.unixtimestamp.com/index.php

violín
fuente
0

Usando day.js

En el 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>

En node.js:

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

Obtiene una marca de tiempo UTC unix sin milisegundos.

Ilich
fuente
-2

Esto devolverá la marca de tiempo en UTC:

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

Yash Pandya
fuente
2
Esto no devuelve el tiempo en UTC: new Date(new Date().toUTCString())da Mier Oct 04 2017 07:20:14 GMT + 0200 (GMT + 02: 00)
Bas van Dijk