mathieuprog / tz

Time zone support for Elixir
Apache License 2.0
125 stars 11 forks source link

Zone abbreviation lookup inconsistent (EST and EDT) #12

Closed dbernheisel closed 2 years ago

dbernheisel commented 2 years ago

I'm hoping the PeriodsBuilder will be able to lookup a timezone based on the abbreviation, however it seems to be inconsistent. For example

Tz.TimeZoneDatabase.time_zone_periods_from_wall_datetime(~N[2020-04-01 00:00:00], "EDT")
{:error, :time_zone_not_found}
Tz.TimeZoneDatabase.time_zone_periods_from_wall_datetime(~N[2020-12-01 00:00:00], "EST")
{:ok, %{std_offset: 0, utc_offset: -18000, zone_abbr: "EST"}}

When I look at the rules it's based on, I see this:

# Rule  NAME    FROM    TO  -   IN  ON  AT  SAVE    LETTER/S
Rule    US  2007    max -   Mar Sun>=8  2:00    1:00    D
Rule    US  2007    max -   Nov Sun>=1  2:00    0   S

So I'm thinking that the EDT abbreviation ought to work between Mar8 thru Nov1, and EST abbreviation ought to work between Nov1 thru Mar8.

mathieuprog commented 2 years ago

Hello, you'll have to be a little patient for me to look into this, because I'm heavily busy on a JS codebase right now 🥲 I'll have a look soon!

mathieuprog commented 2 years ago

I'm back! EDT, as the error says, is not a valid IANA time zone identifier. We need to pass valid IANA time zone identifiers and not time zone abbreviations to the DateTime functions.

iex(1)> DateTime.from_naive(~N[2020-04-01 00:00:00], "EDT", Tz.TimeZoneDatabase)
{:error, :time_zone_not_found}

iex(2)> DateTime.from_naive(~N[2020-04-01 00:00:00], "EDT", TimeZoneInfo.TimeZoneDatabase)
{:error, :time_zone_not_found}

iex(3)> DateTime.from_naive(~N[2020-04-01 00:00:00], "EDT", Tzdata.TimeZoneDatabase)
{:error, :time_zone_not_found}
iex(4)> DateTime.from_naive(~N[2020-12-01 00:00:00], "EST", Tz.TimeZoneDatabase)
{:ok, #DateTime<2020-12-01 00:00:00-05:00 EST EST>}

iex(5)> DateTime.from_naive(~N[2020-12-01 00:00:00], "EST", TimeZoneInfo.TimeZoneDatabase)
{:ok, #DateTime<2020-12-01 00:00:00-05:00 EST EST>}

iex(6)> DateTime.from_naive(~N[2020-12-01 00:00:00], "EST", Tzdata.TimeZoneDatabase)
{:ok, #DateTime<2020-12-01 00:00:00-05:00 EST EST>}
iex(7)> DateTime.from_naive(~N[2020-04-01 00:00:00], "EST5EDT", Tz.TimeZoneDatabase)
{:ok, #DateTime<2020-04-01 00:00:00-04:00 EDT EST5EDT>}

iex(8)> DateTime.from_naive(~N[2020-04-01 00:00:00], "EST5EDT", TimeZoneInfo.TimeZoneDatabase)
{:ok, #DateTime<2020-04-01 00:00:00-04:00 EDT EST5EDT>}

iex(9)> DateTime.from_naive(~N[2020-04-01 00:00:00], "EST5EDT", Tzdata.TimeZoneDatabase)
{:ok, #DateTime<2020-04-01 00:00:00-04:00 EDT EST5EDT>}
iex(10)> DateTime.from_naive(~N[2020-12-01 00:00:00], "EST5EDT", Tz.TimeZoneDatabase)
{:ok, #DateTime<2020-12-01 00:00:00-05:00 EST EST5EDT>}

iex(11)> DateTime.from_naive(~N[2020-12-01 00:00:00], "EST5EDT", TimeZoneInfo.TimeZoneDatabase)
{:ok, #DateTime<2020-12-01 00:00:00-05:00 EST EST5EDT>}

iex(12)> DateTime.from_naive(~N[2020-12-01 00:00:00], "EST5EDT", Tzdata.TimeZoneDatabase)
{:ok, #DateTime<2020-12-01 00:00:00-05:00 EST EST5EDT>}
mathieuprog commented 2 years ago

You may explain your use case to see what we can do.

dbernheisel commented 2 years ago

I'm parsing datetimes from strings (wish me luck), and oftentimes the zone abbreviation is used in written form. I'd like to use one of Elixir's timezone databases to facilitate this lookup, but it seems, as you said, only the names are used for lookups-- not the formatted abbreviations.

For example, on a television commercial it might advertise that Will & Grace is on NBC at 8pmEST/5pmPST. Currently PST is not parsed but EST is. I presume because of these lines in the data file meant for backwards compatibility:

# Zone  NAME        STDOFF  RULES   FORMAT  [UNTIL]
Zone    EST      -5:00  -   EST
Zone    MST      -7:00  -   MST
Zone    HST     -10:00  -   HST
Zone    EST5EDT      -5:00  US  E%sT
Zone    CST6CDT      -6:00  US  C%sT
Zone    MST7MDT      -7:00  US  M%sT
Zone    PST8PDT      -8:00  US  P%sT
iex(8)> Tz.TimeZoneDatabase.time_zone_periods_from_wall_datetime(~N[2020-04-01 00:00:00], "EST")
{:ok, %{std_offset: 0, utc_offset: -18000, zone_abbr: "EST"}}
iex(9)> Tz.TimeZoneDatabase.time_zone_periods_from_wall_datetime(~N[2020-04-01 00:00:00], "PST")
{:error, :time_zone_not_found}

I may need to explore my own parser and abbreviation-friendly Periods builder. This implies that some user decisions should be made when translating abbreviations that are shared between timezone, such as CST (China Standard Time, Cuba Standard Time, or Central Standard Time?)

Thanks for looking into this.

mathieuprog commented 2 years ago

And I was starting to wonder why we can't pass an abbreviation and you just answered that, they are not unique:) I guess you need to do some mapping yourself.