changed localtime to gmtime to fix daylight savings issues

This commit is contained in:
James Unicomb 2022-03-16 12:13:02 +11:00
parent f8a532a7de
commit d8a5a5d5c2
2 changed files with 23 additions and 13 deletions

View File

@ -99,7 +99,7 @@ public:
PYBIND11_TYPE_CASTER(type, const_name("datetime.timedelta")); PYBIND11_TYPE_CASTER(type, const_name("datetime.timedelta"));
}; };
inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) { inline std::tm *gmtime_thread_safe(const std::time_t *time, std::tm *buf) {
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || defined(_MSC_VER) #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || defined(_MSC_VER)
if (localtime_s(buf, time)) if (localtime_s(buf, time))
return nullptr; return nullptr;
@ -107,7 +107,7 @@ inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) {
#else #else
static std::mutex mtx; static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx); std::lock_guard<std::mutex> lock(mtx);
std::tm *tm_ptr = std::localtime(time); std::tm *tm_ptr = std::gmtime(time);
if (tm_ptr != nullptr) { if (tm_ptr != nullptr) {
*buf = *tm_ptr; *buf = *tm_ptr;
} }
@ -166,7 +166,7 @@ public:
return false; return false;
} }
value = time_point_cast<Duration>(system_clock::from_time_t(std::mktime(&cal)) + msecs); value = time_point_cast<Duration>(system_clock::from_time_t(timegm(&cal)) + msecs);
return true; return true;
} }
@ -194,17 +194,17 @@ public:
std::time_t tt std::time_t tt
= system_clock::to_time_t(time_point_cast<system_clock::duration>(src - us)); = system_clock::to_time_t(time_point_cast<system_clock::duration>(src - us));
std::tm localtime; std::tm gmtime;
std::tm *localtime_ptr = localtime_thread_safe(&tt, &localtime); std::tm *gmtime_ptr = gmtime_thread_safe(&tt, &gmtime);
if (!localtime_ptr) { if (!gmtime_ptr) {
throw cast_error("Unable to represent system_clock in local time"); throw cast_error("Unable to represent system_clock in GMT time");
} }
return PyDateTime_FromDateAndTime(localtime.tm_year + 1900, return PyDateTime_FromDateAndTime(gmtime.tm_year + 1900,
localtime.tm_mon + 1, gmtime.tm_mon + 1,
localtime.tm_mday, gmtime.tm_mday,
localtime.tm_hour, gmtime.tm_hour,
localtime.tm_min, gmtime.tm_min,
localtime.tm_sec, gmtime.tm_sec,
us.count()); us.count());
} }
PYBIND11_TYPE_CASTER(type, const_name("datetime.datetime")); PYBIND11_TYPE_CASTER(type, const_name("datetime.datetime"));

View File

@ -71,6 +71,16 @@ def test_chrono_system_clock_roundtrip_date():
assert time2.microsecond == 0 assert time2.microsecond == 0
def test_chrono_system_clock_roundtrip_daylight_savings():
# naive datetime - AEDST clock will change
datetime1 = datetime.datetime(2021, 10, 3, 2, 18, 46, 677734)
# Roundtrip the time
datetime2 = m.test_chrono2(datetime1)
assert datetime2.hour == datetime1.hour
SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif( SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif(
"env.WIN", reason="TZ environment variable only supported on POSIX" "env.WIN", reason="TZ environment variable only supported on POSIX"
) )