Learn how to create a Date from UTC

Get support on JavaScript,jQuery, AJAX and other related technology.
Post Reply
admin
Site Admin
Posts: 44

Learn how to create a Date from UTC

Post by admin » Sun May 17, 2020 7:53 pm

By default, a Date object is created as local time. This is not always desirable, for example when communicating a date between a server and a client that do not reside in the same timezone. In this scenario, one doesn't want to worry about timezones at all until the date needs to be displayed in local time, if that is even required at all.

The problem
In this problem we want to communicate a specific date (day, month, year) with someone in a different timezone. The first implementation naively uses local times, which results in wrong results. The second implementation uses UTC dates to avoid timezones where they are not needed.

Naive approach with WRONG results

Code: Select all

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());
Sample output:
Foo was born on: Sat Jan 1 2000

Code: Select all

//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()));
Sample output:
Foo was born on: Fri Dec 31 1999

And thus, Bar would always believe Foo was born on the last day of 1999.

Correct approach

Code: Select all

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());
Sample output:
Foo was born on: Sat Jan 1 2000

Code: Select all

//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()));
Sample output:
Foo was born on: Sat Jan 1 2000

Creating a Date from UTC
If one wants to create a Date object based on UTC or GMT, the Date.UTC(...) method can be used. It uses the same arguments as the longest Date constructor. This method will return a number representing the time that has passed since January 1, 1970, 00:00:00 UTC.

Code: Select all

console.log(Date.UTC(2000,0,31,12));
Sample output:
949320000000

Code: Select all

var utcDate = new Date(Date.UTC(2000,0,31,12));
console.log(utcDate);
Sample output:
Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))

Unsurprisingly, the difference between UTC time and local time is, in fact, the timezone offset converted to milliseconds.

Code: Select all

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);
Sample output: true

Changing a Date object
All Date object modifiers, such as setDate(...) and setFullYear(...) have an equivalent takes an argument in UTC time rather than in local time.

Code: Select all

var date = new Date();
date.setUTCFullYear(2000,0,31);
date.setUTCHours(12,0,0,0);
console.log(date);
Sample output:
Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))

The other UTC-specific modifiers are .setUTCMonth(), .setUTCDate() (for the day of the month), .setUTCMinutes(), .setUTCSeconds() and .setUTCMilliseconds().

Avoiding ambiguity with getTime() and setTime()
Where the methods above are required to differentiate between ambiguity in dates, it is usually easier to communicate a date as the amount of time that has passed since January 1, 1970, 00:00:00 UTC. This single number represents a single point in time, and can be converted to local time whenever necessary.

Code: Select all

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);
Sample output: true

Code: Select all

//And when constructing a date from it elsewhere...
var otherDate = new Date(timestamp);
//Represented as a universal date
console.log(otherDate.toUTCString());
//Represented as a local date
console.log(otherDate);
Sample output:
Mon, 31 Jan 2000 12:00:00 GMT
Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))

Post Reply