Dates timezones in Angular
Asked Answered
F

1

3

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:

  • date: 20/09/2021
  • hour: 10:30
  • timezone (select): 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.

Ferrante answered 15/7, 2021 at 7:14 Comment(2)
Did you read the Project Status of Moment.js and their recommendations of alternatives? Next to that: questions seeking for libraries is considered offtopic on Stack Overflow.Otila
Yes, thanks for the references! I've been investigating Luxon, and now some browser native date transform functions. I'll write if I find a solution.Ferrante
F
1

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).

1 - Get timezone offset from IANA zone identifier

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.

2 - Get timezone from string

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];

3 - Map non standard timezone abbreviations to its offset

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',

4 - Create Date

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.

Warn

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
Ferrante answered 16/7, 2021 at 15:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.