– updated

Johan Sebergsen Steinberg

How to use Javascript Date with host environment’s local timezone

The most intuitive basics of landing Javascript (JS) Date and local timezone, with or without DTS.

Tags:

The Apollo 11 lunar landing module Eagle, with astronauts Neil Armstrong and Buzz Aldrin aboard, is photographed above the moon by crewmate Michael Collins on the Columbia command module during rendezvous operations on July 21, 1969.

July 20, 1969, 20:17:40 UTC, Neil Armstrong and Buzz Aldrin are the first to land on the moon (photo by crewmate Michael Collins, read more at Space.com)

Armstrong and Aldrin landed on the moon in UTC time for their current host environment. For you to control time with old NASA proficiency using an API as old as the moon landing – Javascript Date inspired by an ancient Java implementation – besides parameter-free new Date() for current device local time, there’s two consistent ways to use a Date object intuitively with local timezone and DTS.

A technicality to note is that the local timezone is not stored in the Date object, but is determined by the host environment.


First option: Defining new Date by individual date and time parameters

A date can be defined by passing individual number parameters. Besides year and month index, they’re all optional.

// Syntax:
// new Date(year, monthIndex, day, hours, minutes, seconds, milliseconds)

const landingDate = new Date(1969, 5, 20)
// Fri Jun 20 1969 00:00:00 GMT[+-HHmm] ([local timezone label])
Fri Jun 20 1969 00:00:00 GMT+0000 (Coordinated Universal Time)

Two things to note:

  1. month is index based, i.e., january is 0
  2. if time is omitted, time will be midnight device local timezone

Avoid date-time-string-format!

Avoid new Date() parameter in date-time-string-format because of it’s inconsistency between included time and excluded

new Date("1969-06-20") – i.e. datestring as parameter – might seem to give the same result as number parameters, but when you only pass a date it will set it to midnight UTC time, then the host environment adds the local timezone offset.

const landingDateMidnightOffset = new Date("1969-06-20");
// [Day Month date …] 1969 [… and time including timezone offset from midnight] GMT[+-HHmm] ([local timezone label])
Fri Jun 20 1969 00:00:00 GMT+0000 (Coordinated Universal Time)

… but there might be an exception

When you want to set the time in UTC, date-time-string-format works as intended. But the option further below might be preferred for consistency.

const landingTime = new Date("1969-06-20T20:17:40.000Z")
Fri Jun 20 1969 20:17:40 GMT+0000 (Coordinated Universal Time)

Preferred option: Mutate Date by set methods

A date can also be set, statement by statement, by Date’s set methods that mutates a Date-object. They also have setUTC variants.

Note two things:

  1. month is index based again
  2. time, when not set, is local current time or the original Date-object’s time
const satLandingDate = new Date();
// Mutate Date object
satLandingDate.setFullYear(1969);
satLandingDate.setMonth(5);
satLandingDate.setDate(20);
Fri Jun 20 1969 21:49:55 GMT+0000 (Coordinated Universal Time)
const satLandingTime = new Date(satLandingDate);
// Mutate Date object
satLandingTime.setUTCHours(20);
satLandingTime.setUTCMinutes(17);
satLandingTime.setUTCSeconds(40);
Fri Jun 20 1969 20:17:40 GMT+0000 (Coordinated Universal Time)

Despite the mess of mutating a variable, this approach can be used to flexibly work with dates and, as utility, used variables can be avoided mutated, e.g.:

const addYears = (years: number, d = new Date()): Date => {
	const newDate = new Date(d);
	newDate.setFullYear(d.getFullYear() + years);
	return newDate;
};

const hundredYearAnniversary = addYears(100, landingDate);
Thu Jun 20 2069 00:00:00 GMT+0000 (Coordinated Universal Time)

Other pitfalls

Avoid toISOString() unless you specifically don’t want local date and time representation, as it converts the Date to UTC.

To get a plain date string, rather use a Date’s get methods in a utility function:

const getPlainDateString = (d = new Date()) => [
	d.getFullYear(),
	String(d.getMonth() + 1).padStart(2, "0"),
	String(d.getDate()).padStart(2, "0"),
].join("-");

const landingDay = getPlainDateString(satLandingDate);
1969-06-20

For further reading, Maggie’s Blog further explains these problems in Fixing JavaScript Date – Web Compatibility and Reality.