lau / tzdata

tzdata for Elixir. Born from the Calendar library.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Possible edge case around last rule applicable for a zone lines last year

ciju opened this issue · comments

Noticed the edge case for Pacific/Apia timezone. This timezone has a shift in offset of about a day in dec 2011. There are also DST rules applicable for the same year. Following are the relevant zone lines.

			 -11:00	WS	-11/-10	2011 Dec 29 24:00
			 13:00	WS	+13/+14

Current implementation ignores the offset change on dec 29th. E.g. The periods generated are:

%{
  until: %{
    utc: "2011-09-24T14:00:00Z",
    standard: "2011-09-24T03:00:00Z",
    wall: "2011-09-24T03:00:00Z"
  },
  zone_abbr: "SST",
  from: %{
    utc: "2011-04-02T14:00:00Z",
    standard: "2011-04-02T03:00:00Z",
    wall: "2011-04-02T03:00:00Z"
  },
  std_off: 0,
  utc_off: -39600
}
%{
  until: %{
    utc: "2012-03-31T14:00:00Z",
    standard: "2012-04-01T03:00:00Z",
    wall: "2012-04-01T04:00:00Z"
  },
  zone_abbr: "WSDT",
  from: %{
    utc: "2011-09-24T14:00:00Z",
    standard: "2011-09-25T03:00:00Z",
    wall: "2011-09-25T04:00:00Z"
  },
  std_off: 3600,
  utc_off: 46800
}

I think the periods should be.

%{
  until: %{
    utc: "2011-09-24T14:00:00Z",
    standard: "2011-09-24T03:00:00Z",
    wall: "2011-09-24T03:00:00Z"
  },
  zone_abbr: "SST",
  from: %{
    utc: "2011-04-02T14:00:00Z",
    standard: "2011-04-02T03:00:00Z",
    wall: "2011-04-02T03:00:00Z"
  },
  std_off: 0,
  utc_off: -39600
}
%{
  until: %{
    utc: "2011-12-30T11:00:00Z",
    standard: "2011-12-30T00:00:00Z",
    wall: "2011-12-30T01:00:00Z"
  },
  zone_abbr: "SST",
  from: %{
    utc: "2011-09-24T14:00:00Z",
    standard: "2011-09-24T03:00:00Z",
    wall: "2011-09-24T03:00:00Z"
  },
  std_off: 3600,
  utc_off: -39600
}
%{
  until: %{
    utc: "2012-03-31T14:00:00Z",
    standard: "2012-04-01T03:00:00Z",
    wall: "2012-04-01T04:00:00Z"
  },
  zone_abbr: "WSDT",
  from: %{
    utc: "2011-12-30T11:00:00Z",
    standard: "2011-12-31T00:00:00Z",
    wall: "2011-12-31T01:00:00Z"
  },
  std_off: 3600,
  utc_off: 46800
}

Link to the zone rules for Pacific/Apia

Haven't checked if this issue applies to any other zones.

Hey @lau Have confirmed the issue in comparison to browser implementations. E.g.

ls = [
  "2011-12-30T09:00:00Z",
  "2011-12-30T09:59:00Z",
  "2011-12-30T10:00:00Z",
  "2011-12-30T10:59:00Z",
  "2011-12-30T11:00:00Z"
]

ls.map(x => [x, new Intl.DateTimeFormat('sv-SE', {
  timeZone: 'Pacific/Apia', 
  year: 'numeric', 
  month: '2-digit', 
  day: '2-digit', 
  hour: '2-digit', 
  minute: '2-digit', 
  second: '2-digit', 
  hour12: false, 
  timeZoneName: 'short'
}).format(new Date(x))])

returns

[
    ["2011-12-30T09:00:00Z", "2011-12-29 23:00:00 GMT−10"],
    ["2011-12-30T09:59:00Z", "2011-12-29 23:59:00 GMT−10"],
    ["2011-12-30T10:00:00Z", "2011-12-31 00:00:00 GMT+14"],
    ["2011-12-30T10:59:00Z", "2011-12-31 00:59:00 GMT+14"],
    ["2011-12-30T11:00:00Z", "2011-12-31 01:00:00 GMT+14"]
]

Current tzdata implementation

[
  "2011-12-30T09:00:00Z",
  "2011-12-30T09:59:00Z",
  "2011-12-30T10:00:00Z",
  "2011-12-30T10:59:00Z",
  "2011-12-30T11:00:00Z"
]
|> Enum.map(&Timex.parse!(&1, "{ISO:Extended:Z}"))
|> Enum.map(&{&1, Timex.Timezone.convert(&1, "Pacific/Apia")})

returns

[
  {~U[2011-12-30 09:00:00Z], #DateTime<2011-12-30 23:00:00+14:00 +14 Pacific/Apia>},
  {~U[2011-12-30 09:59:00Z], #DateTime<2011-12-30 23:59:00+14:00 +14 Pacific/Apia>},
  {~U[2011-12-30 10:00:00Z], #DateTime<2011-12-31 00:00:00+14:00 +14 Pacific/Apia>},
  {~U[2011-12-30 10:59:00Z], #DateTime<2011-12-31 00:59:00+14:00 +14 Pacific/Apia>},
  {~U[2011-12-30 11:00:00Z], #DateTime<2011-12-31 01:00:00+14:00 +14 Pacific/Apia>}
]

My own attempt has issue at edge case. Will see if I can fix that.

@ciju FYI you may also test and add edge cases here: https://github.com/mathieuprog/tzdb_test which compares the output of date calculations against different time zone libraries. I think tzdata still generates a lot of incorrect dates and these tests would help you fix tzdata errors.

Didn't know about tz. Guess I will just move to tz for my purpose. Hope tzdata issues are fixed soon, or Timex moves to tz/better options :)

Timex can be replaced by the standard API (which evolved significantly since Timex released). I thought you were tied to Timex and had to fix the tzdata bug:)