Home > Enterprise >  Create a date object in a specific time zone and convert it to UTC in JavaScript
Create a date object in a specific time zone and convert it to UTC in JavaScript

Time:05-08

My application is currently storing the date and time of a particular event in the following format:

date: 2022-05-06
time: 00:00 // (12:00 AM)

Each event's time also contains a TimeZone associated with it. If the person who is organizing the event is from, say, Singapore, the time zone will be Asia/Singapore.

When I send a calendar invite of this event to its attendees, I want to send it in UTC time so that at the recipient's end, it will be in their time zone. (Note: I am using ics package for creating calendar events).

So, what I want is to create a date object with time = 2022-05-06 00:00 in Singapore TimeZone (according to the above example) and then convert it to UTC, which should give 2022-05-05 16:00 (since Asia/Singapore is UTC 8). How can I achieve this?

Thanks in advance.

CodePudding user response:

A possible approach has to be built upon some pre-conditions

  • the passed date-time string needs to be a parsable string which represents the local date of the to be targeted timezone, thus it does not include parsable timezone offset data.
  • the timezone gets provided as name which is conform to IANA's Time Zone Database.

Then the implementation is as follows

  • create a Date instance from a parsable date representative (either number or string value).

    • Note ... this date object already carries its own timezone offset determined by the client/environment the script is running at.
  • In order to produce a later on easy to parse UTC-conform custom string format the approach utilizes the format method of Intl.DateTimeFormat of ECMAScript's Internationalization API.

    • Note ... the configuration of the options parameter is set with the only goal of returning a custom UTC date time string format where one can easily parse the dates timezone offset from (not as timezone name as provided but as number values in the form ' hh:mm' or '-hh:mm')
  • The timezone offset's hours and minutes are retrieved via a regex ... /([ -]\d{2}):(\d{2})$/ which matches the pattern at the string's end and captures the offsetHours and offsetMinutes substrings.

  • Both string values get parsed into a minute based total number value.

  • Now one has the minute based offset of the provided timezone name in relation to the date object's local/client time which needs to be compensated by the date's own timezone offset

  • The final step is to create a new date with a corrected timezone offset in relation of the provided timezone name to UTC which is done on a millisecond base via the date's getTime value and the former minute based total in milliseconds.

    • Now one can choose to either return the date as toUTCString or as custom UTC conform string again via Intl.DateTimeFormat.format where one would choose e.g. 'lt' (Lithuanian) as locales string parameter because Lithuanian supports the date format of 'YYYY-MM-DD' (with the joining dashes).

function createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  parsableDateWithoutTimeZoneOffset,
  ianaTimeZoneName,
) {
  const date = new Date(parsableDateWithoutTimeZoneOffset);
  const format = new Intl.DateTimeFormat('en', {
      weekday: 'short',
      year: 'numeric',
      month: 'long',
      day: '2-digit',
      hour12: false,
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      timeZone: ianaTimeZoneName,
      timeZoneName: 'longOffset',
    }).format(date);

  let [_, offsetHours = 0, offsetMinutes = 0] = format
    .match(/([ -]\d{2}):(\d{2})$/) ?? [];

  offsetMinutes = (parseInt(offsetHours, 10) * 60)
      parseInt(offsetMinutes, 10)
      date.getTimezoneOffset();

  // return new Date(
  //   date.getTime() - (offsetMinutes * 60000)
  // )
  // .toUTCString();

  return new Intl.DateTimeFormat('lt', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour12: false,
    hour: '2-digit',
    minute: '2-digit',
    timeZone: 'UTC',
  }).format(date.getTime() - (offsetMinutes * 60000));
}

console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Asia/Singapore'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Asia/Singapore'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Asia/Kabul'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Asia/Kabul'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Asia/Istanbul'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Asia/Istanbul'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Europe/Amsterdam'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Europe/Amsterdam'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'UTC'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'UTC'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'America/Jamaica'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'America/Jamaica'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'America/Anchorage'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'America/Anchorage'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Pacific/Marquesas'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Pacific/Marquesas'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Pacific/Honolulu'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Pacific/Honolulu'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Pacific/Chatham'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
  '2022-05-06 00:00', 'Pacific/Chatham'
));
.as-console-wrapper { min-height: 100%!important; top: 0; }

CodePudding user response:

const date = new Date('2020-04-13T00:00:00.000Z').toLocaleString('en-SG').split('T')
console.log(date)

  • Related