Javascript math with time zones

September 23, 2022


Question: 

As a developer, I need to query for records from a specific date — but the API call requires the time range to be specified as Unix timestamps.

From user's perspective, “records from a specific date” is everything with a creation datetime between 12:00am and 11:59pm. Therefore, the exact time range depends on the time zone. 

Usually, you will want to rely on the account time zone, not the browser's local time zone. (Example: the manager of an American company will still want to get a report for their “American business day”, even if they are currently on a holiday in Tokyo and have changed their computer timezone accordingly.) 

Account time zone can be retrieved from API call getConfParameters; API returns the time zone's IANA name (eg. 'America/Toronto' or 'America/Vancouver').

This StackOverflow article might be helpful: https://stackoverflow.com/questions/15141762/how-to-initialize-a-javascript-date-to-a-particular-time-zone

The top comment explains the problem in general, and recommends the Luxon library.

If you do not want to include extra libraries, comment #2 provides a pure-Javascript function  — although for our use case, you would need to flip the subtraction around.

Here is a slightly modified function:

/**
 * @param dateTimeString A relative date and time, for example '2021-03-01 00:00:00'
 * @param tz User's timezone
 * @returns {number} The datetime + timezone converted into a Unix timestamp
 */
function toTimestamp(dateTimeString, tz) {
  // Let the input be midnight, 'America/New_York'

  // The browser will initially interpret this datetime as being in its _local_
  // timezone, which may or may not be what we want.
  // Let's say the local time zone is London, UK; this statement will produce
  // midnight in London
  const localDate = new Date(dateTimeString);

  // Midnight in London = 7pm in New York
  // But calling new Date("7pm") gives us *London 7pm*, which means
  // that we will have two different Date objects we can then directly compare.
  const convertedDate = new Date(localDate.toLocaleString('en-US', {timeZone: tz}));

  // Midnight - 7pm = +5 hours
  const diff = localDate.getTime() - convertedDate.getTime();
  
  // London time + 5 hours (5am) is equal to New York midnight, which is what we wanted
  return new Date(localDate.getTime() + diff).getTime() / 1000;
}

Test cases:

toTimestamp('2021-03-01 00:00:00', 'America/Toronto'); 
1614574800 

toTimestamp('2021-03-26 00:00:00', 'America/Toronto'); 
1616731200