Convert Date to UTC timestamp

Viewed 292

I have a date with a time, like this

const date = {year: 2020, month: 12, day: 31};
const time = {hours: 16, minutes: 2};

How do I get UTC representation of that time depending on a timezone? (without using any libraries)

convetToUTC(date, time, "Europe/Moscow") // => <UTC timestamp>
convetToUTC(date, time, "America/New_York") // => <UTC timestamp>

Examples

convetToUTC(
  {year: 2021, month: 7, day: 30}, 
  {hours: 16, minutes: 15}, 
  "Europe/Moscow"
) // => 1627650900

convetToUTC(
  {year: 2021, month: 7, day: 30}, 
  {hours: 16, minutes: 15}, 
  "America/New_York"
) // => 1627676100
2 Answers

Piggy-backing on Achempion's response, I fixed the timezone offset calculation. The timezone date should be subtracted from the UTC date. The result of this difference should be in minutes.

You will need to then convert the minute offset back into milliseconds and subtract this from the date.

/**
* Calculates the timezone offset of a particular time zone.
* @param {String} timeZone - a database time zone name
* @param {Date} date - a date for determining if DST is accounted for
* @return {Number} returns an offset in minutes
* @see https://stackoverflow.com/a/68593283/1762224
*/
const getTimeZoneOffset = (timeZone = 'UTC', date = new Date()) => {
  const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }));
  const tzDate = new Date(date.toLocaleString('en-US', { timeZone }));
  return (tzDate.getTime() - utcDate.getTime()) / 6e4;
}

const defaultDateConfig = { year: 0, month: 0, date: 0 };
const defaultTimeConfig = { hours: 0, minutes: 0, seconds: 0 };

const convetToUTC = (dateConfig, timeConfig, timeZone) => {
  const { year, month, date } = { ...defaultDateConfig, ...dateConfig };
  const { hours, minutes, seconds } = { ...defaultTimeConfig, ...timeConfig };
  const d = new Date(Date.UTC(year, month - 1, date, hours, minutes, seconds));
  const offsetMs = getTimeZoneOffset(timeZone, d) * 6e4;
  return (d.getTime() - offsetMs) / 1e3;
};

// Main
const date = { year: 2021, month: 7, date: 30 };
const time = { hours: 16, minutes: 15 };

console.log(convetToUTC(date, time, 'America/New_York')); // 1627676100
console.log(convetToUTC(date, time, 'Europe/Moscow'));    // 1627650900

const dateWithTimeZone = (timeZone, year, month, day, hour, minute, second) => {
  let date = new Date(Date.UTC(year, month, day, hour, minute, second));

  let utcDate = new Date(date.toLocaleString('en-US', { timeZone: "UTC" }));
  let tzDate = new Date(date.toLocaleString('en-US', { timeZone: timeZone }));
  let offset = utcDate.getTime() - tzDate.getTime();

  date.setTime( date.getTime() + offset );

  return date;
};

dateWithTimeZone("America/New_York", 2021, 7 - 1, 30, 16, 15, 0).getTime() / 1000)
// => 1627676100

dateWithTimeZone("Europe/Moscow", 2021, 7 - 1, 30, 16, 15, 0).getTime() / 1000)
// => 1627650900

7 - 1 used to illustrate that function accepts month's index, not month's number

Related