From a11065b823f14fbc32bb1fc132304e36f486c8b0 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Mon, 15 Mar 2021 17:04:39 -0700 Subject: [PATCH] Fix fencepost error in calculating the week_num for POSIX timezone rules. Fixes CI failure caused by US starting DST in 2021, a year in which March began on a Monday. --- bindings/python/time64.i | 2 ++ libgnucash/engine/gnc-timezone.cpp | 2 +- libgnucash/engine/test/gtest-gnc-datetime.cpp | 35 ++++++++++++++----- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/bindings/python/time64.i b/bindings/python/time64.i index cf3408a98b..09bb4ee415 100644 --- a/bindings/python/time64.i +++ b/bindings/python/time64.i @@ -109,6 +109,8 @@ PyDateTime_IMPORT; struct tm t; gnc_localtime_r(&$1, &t); + printf("\nConverting %d hours and %d minutes in zone %ld %s to python local time\n", + t.tm_hour, t.tm_min, t.tm_gmtoff/3600, t.tm_isdst ? "DST" : "STD"); $result = PyDateTime_FromDateAndTime(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, 0); diff --git a/libgnucash/engine/gnc-timezone.cpp b/libgnucash/engine/gnc-timezone.cpp index 33f0609ec5..dc735a402b 100644 --- a/libgnucash/engine/gnc-timezone.cpp +++ b/libgnucash/engine/gnc-timezone.cpp @@ -500,7 +500,7 @@ namespace DSTRule Transition::Transition(gregorian_date date) : month(date.month()), dow(date.day_of_week()), - week(static_cast((7 + date.day() - date.day_of_week()) / 7)) + week(static_cast((6 + date.day() - date.day_of_week()) / 7)) {} bool diff --git a/libgnucash/engine/test/gtest-gnc-datetime.cpp b/libgnucash/engine/test/gtest-gnc-datetime.cpp index 446f810e89..b713aa2d6d 100644 --- a/libgnucash/engine/test/gtest-gnc-datetime.cpp +++ b/libgnucash/engine/test/gtest-gnc-datetime.cpp @@ -518,15 +518,34 @@ TEST(gnc_datetime_functions, test_date) EXPECT_EQ(ymd.day - (12 + atime.offset() / 3600) / 24, 13); } /* This test works only in the America/LosAngeles time zone and - * there's no way at present to make it more flexible. -TEST(gnc_datetime_functions, test_timezone_offset) + * there's no straightforward wat to make it more flexible. It ensures + * that DST in that timezone transitions correctly for each day of the + * week in which March begines. + + TEST(gnc_datetime_functions, test_timezone_offset) { + struct Timepair + { + time64 before; + time64 after; + }; + std::array years{ + Timepair{1615633140, 1615719540}, //2021, Monday + Timepair{1457780340, 1457866740}, //2016, Tuesday + Timepair{1489229940, 1489316340}, //2017, Wednesday + Timepair{1520679540, 1520765940}, //2018, Thursday + Timepair{1552129140, 1552215540}, //2019, Friday + Timepair{1741431540, 1741517940}, //2025, Saturday + Timepair{1583578740, 1583665140} //2020, Sunday + }; + for (auto year : years) + { + GncDateTime before{year.before}; + GncDateTime after{year.after}; +// std::cerr << before.format_iso8601() << std::endl; + EXPECT_EQ(-28800, before.offset()); + EXPECT_EQ(-25200, after.offset()); + } - GncDateTime gncdt1(1488797940); //6 Mar 2017 - EXPECT_EQ(-28800, gncdt1.offset()); - GncDateTime gncdt2(1489661940); //16 Mar 2017 10:59 Z - EXPECT_EQ(-25200, gncdt2.offset()); - GncDateTime gncdt3(1490525940); //26 Mar 2017 - EXPECT_EQ(-25200, gncdt3.offset()); } */