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