On Thu, Jul 23, 2026 at 1:28 PM Tomasz Kamiński <[email protected]> wrote:

> When _M_get_sys_info seeds a Zone line by looking up the active rule
> just before info.begin, the previous code interpreted each rule in
> isolation against ri.offset() (the line's standard offset alone),
> ignoring the running save accumulated by earlier rules in the same
> year. For most zones this gives the right answer because the search
> only matters when no rule has fired yet, but for zones whose rule
> set has wall-time rules whose effective firing time depends on a
> prior rule's save it produces wrong answers.
>
> Canonical case: Europe/Paris around 1945.  France's rules
>
>   R Fr 1945 o - Apr 2  2 2 M
>   R Fr 1945 o - Sep 16 3 0 -
>
> both use plain wall time. In Paris's stdoff=1 frame, the September
> rule's at_time of 03:00 wall translates to UT Sep 16 02:00 if no
> prior save is applied, but to UT Sep 16 00:00 once the running save
> of 2h from the April rule is taken into account.  When seeding a
> sys_info whose info.begin falls between those two values, the simple
> search picks the April rule (save=2 → CEMT, total offset 3h) when
> the correct answer is the September rule (save=0 → CET, total offset
> 1h). libstdc++ reports this as a sustained CEMT stretch where zic
> and libc agree on CET.
>
> To address above we now consider rules triggering at info.begin (not
> only before), and the find algorithm is expanded to collect three
> rule transitions around specified time t, while continuing to ignore
> the save:
> * curr_tran: transition happening before or at time t,
> * prev_tran: transition preceding above transition,
> * next_tran: transition happening after time t.
>
> This collects sufficient information to adjust the start_time (if
> Wall time is used) for curr_tran (save of prev_tran) and next_tran
> (save of curr_tran). Assuming that applying save value does not
> change order of transition (cascading save would be ill-defined
> otherwise), after the adjustment the actual active rule is:
>  * next_tran.rule: if the adjustment pushed next_tran.when to
>    time before or at t, which happen for positive save (see
>    test_positive),
>  * prev_tran.rule: if adjustment pushed curr_tran.when to time
>    after time t, which happens for negative save (see test_negative),
>  * curr_tran.rule.
>
> For the time at the start (Jan/1) or end of the year (December/31),
> for each rule, in addition to transition in year of t, we check
> transitions in previous or next year respectively (years in range
> [first_year, last_year]). This handle rules whose firing (specified
> in local time) crosses a year boundary due to a large stdoff or save.
> One example is Pacific/Auckland's 1946 Jan 1 rule, in stdoff=12h,
> fires at 1945-12-31 11:30 UT, see test_next_year.
>
> The fallback "earliest STD rule" logic is preserved for the case
> where no rule has fired yet, but is extracted to separate function.
> This lookup is optimized, by searching the rules by name, from, and
> save in that order, grouping std rules in given year together.
>
>         PR libstdc++/124853
>
> libstdc++-v3/ChangeLog:
>
>         * src/c++20/tzdb.cc
>         (time_zone::_M_get_sys_info): Extract code blocks to
>         separate functions, and invoke them.
>         (<unnamed>::find_active_rule): Modify algorithm to
>         handle cascading saves.
>         (<unnamed>::find_first_std): Simplified implementation
>         benefiting from reordering of rules.
>         (chrono::reload_tzdb): Sort rules by name, from and save.
>         * testsuite/std/time/time_zone/wall_cascade.cc: New test.
>
> Reviewed-by: Tomasz Kamiński <[email protected]>
> Co-authored-by: Álvaro Begué <[email protected]>
> Signed-off-by: Tomasz Kamiński <[email protected]>
> Signed-off-by: Álvaro Begué <[email protected]>
>
>         (cherry picked from commits
> f7cde200320e0800e4fcc5cea399e9faef50f8d4)
>         (610134a51fa3d0bcd3e0980c6574557172dc88c0)
> ---
> This squashes "- seconds(1)" from the follow up (r17-2462-g610134a51fa3d0),
> and I have modified the first sentece of paragraph of commit description
> that starts with:
>  To address above we now consider rules triggering at info.begin...
>
> As mentioned in the follow up patch, this is now pure improvment in
> consistency with date library and reduces number of differences to
> 271 from 422 (after parsing/stop condition patches) and 635 (16.1)
> respectively.
>
> I have also tried to measure the performance impact on this change,
> but the difference is affecting only first query. So I have tried
> to measure the time it takes to iterate each Zone by sys_info
> (query end next) from year -5000 to 2000. This is not perfect
> as we expand follow up zones, but the best think I could come up
> with. The percante difference between state before/this patch
> as follows (PXX% is XX percentile):
> MIN      MED    P90%    P95%    P99%    MAX       AVG
> -60,56%  0.55%  46.42%  56.35%  80.4%%  175.46%   0.43%
>
I have attached the csv file that lists the results collected for all
zones.

>
> It's hard to make anything from this numbers, and we cannot really
> do repeated measurments. The Avarate is certainly acceptable, and
> that does not affect any following calls.
>
> (I believe the reduction come from the fact that finding first DST
> rule is now much quicker).
>
> As the original patch is on trunk since Jun 30, and the follow up
> is really small change, I think given above this is fine to backport.
>
> Tested on x86_64-linux locally and powerpc64le. OK for GCC-16?
>
>  libstdc++-v3/src/c++20/tzdb.cc                | 209 ++++++++++----
>  .../std/time/time_zone/wall_cascade.cc        | 273 ++++++++++++++++++
>  2 files changed, 425 insertions(+), 57 deletions(-)
>  create mode 100644
> libstdc++-v3/testsuite/std/time/time_zone/wall_cascade.cc
>
> diff --git a/libstdc++-v3/src/c++20/tzdb.cc
> b/libstdc++-v3/src/c++20/tzdb.cc
> index a1148355303..6af5768a58e 100644
> --- a/libstdc++-v3/src/c++20/tzdb.cc
> +++ b/libstdc++-v3/src/c++20/tzdb.cc
> @@ -689,6 +689,147 @@ namespace std::chrono
>        }
>  #endif
>      };
> +
> +    const Rule*
> +    find_active_rule(span<const Rule> rules, sys_seconds t, seconds
> std_offset)
> +    {
> +      struct Transition {
> +       const Rule* rule;
> +       sys_seconds when;
> +      };
> +
> +      const year_month_day date(chrono::floor<days>(t));
> +      // Expand the search window for a time near the end
> +      // of the year which can be pushed to next/previous
> +      // year by 'offset'. This assumes that 'offset' is
> +      // never greater than 24h.
> +      year first_year = date.year(), last_year = date.year();
> +      if (std_offset.count() > 0)
> +       if (date.month() == December && date.day() == day(31))
> +         ++last_year;
> +      if (std_offset.count() < 0)
> +       if (date.month() == January && date.day() == day(1))
> +         --first_year;
> +
> +      // Rule specifying start time as Wall time, should apply
> +      // running 'save' accumulated by earlier rules. To handle
> +      // that we firstly collect transitions surrounding specified
> +      // time t, ignoring the 'save':
> +      // * curr_tran - rule active directly before or at t,
> +      // * prev_tran - rule transition before curr_tran
> +      // * next_tran - rule transition directly after t
> +      Transition prev_tran{nullptr, sys_seconds::min()};
> +      Transition curr_tran{nullptr, sys_seconds::min()};
> +      Transition next_tran{nullptr, sys_seconds::max()};
> +      for (const auto& rule : rules)
> +       {
> +         if (last_year < rule.from) // Rule doesn't apply yet at time t.
> +           break; // Rules are ordered by 'from' in ascending order.
> +
> +         seconds offset{}; // appropriate for at_time::Universal
> +         if (rule.when.indicator == at_time::Wall
> +             || rule.when.indicator == at_time::Standard)
> +           offset = std_offset;
> +
> +         // Times at which rule takes affect before (or equal) t,
> +         // and after t, respectively.
> +         sys_seconds start_before = sys_seconds::min();
> +         sys_seconds start_after = sys_seconds::max();
> +         auto for_year = [&](year y)
> +         {
> +           // Time the rule takes effect on year y:
> +           const sys_seconds rule_start = rule.start_time(y, offset);
> +           if (rule_start <= t)
> +             {
> +               start_before = rule_start;
> +               if (y == last_year && rule.to > y)
> +                 start_after = rule.start_time(++y, offset);
> +             }
> +           // Do not override start_after set for first_year
> +           else if (rule_start < start_after)
> +             {
> +               start_after = rule_start;
> +               if (y == first_year && rule.from < y)
> +                 start_before = rule.start_time(--y, offset);
> +             }
> +         };
> +
> +         if (first_year > rule.to)
> +           // Rule no longer applies at time t, record last transition
> +            start_before = rule.start_time(rule.to, offset);
> +         else if (first_year == last_year)
> +           for_year(first_year);
> +         else
> +          {
> +            // Local time may of t may be in prev/next year.
> +            if (first_year >= rule.from)
> +              for_year(first_year);
> +            if (last_year <= rule.to)
> +              for_year(last_year);
> +          }
> +
> +         if (curr_tran.when < start_before)
> +           {
> +             prev_tran = curr_tran;
> +             curr_tran = {&rule, start_before};
> +           }
> +         else if (prev_tran.when < start_before)
> +           prev_tran = {&rule, start_before};
> +
> +         if (start_after < next_tran.when)
> +           next_tran = {&rule, start_after};
> +       }
> +
> +      // No rule was active at the time of t, running 'save'
> +      // cannot change this output, as we have no save to apply.
> +      if (!curr_tran.rule)
> +       return nullptr;
> +
> +      auto cascade_save = [](const Rule* from, Transition& to)
> +      {
> +       if (!from || from->save == seconds(0))
> +         return false;
> +       if (!to.rule || to.rule->when.indicator != at_time::Wall)
> +          return false;
> +       to.when -= from->save;
> +       return true;
> +      };
> +
> +      if (cascade_save(curr_tran.rule, next_tran))
> +       // Running save moved what we considered next_tran to time
> +       // before or at t, in that case next_tran is active rule.
> +       if (next_tran.when <= t)
> +         return next_tran.rule;
> +
> +      if (cascade_save(prev_tran.rule, curr_tran))
> +       // Running save moved what we consider curr_tran to
> +       // time after t, in that case prev_tran is active rule.
> +       if (curr_tran.when > t)
> +         return prev_tran.rule;
> +
> +      return curr_tran.rule;
> +    }
> +
> +    const Rule*
> +    find_first_std(span<const Rule> rules)
> +    {
> +      auto is_std = [](const Rule& rule) { return !rule.save.count(); };
> +      // Rules with same name are sorted by 'from' and then 'save' in
> ascending order.
> +      auto it = ranges::find_if(rules, is_std);
> +      if (it == rules.end())
> +       return nullptr;
> +
> +      const Rule* first = &*it;
> +      const year y = first->from;
> +      for (const Rule& next : span<const Rule>(++it, rules.end()))
> +       {
> +         if (!is_std(next) || next.from > y)
> +           break;
> +         if (next.start_time(y, {}) < first->start_time(y, {}))
> +           first = &next;
> +       }
> +      return first;
> +    }
>    } // namespace
>  #endif // TZDB_DISABLED
>
> @@ -877,70 +1018,17 @@ namespace std::chrono
>
>      if (letters.empty())
>        {
> -       sys_seconds t = info.begin - seconds(1);
> -       const year_month_day date(chrono::floor<days>(t));
> -
>         // Try to find a Rule active before this time, to get initial
>         // SAVE and LETTERS values. There may not be a Rule for the period
>         // before the first DST transition, so find the earliest DST->STD
>         // transition and use the LETTERS from that.
> -       const Rule* active_rule = nullptr;
> -       sys_seconds active_rule_start = sys_seconds::min();
> -       const Rule* first_std = nullptr;
> -       for (const auto& rule : rules)
> -         {
> -           if (rule.save == minutes(0))
> -             {
> -               if (!first_std)
> -                 first_std = &rule;
> -               else if (rule.from < first_std->from)
> -                 first_std = &rule;
> -               else if (rule.from == first_std->from)
> -                 {
> -                   if (rule.start_time(rule.from, {})
> -                         < first_std->start_time(first_std->from, {}))
> -                     first_std = &rule;
> -                 }
> -             }
> -
> -           year y = date.year();
> -
> -           if (y > rule.to) // rule no longer applies at time t
> -             continue;
> -           if (y < rule.from) // rule doesn't apply yet at time t
> -             continue;
> -
> -           sys_seconds rule_start;
> -
> -           seconds offset{}; // appropriate for at_time::Universal
> -           if (rule.when.indicator == at_time::Wall)
> -             offset = info.offset;
> -           else if (rule.when.indicator == at_time::Standard)
> -             offset = ri.offset();
> -
> -           // Time the rule takes effect this year:
> -           rule_start = rule.start_time(y, offset);
> -
> -           if (rule_start >= t && rule.from < y)
> -             {
> -               // Try this rule in the previous year.
> -               rule_start = rule.start_time(--y, offset);
> -             }
> -
> -           if (active_rule_start < rule_start && rule_start < t)
> -             {
> -               active_rule_start = rule_start;
> -               active_rule = &rule;
> -             }
> -         }
> -
> -       if (active_rule)
> +       if (const Rule* active_rule = find_active_rule(rules, info.begin,
> ri.offset()))
>           {
>             info.offset = ri.offset() + active_rule->save;
>             info.save = chrono::duration_cast<minutes>(active_rule->save);
>             letters = active_rule->letters;
>           }
> -       else if (first_std)
> +       else if (const Rule* first_std = find_first_std(rules))
>           letters = first_std->letters;
>        }
>
> @@ -1828,7 +1916,14 @@ constinit tzdb_list::_Node::NumLeapSeconds
> tzdb_list::_Node::num_leap_seconds;
>
>      ranges::sort(node->db.zones, {}, &time_zone::name);
>      ranges::sort(node->db.links, {}, &time_zone_link::name);
> -    ranges::stable_sort(node->rules, {}, &Rule::name);
> +    ranges::sort(node->rules, [](const Rule& lhs, const Rule& rhs)
> +    {
> +      if (auto result = lhs.name <=> rhs.name; result != 0)
> +       return result < 0;
> +      if (auto result = lhs.from <=> rhs.from; result != 0)
> +       return result < 0;
> +      return lhs.save < rhs.save;
> +    });
>
>      return Node::_S_replace_head(std::move(head), std::move(node));
>  #else
> @@ -2441,7 +2536,7 @@ constinit tzdb_list::_Node::NumLeapSeconds
> tzdb_list::_Node::num_leap_seconds;
>             {
>               if (c = in.get(); c == '<' || c == '>')
>                 if (in.get() == '=')
> -                 if (unsigned d; (in >> d) && (d <= 31)) [[likely]]
> +                 if (unsigned d; (in >> d) && (d <= 31)) [[likely]]
>                     {
>                       on.kind = c == '<' ? LessEq : GreaterEq;
>                       on.day_of_week = w.wd.c_encoding();
> diff --git a/libstdc++-v3/testsuite/std/time/time_zone/wall_cascade.cc
> b/libstdc++-v3/testsuite/std/time/time_zone/wall_cascade.cc
> new file mode 100644
> index 00000000000..3529c2de852
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/std/time/time_zone/wall_cascade.cc
> @@ -0,0 +1,273 @@
> +// { dg-do run { target c++20 } }
> +// { dg-require-effective-target tzdb }
> +// { dg-require-effective-target cxx11_abi }
> +// { dg-xfail-run-if "no weak override on AIX" { powerpc-ibm-aix* } }
> +
> +// Wall-time rules in the same rule set whose effective firing time
> +// depends on a prior rule's save (Europe/Paris 1945):
> +//   1945 Apr 2  02:00 wall  save=2  M
> +//   1945 Sep 16 03:00 wall  save=0  -
> +// In the (stdoff=1, save=2) frame the September rule fires at
> +// Sep 16 00:00 UT, not Sep 16 02:00 UT.
> +
> +#include <chrono>
> +#include <fstream>
> +#include <testsuite_hooks.h>
> +
> +static bool override_used = false;
> +
> +namespace __gnu_cxx
> +{
> +  const char* zoneinfo_dir_override() {
> +    override_used = true;
> +    return "./";
> +  }
> +}
> +
> +using namespace std::chrono;
> +
> +void
> +test_positive()
> +{
> +  // Line 1 ends at "1945 Sep 16 1u" (Universal time, no save
> shenanigans),
> +  // so info.begin for line 2 is exactly 1945-09-16 01:00 UT.
> +  //
> +  // Two-line zone whose second line begins at 1945 Sep 16 01:00 UT,
> +  // between the cascaded firing time (Sep 16 00:00 UT) and the
> +  // non-cascaded firing time (Sep 16 02:00 UT) of the September rule.
> +  // The seeding must pick the September rule (save=0, CET) at info.begin.
> +  std::ofstream("tzdata.zi") << R"(# version test_wall_cascade
> +R Fr 1945 o - Apr 2  2 2 M
> +R Fr 1945 o - Sep 16 3 0 -
> +Z Test/Paris 0  -  X     1945 Sep 16 1u
> +             1  Fr CE%sT
> +)";
> +
> +  const auto& db = reload_tzdb();
> +  VERIFY( override_used ); // If this fails then XFAIL for the target.
> +  VERIFY( db.version == "test_wall_cascade" );
> +
> +  auto* tz = locate_zone("Test/Paris");
> +
> +  // Line 2 begins at exactly 1945-09-16 01:00 UT.  Sample one second
> +  // after the boundary, well inside line 2's first sys_info.
> +  auto info = tz->get_info(sys_seconds{
> +      sys_days(1945y/September/16) + 1h + 1s});
> +  VERIFY( info.offset == 1h );
> +  VERIFY( info.save == 0min );
> +  VERIFY( info.abbrev == "CET" );
> +
> +  // The boundary instant itself is in the new line.
> +  auto at_boundary
> +    = tz->get_info(sys_seconds{sys_days(1945y/September/16) + 1h});
> +  VERIFY( at_boundary.offset == 1h );
> +  VERIFY( at_boundary.save == 0min );
> +
> +  // Sample later still in line 2 (winter): unchanged.
> +  auto winter = tz->get_info(sys_days(1945y/December/1));
> +  VERIFY( winter.offset == 1h );
> +  VERIFY( winter.save == 0min );
> +}
> +
> +void
> +test_negative()
> +{
> +  // This is synthetic version of above example, with negative
> +  // running save.
> +  //
> +  // Two-line zone whose second line begins at 1945 Sep 16 01:00 UT,
> +  // before the cascaded firing time (Sep 16 02:00 UT), but after
> +  // non-cascaded firing time (Sep 16 00:00 UT) of the September rule.
> +  // The seeding must pick the April rule (save=-2, CEST) at info.begin.
> +  std::ofstream("tzdata.zi") << R"(# version test_negative_cascade
> +R Fr 1945 o - Apr 2  2 -3 M
> +R Fr 1945 o - Sep 16 0 0 -
> +Z Test/Negative 0  -  X     1945 Sep 16 1u
> +             1  Fr CE%sT
> +)";
> +
> +  const auto& db = reload_tzdb();
> +  VERIFY( override_used ); // If this fails then XFAIL for the target.
> +  VERIFY( db.version == "test_negative_cascade" );
> +
> +  auto* tz = locate_zone("Test/Negative");
> +
> +  // Line 2 begins at exactly 1945-09-16 01:00 UT, sample
> +  // one second after.
> +  auto info = tz->get_info(sys_seconds{
> +      sys_days(1945y/September/16) + 1h + 1s});
> +  VERIFY( info.offset == -2h );
> +  VERIFY( info.save == -3h );
> +  VERIFY( info.abbrev == "CEMT" );
> +
> +  // The boundary instant.
> +  auto at_boundary
> +    = tz->get_info(sys_seconds{sys_days(1945y/September/16) + 1h});
> +  VERIFY( at_boundary.offset == -2h );
> +  VERIFY( at_boundary.save == -3h );
> +
> +  // Test the firing of Sep 16 rule
> +  auto at_sep_rule = tz->get_info(sys_seconds{
> +    sys_days(1945y/September/16) + 2h});
> +  // The transition_window < 1d condition triggers, and
> +  // transition is ignored.
> +  // VERIFY( at_sep_rule.offset == 1h );
> +  // VERIFY( at_sep_rule.save == 0h );
> +  // VERIFY( at_sep_rule.abbrev == "CET" );
> +}
> +
> +void
> +test_next_year()
> +{
> +  // The NZ 1946 rule triggers at 1946 Jan 1 00:00:00
> +  // local time, which correspond to 1946 Dec 13 12:00:00 UT.
> +  std::ofstream("tzdata.zi") << R"(# version test_next_year
> +R NZ 1934 1940 - Ap lastSu 2 0 M
> +R NZ 1934 1940 - S lastSu 2 0:30 S
> +R NZ 1946 o - Ja 1 0 0 S
> +Z Pacific/Auckland 11:39:4 - LMT 1868 N 2
> +11:30 NZ NZ%sT 1946
> +12 NZ NZ%sT
> +Z Pacific/AucklandUT 11:39:4 - LMT 1868 N 2
> +11:30 NZ NZ%sT 1945 Dec 31 13u
> +12 NZ NZ%sT
> +)";
> +
> +  const auto& db = reload_tzdb();
> +  VERIFY( override_used ); // If this fails then XFAIL for the target.
> +  VERIFY( db.version == "test_next_year" );
> +
> +  // Pacific/Auckland requires both PR124854 and PR116110 to work
> +  // correctly. TODO test it once implemented.
> +  // The UT version uses 1945-12-31 13:00:00 UT after
> +  // the rule application change.
> +  auto* utz = locate_zone("Pacific/AucklandUT");
> +
> +  // Before the change
> +  auto before_utboundary
> +   = utz->get_info(sys_seconds{sys_days(1945y/December/31) + 11h});
> +  VERIFY( before_utboundary.offset == 12h );
> +  VERIFY( before_utboundary.save == 30min );
> +  VERIFY( before_utboundary.abbrev == "NZST" );
> +
> +  auto at_utboundary
> +    = utz->get_info(sys_seconds{sys_days(1945y/December/31) + 13h});
> +  VERIFY( at_utboundary.offset == 12h );
> +  VERIFY( at_utboundary.save == 0h );
> +  VERIFY( at_utboundary.abbrev == "NZST" );
> +
> +  auto after_utboundary
> +    = utz->get_info(sys_seconds{sys_days(1945y/December/31) + 14h});
> +  VERIFY( after_utboundary.offset == 12h );
> +  VERIFY( after_utboundary.save == 0h );
> +  VERIFY( after_utboundary.abbrev == "NZST" );
> +}
> +
> +void
> +test_prev_year()
> +{
> +  // The synthetic version of above, where the local
> +  // time for rule is moved to previous year.
> +  // The NZ 1946 rule triggers at 1946 Dec 31 22:00:00
> +  // local time, which correspond to 1947 Jan 1 10:00:00 UT.
> +  std::ofstream("tzdata.zi") << R"(# version test_prev_year
> +R PY 1934 1940 - Ap lastSu 2 0 M
> +R PY 1934 1940 - S lastSu 2 0:30 S
> +R PY 1946 o - D 31 22 0 S
> +Z Test/PrevYear -11:39:4 - LMT 1868 N 2
> +-12:30 PY PY%sT 1947 Jan 1 11u
> +-12 PY PY%sT
> +)";
> +
> +  const auto& db = reload_tzdb();
> +  VERIFY( override_used ); // If this fails then XFAIL for the target.
> +  VERIFY( db.version == "test_prev_year" );
> +
> +  // The UT version uses 1945-12-31 13:00:00 UT after
> +  // the rule application change.
> +  auto* tz = locate_zone("Test/PrevYear");
> +
> +  // Before the change
> +  auto before_boundary
> +   = tz->get_info(sys_seconds{sys_days(1947y/January/1) + 9h});
> +  VERIFY( before_boundary.offset == -12h );
> +  VERIFY( before_boundary.save == 30min );
> +  VERIFY( before_boundary.abbrev == "PYST" );
> +
> +  auto at_boundary
> +    = tz->get_info(sys_seconds{sys_days(1947y/January/1) + 11h});
> +  VERIFY( at_boundary.offset == -12h );
> +  VERIFY( at_boundary.save == 0h );
> +  VERIFY( at_boundary.abbrev == "PYST" );
> +
> +  auto after_boundary
> +    = tz->get_info(sys_seconds{sys_days(1947y/January/1) + 12h});
> +  VERIFY( after_boundary.offset == -12h );
> +  VERIFY( after_boundary.save == 0h );
> +  VERIFY( after_boundary.abbrev == "PYST" );
> +}
> +
> +void
> +test_earlier_year()
> +{
> +  // Synthetic example where PY 1941 rule is still running.
> +  std::ofstream("tzdata.zi") << R"(# version test_earlier_year
> +R EY 1934 1941 - Ap lastSu 2 0 M
> +R EY 1934 1940 - S lastSu 2 0:30 S
> +Z Test/EarielYear 11:39:4 - LMT 1868 N 2
> +11:30 EY EY%sT 1943 Jan 1 12u
> +12 EY EY%sT
> +   )";
> +
> +  const auto& db = reload_tzdb();
> +  VERIFY( override_used ); // If this fails then XFAIL for the target.
> +  VERIFY( db.version == "test_earlier_year" );
> +
> +  auto* utz = locate_zone("Test/EarielYear");
> +  auto at_boundary
> +    = utz->get_info(sys_seconds{sys_days(1943y/January/1) + 12h});
> +  VERIFY( at_boundary.offset == 12h );
> +  VERIFY( at_boundary.save == 0min );
> +  VERIFY( at_boundary.abbrev == "EYMT" );
> +}
> +
> +void
> +test_at_boundary()
> +{
> +  std::ofstream("tzdata.zi") << R"(# version test_at_boundary
> +R p 1947 1966 - Ap Su>=1 2s 1 S
> +R p 1947 1965 - O Su>=1 2s 0 -
> +R p 1976 o - S lastSu 1 0 -
> +R p 1977 o - Mar lastSu 0s 1 S
> +R p 1977 o - S lastSu 0s 0 -
> +Z Europe/Lisbon -0:36:45 - LMT 1884
> +1 - CET 1976 S 26 1
> +0 p WE%sT 1986
> +   )";
> +
> +  const auto& db = reload_tzdb();
> +  VERIFY( override_used ); // If this fails then XFAIL for the target.
> +  VERIFY( db.version == "test_at_boundary" );
> +
> +  // The change from CET to WE%sT line happens 1976 Sep 26 00:00:00 UT,
> +  // should take into consideration 1976 lastSu rule that fires at the
> +  // same time (running save is 1h from 1966 Ap rule application),
> +  // and start in standard time (WET period).
> +  auto* utz = locate_zone("Europe/Lisbon");
> +  auto at_boundary
> +    = utz->get_info(sys_seconds{sys_days(1976y/September/26) + 0h});
> +  VERIFY( at_boundary.offset == 0h );
> +  VERIFY( at_boundary.save == 0min );
> +  VERIFY( at_boundary.abbrev == "WET" );
> +}
> +
> +int
> +main()
> +{
> +  test_positive();
> +  test_negative();
> +  test_next_year();
> +  test_prev_year();
> +  test_earlier_year();
> +  test_at_boundary();
> +}
> --
> 2.55.0
>
>
AVG 21121 21020 -101 0.43%
MIN 610 629 -45836 -60.56%
MEDIAN 16909 18205 23 0.55%
P90% 49874 48489 7018 46.42%
P95% 64902 57982 12983 56.35%
P99% 86505 97889 26668 80.48%
MAX 131650 133930 39195 175.46%
Africa/Abidjan 2545 1265 -1280 -50.29%
Africa/Accra 1322 1304 -18 -1.36%
Africa/Addis_Ababa 3398 2283 -1115 -32.81%
Africa/Algiers 14702 15182 480 3.26%
Africa/Asmara 3112 1421 -1691 -54.34%
Africa/Asmera 2530 2098 -432 -17.08%
Africa/Bamako 1240 1260 20 1.61%
Africa/Bangui 1717 1778 61 3.55%
Africa/Banjul 1298 1316 18 1.39%
Africa/Bissau 1231 925 -306 -24.86%
Africa/Blantyre 1265 1355 90 7.11%
Africa/Brazzaville 1541 1940 399 25.89%
Africa/Bujumbura 1202 1320 118 9.82%
Africa/Cairo 67264 68101 837 1.24%
Africa/Casablanca 67714 68462 748 1.10%
Africa/Ceuta 24477 26193 1716 7.01%
Africa/Conakry 1283 1291 8 0.62%
Africa/Dakar 1306 1332 26 1.99%
Africa/Dar_es_Salaam 2467 2039 -428 -17.35%
Africa/Djibouti 2513 2072 -441 -17.55%
Africa/Douala 1651 1196 -455 -27.56%
Africa/El_Aaiun 58339 56374 -1965 -3.37%
Africa/Freetown 818 898 80 9.78%
Africa/Gaborone 1307 790 -517 -39.56%
Africa/Harare 844 1268 424 50.24%
Africa/Johannesburg 5027 5225 198 3.94%
Africa/Juba 9658 9614 -44 -0.46%
Africa/Kampala 1818 1290 -528 -29.04%
Africa/Khartoum 12731 13659 928 7.29%
Africa/Kigali 1355 1265 -90 -6.64%
Africa/Kihasa 1616 1858 242 14.98%
Africa/Lagos 2310 1530 -780 -33.77%
Africa/Libreville 1701 1339 -362 -21.28%
Africa/Lome 768 788 20 2.60%
Africa/Luanda 1499 1922 423 28.22%
Africa/Lubumbashi 1243 1282 39 3.14%
Africa/Lusaka 881 1209 328 37.23%
Africa/Malabo 2281 1305 -976 -42.79%
Africa/Maputo 864 775 -89 -10.30%
Africa/Maseru 4156 3562 -594 -14.29%
Africa/Mbabane 3058 5096 2038 66.64%
Africa/Mogadishu 1538 2147 609 39.60%
Africa/Monrovia 939 1543 604 64.32%
Africa/Nairobi 2623 1442 -1181 -45.02%
Africa/Ndjamena 1008 1070 62 6.15%
Africa/Niamey 1729 1286 -443 -25.62%
Africa/Nouakchott 748 1290 542 72.46%
Africa/Ouagadougou 783 845 62 7.92%
Africa/Porto-Novo 1521 1867 346 22.75%
Africa/Sao_Tome 1203 1200 -3 -0.25%
Africa/Timbuktu 758 920 162 21.37%
Africa/Tripoli 12741 12328 -413 -3.24%
Africa/Tunis 11779 13268 1489 12.64%
Africa/Windhoek 16876 16429 -447 -2.65%
America/Adak 27649 55904 28255 102.19%
America/Anchorage 41269 31601 -9668 -23.43%
America/Anguilla 4030 3947 -83 -2.06%
America/Antigua 5862 3582 -2280 -38.89%
America/Araguaina 29107 41188 12081 41.51%
America/Argentina/Buenos_Aires 33499 32790 -709 -2.12%
America/Argentina/Catamarca 23064 22014 -1050 -4.55%
America/Argentina/ComodRivadavia 34442 23618 -10824 -31.43%
America/Argentina/Cordoba 24963 23353 -1610 -6.45%
America/Argentina/Jujuy 21415 34129 12714 59.37%
America/Argentina/La_Rioja 34126 22514 -11612 -34.03%
America/Argentina/Mendoza 34361 33099 -1262 -3.67%
America/Argentina/Rio_Gallegos 21073 20671 -402 -1.91%
America/Argentina/Salta 34200 22960 -11240 -32.87%
America/Argentina/San_Juan 23428 23328 -100 -0.43%
America/Argentina/San_Luis 21521 22697 1176 5.46%
America/Argentina/Tucuman 38701 22761 -15940 -41.19%
America/Argentina/Ushuaia 33630 33902 272 0.81%
America/Aruba 4032 3590 -442 -10.96%
America/Asuncion 48003 32999 -15004 -31.26%
America/Atikokan 905 990 85 9.39%
America/Atka 28019 43865 15846 56.55%
America/Bahia 47969 29484 -18485 -38.54%
America/Bahia_Banderas 21173 21640 467 2.21%
America/Barbados 8937 8942 5 0.06%
America/Belem 27784 26729 -1055 -3.80%
America/Belize 22853 22084 -769 -3.36%
America/Blanc-Sablon 3709 5433 1724 46.48%
America/Boa_Vista 31472 19190 -12282 -39.03%
America/Bogota 4775 2987 -1788 -37.45%
America/Boise 30272 43806 13534 44.71%
America/Buenos_Aires 21109 33415 12306 58.30%
America/Cambridge_Bay 27521 26787 -734 -2.67%
America/Campo_Grande 38235 54401 16166 42.28%
America/Cancun 11461 17967 6506 56.77%
America/Caracas 2561 1468 -1093 -42.68%
America/Catamarca 26294 21989 -4305 -16.37%
America/Cayenne 1315 1740 425 32.32%
America/Cayman 1032 895 -137 -13.28%
America/Chicago 64800 72200 7400 11.42%
America/Chihuahua 14585 21385 6800 46.62%
America/Ciudad_Juarez 28371 20027 -8344 -29.41%
America/Coral_Harbour 842 862 20 2.38%
America/Cordoba 22213 34966 12753 57.41%
America/Costa_Rica 5823 4893 -930 -15.97%
America/Coyhaique 83041 46137 -36904 -44.44%
America/Creston 6300 9740 3440 54.60%
America/Cuiaba 57754 35942 -21812 -37.77%
America/Curacao 3745 3369 -376 -10.04%
America/Danmarkshavn 13243 14945 1702 12.85%
America/Dawson 23681 22073 -1608 -6.79%
America/Dawson_Creek 20894 15684 -5210 -24.94%
America/Denver 35283 48096 12813 36.31%
America/Detroit 41328 28024 -13304 -32.19%
America/Dominica 3704 3538 -166 -4.48%
America/Edmonton 26924 41901 14977 55.63%
America/Eirunepe 22437 19983 -2454 -10.94%
America/El_Salvador 4735 5055 320 6.76%
America/Eenada 34213 52955 18742 54.78%
America/Fort_Nelson 41025 27569 -13456 -32.80%
America/Fort_Wayne 23120 23859 739 3.20%
America/Fortaleza 22306 34476 12170 54.56%
America/Glace_Bay 28753 28850 97 0.34%
America/Godthab 34847 57504 22657 65.02%
America/Goose_Bay 44527 70276 25749 57.83%
America/Grand_Turk 32492 21526 -10966 -33.75%
America/Grenada 3801 3631 -170 -4.47%
America/Guadeloupe 4067 5598 1531 37.64%
America/Guatemala 6384 4664 -1720 -26.94%
America/Guayaquil 3142 5008 1866 59.39%
America/Guyana 1550 2025 475 30.65%
America/Halifax 79565 53743 -25822 -32.45%
America/Havana 46934 43774 -3160 -6.73%
America/Hermosillo 6215 9282 3067 49.35%
America/Indiana/Indianapolis 22783 23292 509 2.23%
America/Indiana/Knox 46788 47565 777 1.66%
America/Indiana/Marengo 21877 34091 12214 55.83%
America/Indiana/Petersburg 37463 24866 -12597 -33.63%
America/Indiana/Tell_City 22706 22142 -564 -2.48%
America/Indiana/Vevay 26558 26036 -522 -1.97%
America/Indiana/Vincennes 26036 23935 -2101 -8.07%
America/Indiana/Winamac 33771 35009 1238 3.67%
America/Indianapolis 22266 32692 10426 46.82%
America/Inuvik 26748 23734 -3014 -11.27%
America/Iqaluit 27008 24885 -2123 -7.86%
America/Jamaica 8043 12633 4590 57.07%
America/Jujuy 22815 23044 229 1.00%
America/Juneau 42622 43069 447 1.05%
America/Kentucky/Louisville 33392 52416 19024 56.97%
America/Kentucky/Monticello 42648 28836 -13812 -32.39%
America/Knox_IN 32505 47560 15055 46.32%
America/Kralendijk 3763 5360 1597 42.44%
America/La_Paz 2248 1271 -977 -43.46%
America/Lima 10057 10218 161 1.60%
America/Los_Angeles 33543 38790 5247 15.64%
America/Louisville 51381 36286 -15095 -29.38%
America/Lower_Princes 3788 5605 1817 47.97%
America/Maceio 24356 25793 1437 5.90%
America/Managua 7601 8006 405 5.33%
America/Manaus 31196 29949 -1247 -4.00%
America/Marigot 3620 3601 -19 -0.52%
America/Martinique 1667 996 -671 -40.25%
America/Matamoros 17971 19833 1862 10.36%
America/Mazatlan 15256 14834 -422 -2.77%
America/Mendoza 21616 33171 11555 53.46%
America/Menominee 40882 41663 781 1.91%
America/Merida 12363 13169 806 6.52%
America/Metlakatla 31990 18898 -13092 -40.93%
America/Mexico_City 16942 24283 7341 43.33%
America/Miquelon 22300 22141 -159 -0.71%
America/Moncton 40175 60238 20063 49.94%
America/Monterrey 21441 21997 556 2.59%
America/Montevideo 34877 34750 -127 -0.36%
America/Montreal 68036 76110 8074 11.87%
America/Montserrat 3862 6966 3104 80.37%
America/Nassau 47523 52446 4923 10.36%
America/New_York 42805 71337 28532 66.66%
America/Nipigon 69110 52224 -16886 -24.43%
America/Nome 27386 29562 2176 7.95%
America/Noronha 36120 25107 -11013 -30.49%
America/North_Dakota/Beulah 29076 43388 14312 49.22%
America/North_Dakota/Center 28957 29763 806 2.78%
America/North_Dakota/New_Salem 42845 42847 2 0.00%
America/Nuuk 34854 27159 -7695 -22.08%
America/Ojinaga 19961 21941 1980 9.92%
America/Panama 1650 1020 -630 -38.18%
America/Pangnirtung 28319 28347 28 0.10%
America/Paramaribo 1464 1352 -112 -7.65%
America/Phoenix 10157 7204 -2953 -29.07%
America/Port-au-Prince 28839 21590 -7249 -25.14%
America/Port_of_Spain 3399 3549 150 4.41%
America/Porto_Acre 28254 19492 -8762 -31.01%
America/Porto_Velho 18484 26871 8387 45.37%
America/Puerto_Rico 3887 3946 59 1.52%
America/Punta_Arenas 81825 49043 -32782 -40.06%
America/Rainy_River 52691 38550 -14141 -26.84%
America/Rankin_Inlet 23544 24466 922 3.92%
America/Recife 35510 44484 8974 25.27%
America/Regina 14702 24117 9415 64.04%
America/Resolute 23878 25287 1409 5.90%
America/Rio_Branco 27979 18979 -9000 -32.17%
America/Rosario 34311 23509 -10802 -31.48%
America/Santa_Isabel 33961 35275 1314 3.87%
America/Santarem 18443 25841 7398 40.11%
America/Santiago 58706 54752 -3954 -6.74%
America/Santo_Domingo 6079 6816 737 12.12%
America/Sao_Paulo 39871 40523 652 1.64%
America/Scoresbysund 35637 35908 271 0.76%
America/Shiprock 31315 31430 115 0.37%
America/Sitka 29601 43334 13733 46.39%
America/St_Barthelemy 4130 5536 1406 34.04%
America/St_Joh 53719 64045 10326 19.22%
America/St_Kitts 5834 3914 -1920 -32.91%
America/St_Lucia 5763 4066 -1697 -29.45%
America/St_Thomas 3688 3515 -173 -4.69%
America/St_Vincent 3790 5481 1691 44.62%
America/Swift_Current 10006 13824 3818 38.16%
America/Tegucigalpa 3657 4427 770 21.06%
America/Thule 17799 19570 1771 9.95%
America/Thunder_Bay 68710 54693 -14017 -20.40%
America/Tijuana 34189 37138 2949 8.63%
America/Toronto 47915 74555 26640 55.60%
America/Tortola 4062 5482 1420 34.96%
America/Vancouver 29570 33283 3713 12.56%
America/Virgin 5717 3942 -1775 -31.05%
America/Whitehorse 30431 29727 -704 -2.31%
America/Winnipeg 40283 36492 -3791 -9.41%
America/Yakutat 28833 41491 12658 43.90%
America/Yellowknife 28898 41229 12331 42.67%
Antarctica/Casey 2867 2722 -145 -5.06%
Antarctica/Davis 2737 1585 -1152 -42.09%
Antarctica/DumontDUrville 1991 1568 -423 -21.25%
Antarctica/Macquarie 34736 37957 3221 9.27%
Antarctica/Mawson 1438 1633 195 13.56%
Antarctica/McMurdo 33622 49654 16032 47.68%
Antarctica/Palmer 32296 33871 1575 4.88%
Antarctica/Rothera 1164 930 -234 -20.10%
Antarctica/South_Pole 49962 48873 -1089 -2.18%
Antarctica/Syowa 1229 960 -269 -21.89%
Antarctica/Troll 13391 19084 5693 42.51%
Antarctica/Vostok 1609 1790 181 11.25%
Arctic/Longyearbyen 27771 32056 4285 15.43%
Asia/Aden 1950 1122 -828 -42.46%
Asia/Almaty 21182 20985 -197 -0.93%
Asia/Amman 27020 43542 16522 61.15%
Asia/Anadyr 18439 24919 6480 35.14%
Asia/Aqtau 14420 39721 25301 175.46%
Asia/Aqtobe 13978 16170 2192 15.68%
Asia/Ashgabat 8589 12975 4386 51.07%
Asia/Ashkhabad 13015 8940 -4075 -31.31%
Asia/Atyrau 14461 14599 138 0.95%
Asia/Baghdad 15073 14294 -779 -5.17%
Asia/Bahrain 1410 1637 227 16.10%
Asia/Baku 16972 18411 1439 8.48%
Asia/Bangkok 2302 1649 -653 -28.37%
Asia/Barnaul 25500 19614 -5886 -23.08%
Asia/Beirut 26038 26281 243 0.93%
Asia/Bishkek 16418 21854 5436 33.11%
Asia/Brunei 6996 8836 1840 26.30%
Asia/Calcutta 2027 1524 -503 -24.81%
Asia/Chita 29084 24995 -4089 -14.06%
Asia/Choibalsan 22264 14481 -7783 -34.96%
Asia/Chongqing 8396 8670 274 3.26%
Asia/Chungking 11040 13328 2288 20.72%
Asia/Colombo 2154 2580 426 19.78%
Asia/Dacca 4135 3782 -353 -8.54%
Asia/Damascus 63673 56109 -7564 -11.88%
Asia/Dhaka 6085 3532 -2553 -41.96%
Asia/Dili 1474 1222 -252 -17.10%
Asia/Dubai 1326 1435 109 8.22%
Asia/Dushanbe 9056 12133 3077 33.98%
Asia/Famagusta 25068 28384 3316 13.23%
Asia/Gaza 131129 120672 -10457 -7.97%
Asia/Harbin 9060 9468 408 4.50%
Asia/Hebron 73572 76193 2621 3.56%
Asia/Ho_Chi_Minh 2106 2425 319 15.15%
Asia/Hong_Kong 18370 19656 1286 7.00%
Asia/Hovd 14182 15306 1124 7.93%
Asia/Irkutsk 17729 18571 842 4.75%
Asia/Istanbul 54526 39687 -14839 -27.21%
Asia/Jakarta 2016 1888 -128 -6.35%
Asia/Jayapura 1490 1832 342 22.95%
Asia/Jerusalem 46093 49461 3368 7.31%
Asia/Kabul 1311 1284 -27 -2.06%
Asia/Kamchatka 17827 18483 656 3.68%
Asia/Karachi 8300 5051 -3249 -39.14%
Asia/Kashgar 1189 1003 -186 -15.64%
Asia/Kathmandu 1371 1259 -112 -8.17%
Asia/Katmandu 1503 1103 -400 -26.61%
Asia/Khandyga 18194 20545 2351 12.92%
Asia/Kolkata 2658 1608 -1050 -39.50%
Asia/Krasnoyarsk 24512 17618 -6894 -28.13%
Asia/Kuala_Lumpur 2071 1963 -108 -5.21%
Asia/Kuching 7649 8910 1261 16.49%
Asia/Kuwait 1260 1142 -118 -9.37%
Asia/Macao 22127 25480 3353 15.15%
Asia/Macau 35753 24456 -11297 -31.60%
Asia/Magadan 24164 17786 -6378 -26.39%
Asia/Makassar 1496 1191 -305 -20.39%
Asia/Manila 6989 8623 1634 23.38%
Asia/Muscat 1245 979 -266 -21.37%
Asia/Nicosia 23514 26822 3308 14.07%
Asia/Novokuznetsk 16672 17580 908 5.45%
Asia/Novosibirsk 25536 18598 -6938 -27.17%
Asia/Omsk 16471 17435 964 5.85%
Asia/Oral 14309 20608 6299 44.02%
Asia/Phnom_Penh 1372 1081 -291 -21.21%
Asia/Pontianak 1978 1796 -182 -9.20%
Asia/Pyongyang 1076 1760 684 63.57%
Asia/Qatar 2102 1009 -1093 -52.00%
Asia/Qostanay 13397 14397 1000 7.46%
Asia/Qyzylorda 15742 21581 5839 37.09%
Asia/Rangoon 1672 1385 -287 -17.17%
Asia/Riyadh 1135 1003 -132 -11.63%
Asia/Saigon 3018 1770 -1248 -41.35%
Asia/Sakhalin 25439 18596 -6843 -26.90%
Asia/Samarkand 7881 8358 477 6.05%
Asia/Seoul 10777 14875 4098 38.03%
Asia/Shanghai 9189 10174 985 10.72%
Asia/Singapore 2032 1877 -155 -7.63%
Asia/Srednekolymsk 29570 18719 -10851 -36.70%
Asia/Taipei 14748 10792 -3956 -26.82%
Asia/Tashkent 8514 9076 562 6.60%
Asia/Tbilisi 17558 24666 7108 40.48%
Asia/Tehran 23450 24134 684 2.92%
Asia/Tel_Aviv 43278 49655 6377 14.73%
Asia/Thimbu 1370 1190 -180 -13.14%
Asia/Thimphu 2231 1082 -1149 -51.50%
Asia/Tokyo 4119 5049 930 22.58%
Asia/Tomsk 18843 19460 617 3.27%
Asia/Ujung_Pandang 1545 1333 -212 -13.72%
Asia/Ulaanbaatar 13665 15510 1845 13.50%
Asia/Ulan_Bator 21552 21488 -64 -0.30%
Asia/Urumqi 1825 939 -886 -48.55%
Asia/Ust-Nera 17019 18611 1592 9.35%
Asia/Vientiane 2109 1611 -498 -23.61%
Asia/Vladivostok 18947 18475 -472 -2.49%
Asia/Yakutsk 16515 18995 2480 15.02%
Asia/Yangon 2606 2025 -581 -22.29%
Asia/Yekaterinburg 25238 17601 -7637 -30.26%
Asia/Yerevan 17000 18096 1096 6.45%
Atlantic/Azores 66857 102814 35957 53.78%
Atlantic/Bermuda 32338 32494 156 0.48%
Atlantic/Canary 19768 26843 7075 35.79%
Atlantic/Cape_Verde 2425 1867 -558 -23.01%
Atlantic/Faeroe 28346 19582 -8764 -30.92%
Atlantic/Faroe 19530 19989 459 2.35%
Atlantic/Jan_Mayen 29570 41296 11726 39.66%
Atlantic/Madeira 60128 65559 5431 9.03%
Atlantic/Reykjavik 748 853 105 14.04%
Atlantic/South_Georgia 1968 1535 -433 -22.00%
Atlantic/St_Helena 1225 734 -491 -40.08%
Atlantic/Stanley 19662 19190 -472 -2.40%
Australia/ACT 33569 36211 2642 7.87%
Australia/Adelaide 30466 32203 1737 5.70%
Australia/Brisbane 7095 8435 1340 18.89%
Australia/Broken_Hill 53218 38298 -14920 -28.04%
Australia/Canberra 51180 37163 -14017 -27.39%
Australia/Currie 61207 39206 -22001 -35.95%
Australia/Darwin 5080 7941 2861 56.32%
Australia/Eucla 11891 9014 -2877 -24.19%
Australia/Hobart 37324 40808 3484 9.33%
Australia/LHI 43084 42638 -446 -1.04%
Australia/Lindeman 14046 8950 -5096 -36.28%
Australia/Lord_Howe 28703 29779 1076 3.75%
Australia/Melbourne 33176 49744 16568 49.94%
Australia/W 31974 35407 3433 10.74%
Australia/North 8896 5707 -3189 -35.85%
Australia/Perth 13041 8645 -4396 -33.71%
Australia/Queeland 6867 7585 718 10.46%
Australia/South 30677 31528 851 2.77%
Australia/Sydney 33524 35733 2209 6.59%
Australia/Tasmania 59927 41908 -18019 -30.07%
Australia/Victoria 49836 35892 -13944 -27.98%
Australia/West 10721 8527 -2194 -20.46%
Australia/Yancowinna 33618 35776 2158 6.42%
Brazil/Acre 18410 26298 7888 42.85%
Brazil/DeNoronha 24251 34487 10236 42.21%
Brazil/East 58061 39966 -18095 -31.17%
Brazil/West 31396 22438 -8958 -28.53%
CET 53457 42100 -11357 -21.25%
CST6CDT 42964 70528 27564 64.16%
Canada/Atlantic 54416 61068 6652 12.22%
Canada/Central 35207 53101 17894 50.83%
Canada/Eastern 68561 55798 -12763 -18.62%
Canada/Mountain 40768 32340 -8428 -20.67%
Canada/Newfoundland 86446 60162 -26284 -30.41%
Canada/Pacific 30894 31914 1020 3.30%
Canada/Saskatchewan 15180 23478 8298 54.66%
Canada/Yukon 19982 20989 1007 5.04%
Chile/Continental 88407 57597 -30810 -34.85%
Chile/EasterIsland 79607 51069 -28538 -35.85%
Cuba 76383 46201 -30182 -39.51%
EET 27551 27470 -81 -0.29%
EST 899 1654 755 83.98%
EST5EDT 42689 52178 9489 22.23%
Egypt 67219 47429 -19790 -29.44%
Eire 69817 69619 -198 -0.28%
Etc/GMT 1162 1149 -13 -1.12%
Etc/GMT+0 631 791 160 25.36%
Etc/GMT+1 1019 835 -184 -18.06%
Etc/GMT+10 1031 962 -69 -6.69%
Etc/GMT+11 1808 845 -963 -53.26%
Etc/GMT+12 1792 803 -989 -55.19%
Etc/GMT+2 1790 1384 -406 -22.68%
Etc/GMT+3 1101 1305 204 18.53%
Etc/GMT+4 967 841 -126 -13.03%
Etc/GMT+5 1118 787 -331 -29.61%
Etc/GMT+6 1772 830 -942 -53.16%
Etc/GMT+7 1780 751 -1029 -57.81%
Etc/GMT+8 1792 1327 -465 -25.95%
Etc/GMT+9 961 1288 327 34.03%
Etc/GMT-0 785 769 -16 -2.04%
Etc/GMT-1 1015 896 -119 -11.72%
Etc/GMT-10 1801 901 -900 -49.97%
Etc/GMT-11 1752 761 -991 -56.56%
Etc/GMT-12 1845 4307 2462 133.44%
Etc/GMT-13 1028 1260 232 22.57%
Etc/GMT-14 1266 801 -465 -36.73%
Etc/GMT-2 1044 1273 229 21.93%
Etc/GMT-3 1838 817 -1021 -55.55%
Etc/GMT-4 1817 770 -1047 -57.62%
Etc/GMT-5 1797 1306 -491 -27.32%
Etc/GMT-6 1026 1257 231 22.51%
Etc/GMT-7 1032 806 -226 -21.90%
Etc/GMT-8 1194 905 -289 -24.20%
Etc/GMT-9 920 776 -144 -15.65%
Etc/GMT0 1140 642 -498 -43.68%
Etc/Greenwich 1201 1209 8 0.67%
Etc/UCT 668 1118 450 67.37%
Etc/UTC 674 629 -45 -6.68%
Etc/Universal 678 1158 480 70.80%
Etc/Zulu 1155 653 -502 -43.46%
Europe/Amsterdam 54763 38538 -16225 -29.63%
Europe/Andorra 27548 28057 509 1.85%
Europe/Astrakhan 17609 24263 6654 37.79%
Europe/Athe 25283 31266 5983 23.66%
Europe/Belfast 76746 92632 15886 20.70%
Europe/Belgrade 31942 25200 -6742 -21.11%
Europe/Berlin 44747 42331 -2416 -5.40%
Europe/Bratislava 40900 40866 -34 -0.08%
Europe/Brussels 40801 39357 -1444 -3.54%
Europe/Bucharest 26487 31302 4815 18.18%
Europe/Budapest 31018 35507 4489 14.47%
Europe/Busingen 31389 21494 -9895 -31.52%
Europe/Chisinau 46020 45648 -372 -0.81%
Europe/Copenhagen 41203 45390 4187 10.16%
Europe/Dublin 70916 110111 39195 55.27%
Europe/Gibraltar 65480 72474 6994 10.68%
Europe/Guerey 75260 87045 11785 15.66%
Europe/Helsinki 29762 30571 809 2.72%
Europe/Isle_of_Man 131491 132408 917 0.70%
Europe/Istanbul 39048 56044 16996 43.53%
Europe/Jersey 80149 82394 2245 2.80%
Europe/Kaliningrad 21348 23824 2476 11.60%
Europe/Kiev 23530 35547 12017 51.07%
Europe/Kirov 23806 27499 3693 15.51%
Europe/Kyiv 35061 35230 169 0.48%
Europe/Lisbon 93579 97866 4287 4.58%
Europe/Ljubljana 24038 22885 -1153 -4.80%
Europe/London 75229 88115 12886 17.13%
Europe/Luxembourg 36086 40114 4028 11.16%
Europe/Madrid 49772 35227 -14545 -29.22%
Europe/Malta 54583 55181 598 1.10%
Europe/Mariehamn 29888 21797 -8091 -27.07%
Europe/Mik 18530 18585 55 0.30%
Europe/Monaco 37165 40619 3454 9.29%
Europe/Moscow 19650 21535 1885 9.59%
Europe/Nicosia 33819 24879 -8940 -26.43%
Europe/Oslo 41238 41490 252 0.61%
Europe/Paris 57151 56900 -251 -0.44%
Europe/Podgorica 23036 23915 879 3.82%
Europe/Prague 27016 30361 3345 12.38%
Europe/Riga 24294 26604 2310 9.51%
Europe/Rome 55333 42517 -12816 -23.16%
Europe/Samara 25788 26203 415 1.61%
Europe/San_Marino 56980 56532 -448 -0.79%
Europe/Sarajevo 24024 24340 316 1.32%
Europe/Saratov 16820 17450 630 3.75%
Europe/Simferopol 19062 21468 2406 12.62%
Europe/Skopje 30961 22185 -8776 -28.35%
Europe/Sofia 35927 28842 -7085 -19.72%
Europe/Stockholm 61930 30918 -31012 -50.08%
Europe/Tallinn 30075 29543 -532 -1.77%
Europe/Tirane 25078 26307 1229 4.90%
Europe/Tiraspol 30569 46400 15831 51.79%
Europe/Ulyanovsk 24736 19152 -5584 -22.57%
Europe/Uzhgorod 35002 35532 530 1.51%
Europe/Vaduz 59043 23595 -35448 -60.04%
Europe/Vatican 39830 42401 2571 6.45%
Europe/Vienna 27807 29450 1643 5.91%
Europe/Vilnius 24444 26784 2340 9.57%
Europe/Volgograd 23738 18314 -5424 -22.85%
Europe/Warsaw 50443 40915 -9528 -18.89%
Europe/Zagreb 30647 24064 -6583 -21.48%
Europe/Zaporozhye 25175 35929 10754 42.72%
Europe/Zurich 21104 23074 1970 9.33%
Factory 651 1059 408 62.67%
GB 129735 83899 -45836 -35.33%
GB-Eire 131650 133930 2280 1.73%
GMT 1942 766 -1176 -60.56%
GMT+0 731 1109 378 51.71%
GMT-0 637 703 66 10.36%
GMT0 634 712 78 12.30%
Greenwich 1078 1151 73 6.77%
HST 6041 4377 -1664 -27.55%
Hongkong 26345 18067 -8278 -31.42%
Iceland 823 1275 452 54.92%
Indian/Antananarivo 1713 1306 -407 -23.76%
Indian/Chagos 1406 1108 -298 -21.19%
Indian/Christmas 2040 1606 -434 -21.27%
Indian/Cocos 2508 1574 -934 -37.24%
Indian/Comoro 2514 1285 -1229 -48.89%
Indian/Kerguelen 1371 859 -512 -37.35%
Indian/Mahe 1189 869 -320 -26.91%
Indian/Maldives 1259 1042 -217 -17.24%
Indian/Mauritius 5728 5671 -57 -1.00%
Indian/Mayotte 2521 1588 -933 -37.01%
Indian/Reunion 1866 1035 -831 -44.53%
Iran 24736 21404 -3332 -13.47%
Israel 43102 44485 1383 3.21%
Jamaica 8245 8841 596 7.23%
Japan 6302 7016 714 11.33%
Kwajalein 2742 1545 -1197 -43.65%
Libya 16438 12977 -3461 -21.05%
MET 38118 37902 -216 -0.57%
MST 6174 6402 228 3.69%
MST7MDT 31456 33627 2171 6.90%
Mexico/BajaNorte 51752 53226 1474 2.85%
Mexico/BajaSur 20595 15706 -4889 -23.74%
Mexico/General 23776 18425 -5351 -22.51%
NZ 33312 35095 1783 5.35%
NZ-CHAT 27395 27615 220 0.80%
Navajo 30704 36507 5803 18.90%
PRC 12456 13031 575 4.62%
PST8PDT 52784 38118 -14666 -27.78%
Pacific/Apia 12316 12685 369 3.00%
Pacific/Auckland 34055 32540 -1515 -4.45%
Pacific/Bougainville 1766 1984 218 12.34%
Pacific/Chatham 41134 29624 -11510 -27.98%
Pacific/Chuuk 2116 1559 -557 -26.32%
Pacific/Easter 78478 50093 -28385 -36.17%
Pacific/Efate 8631 11830 3199 37.06%
Pacific/Enderbury 1603 1060 -543 -33.87%
Pacific/Fakaofo 1248 1104 -144 -11.54%
Pacific/Fiji 17186 15793 -1393 -8.11%
Pacific/Funafuti 1979 878 -1101 -55.63%
Pacific/Galapagos 5718 4755 -963 -16.84%
Pacific/Gambier 1263 1422 159 12.59%
Pacific/Guadalcanal 1480 988 -492 -33.24%
Pacific/Guam 10692 7365 -3327 -31.12%
Pacific/Honolulu 3751 5939 2188 58.33%
Pacific/Johton 6097 4006 -2091 -34.30%
Pacific/Kanton 2330 1376 -954 -40.94%
Pacific/Kiritimati 1545 1934 389 25.18%
Pacific/Kosrae 2017 1809 -208 -10.31%
Pacific/Kwajalein 2691 1546 -1145 -42.55%
Pacific/Majuro 1135 1458 323 28.46%
Pacific/Marquesas 1970 987 -983 -49.90%
Pacific/Midway 1501 1004 -497 -33.11%
Pacific/Nauru 1672 2095 423 25.30%
Pacific/Niue 1318 1086 -232 -17.60%
Pacific/Norfolk 14907 10636 -4271 -28.65%
Pacific/Noumea 4558 6172 1614 35.41%
Pacific/Pago_Pago 1389 889 -500 -36.00%
Pacific/Palau 1989 1113 -876 -44.04%
Pacific/Pitcairn 1519 1654 135 8.89%
Pacific/Pohnpei 1118 931 -187 -16.73%
Pacific/Ponape 1185 1435 250 21.10%
Pacific/Port_Moresby 1249 1593 344 27.54%
Pacific/Rarotonga 12609 9705 -2904 -23.03%
Pacific/Saipan 10714 8046 -2668 -24.90%
Pacific/Samoa 788 1453 665 84.39%
Pacific/Tahiti 1085 980 -105 -9.68%
Pacific/Tarawa 1935 875 -1060 -54.78%
Pacific/Tongatapu 6198 8052 1854 29.91%
Pacific/Truk 2110 1171 -939 -44.50%
Pacific/Wake 2025 951 -1074 -53.04%
Pacific/Wallis 1264 1380 116 9.18%
Pacific/Yap 1234 1551 317 25.69%
Poland 34892 37456 2564 7.35%
Portugal 59675 61944 2269 3.80%
ROC 14608 11594 -3014 -20.63%
ROK 14612 11683 -2929 -20.05%
Singapore 2076 2518 442 21.29%
Turkey 36420 42660 6240 17.13%
UCT 1161 639 -522 -44.96%
US/Alaska 27014 42130 15116 55.96%
US/Aleutian 42377 32003 -10374 -24.48%
US/Arizona 9537 6959 -2578 -27.03%
US/Central 44928 69945 25017 55.68%
US/East-Indiana 21745 23509 1764 8.11%
US/Eastern 65486 51963 -13523 -20.65%
US/Hawaii 3824 4336 512 13.39%
US/Indiana-Starke 46790 34346 -12444 -26.60%
US/Michigan 41186 31103 -10083 -24.48%
US/Mountain 32479 48325 15846 48.79%
US/Pacific 33663 35691 2028 6.02%
US/Samoa 940 1013 73 7.77%
UTC 614 1158 544 88.60%
Universal 1143 715 -428 -37.45%
W-SU 28983 22915 -6068 -20.94%
WET 61715 98640 36925 59.83%
Zulu 610 696 86 14.10%

Reply via email to