In an Angular app, I have a form and I want the user to be able to create a Date in any timezone. The user inputs:
20/09/2021
10:30
Europe/Madrid
What I did was saving in a local file the relationship between timezone and its offset (Europe/Madrid
-> +0200
) and then create the Date using a string, like this: new Date("2021-09-20T10:30:00+0200")
.
My problem is calculating the summer hours, right now I use static timezones but that is not realistic because some countries change its timezones twice a year. I need an automatic solution.
I've been reading about moment and moment-timezone but both are legacy projects and its use is discouraged, so I am looking for something different. Thank you.
Finally I've found a solution.
Instead of static timezone offsets I used the IANA code (e.g. Asia/Kabul
) so I can calculate its value live (GMT+4:30
-> +0430
).
I used Intl, a native browser class to format dates. Example:
new Intl.DateTimeFormat("en", {
timeZone: "Pacific/Palau",
day: "2-digit",
month: "2-digit",
year: "numeric",
weekday: "long",
hour: "2-digit",
minute: "2-digit",
hour12: false,
second: "2-digit",
timeZoneName: "short",
}).format(new Date());
("Thursday, 07/15/2021, 17:19:51 PM GMT+9");
With this I could create the Date, but Date constructor will use the local timezone offset and calculate the difference, so the final time in the selected timezone will not be the specified one.
From Intl returned date string ("Thursday, 07/15/2021, 17:19:51 PM GMT+9"
) I get the last part (GMT+9
) like this:
const dateSplit = dateStr.split(" ");
const timezoneAbbr = dateSplit[dateSplit.length - ONE];
Now, because some countries have not-standard timezone abbreviations (like AST), we need to map time zone abbreviations to UTC before creating the Date
object (because Date
constructor returns error for some time zone abbreviations). I created this relationship using an enum like this:
export enum TimezoneAbbreviation {
ACDT = '+1030',
ACST = '+0930',
ACT = '-0500',
ADT = '-0300',
Finally create date string with format yyyy/MM/dd hh:mm ZZ
(e.g.: 2021/05/10 10:30 UTC-1
) and call Date
constructor with it.
There's no consensus on timezone abbreviations and may vary (they use CLDR format). Also there is confusing data like duplicated abbreviations:
Abbr | Name | UTC offset |
---|---|---|
AST | Arabia Standard Time | UTC+03 |
AST | Atlantic Standard Time | UTC−04 |
SST | Samoa Standard Time | UTC−11 |
SST | Singapore Standard Time | UTC+08 |