JavaScript Creando una fecha desde UTC


Ejemplo

De forma predeterminada, un objeto Date se crea como hora local. Esto no siempre es deseable, por ejemplo, cuando se comunica una fecha entre un servidor y un cliente que no residen en la misma zona horaria. En este escenario, uno no quiere preocuparse por las zonas horarias hasta que la fecha deba mostrarse en la hora local, si es que se requiere.

El problema

En este problema, queremos comunicar una fecha específica (día, mes, año) con alguien en una zona horaria diferente. La primera implementación usa ingenuamente los tiempos locales, lo que resulta en resultados incorrectos. La segunda implementación usa fechas UTC para evitar las zonas horarias donde no son necesarias.

Enfoque ingenuo con resultados equivocados

function formatDate(dayOfWeek, day, month, year) {
  var daysOfWeek = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
  return daysOfWeek[dayOfWeek] + " " + months[month] + " " + day + " " + year;
}

//Foo lives in a country with timezone GMT + 1
var birthday = new Date(2000,0,1);
console.log("Foo was born on: " + formatDate(birthday.getDay(), birthday.getDate(),
      birthday.getMonth(), birthday.getFullYear()));

sendToBar(birthday.getTime());

Salida de muestra: Foo was born on: Sat Jan 1 2000

//Meanwhile somewhere else...

//Bar lives in a country with timezone GMT - 1
var birthday = new Date(receiveFromFoo());
console.log("Foo was born on: " + formatDate(birthday.getDay(), birthday.getDate(),
      birthday.getMonth(), birthday.getFullYear()));

Salida de muestra: Foo was born on: Fri Dec 31 1999

Y así, Bar siempre creería que Foo nació el último día de 1999.

Enfoque correcto

function formatDate(dayOfWeek, day, month, year) {
  var daysOfWeek = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
  return daysOfWeek[dayOfWeek] + " " + months[month] + " " + day + " " + year;
}

//Foo lives in a country with timezone GMT + 1
var birthday = new Date(Date.UTC(2000,0,1));
console.log("Foo was born on: " + formatDate(birthday.getUTCDay(), birthday.getUTCDate(),
      birthday.getUTCMonth(), birthday.getUTCFullYear()));

sendToBar(birthday.getTime());

Salida de muestra: Foo was born on: Sat Jan 1 2000

//Meanwhile somewhere else...

//Bar lives in a country with timezone GMT - 1
var birthday = new Date(receiveFromFoo());
console.log("Foo was born on: " + formatDate(birthday.getUTCDay(), birthday.getUTCDate(), 
      birthday.getUTCMonth(), birthday.getUTCFullYear()));

Salida de muestra: Foo was born on: Sat Jan 1 2000

Creando una fecha desde UTC

Si uno quiere crear un objeto Date basado en UTC o GMT, se puede usar el método Date.UTC(...) . Utiliza los mismos argumentos que el constructor de Date más largo. Este método devolverá un número que representa el tiempo transcurrido desde el 1 de enero de 1970, 00:00:00 UTC.

console.log(Date.UTC(2000,0,31,12));

Salida de muestra: 949320000000

var utcDate = new Date(Date.UTC(2000,0,31,12));
console.log(utcDate);

Salida de muestra: Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))

Como era de esperar, la diferencia entre la hora UTC y la hora local es, de hecho, el desplazamiento de zona horaria convertido en milisegundos.

var utcDate = new Date(Date.UTC(2000,0,31,12));
var localDate = new Date(2000,0,31,12);

console.log(localDate - utcDate === utcDate.getTimezoneOffset() * 60 * 1000);

Salida de muestra: true

Cambiar un objeto de fecha

Todos los modificadores de objetos de Date , como setDate(...) y setFullYear(...) tienen un equivalente toma un argumento en la hora UTC en lugar de en la hora local.

var date = new Date();
date.setUTCFullYear(2000,0,31);
date.setUTCHours(12,0,0,0);
console.log(date);

Salida de muestra: Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))

Los otros modificadores específicos de UTC son .setUTCMonth() , .setUTCDate() (para el día del mes), .setUTCMinutes() , .setUTCSeconds() y .setUTCMilliseconds() .

Evitar la ambigüedad con getTime () y setTime ()

Cuando se requieren los métodos anteriores para diferenciar la ambigüedad en las fechas, generalmente es más fácil comunicar una fecha como el tiempo transcurrido desde el 1 de enero de 1970, a las 00:00:00 UTC. Este número único representa un solo punto en el tiempo y se puede convertir a la hora local siempre que sea necesario.

var date = new Date(Date.UTC(2000,0,31,12));
var timestamp = date.getTime();
//Alternatively
var timestamp2 = Date.UTC(2000,0,31,12);
console.log(timestamp === timestamp2);

Salida de muestra: true

//And when constructing a date from it elsewhere...
var otherDate = new Date(timestamp);

//Represented as an universal date
console.log(otherDate.toUTCString());
//Represented as a local date
console.log(otherDate);

Salida de muestra:

Mon, 31 Jan 2000 12:00:00 GMT
Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))