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 ofIntl.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'
)
- Note ... the configuration of the
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 theoffsetHours
andoffsetMinutes
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 viaIntl.DateTimeFormat.format
where one would choose e.g.'lt'
(Lithuanian) aslocales
string parameter because Lithuanian supports the date format of'YYYY-MM-DD'
(with the joining dashes).
- Now one can choose to either return the date as
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)