mirror of
https://github.com/pybind/pybind11.git
synced 2026-05-24 14:55:01 +00:00
Fix bug roundtripping datetime.time objects after midnight in eastern hemisphere timezones (#2417) (#2438)
* Fix bug roundtripping datetime.time objects after midnight in eastern hemisphere timezones (#2417) * tests: check more timezones * Fix review remarks: remove useless comment and skip setting TZ environment variable on Windows
This commit is contained in:
@@ -150,21 +150,28 @@ public:
|
||||
// Lazy initialise the PyDateTime import
|
||||
if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
|
||||
|
||||
std::time_t tt = system_clock::to_time_t(time_point_cast<system_clock::duration>(src));
|
||||
// Get out microseconds, and make sure they are positive, to avoid bug in eastern hemisphere time zones
|
||||
// (cfr. https://github.com/pybind/pybind11/issues/2417)
|
||||
using us_t = duration<int, std::micro>;
|
||||
auto us = duration_cast<us_t>(src.time_since_epoch() % seconds(1));
|
||||
if (us.count() < 0)
|
||||
us += seconds(1);
|
||||
|
||||
// Subtract microseconds BEFORE `system_clock::to_time_t`, because:
|
||||
// > If std::time_t has lower precision, it is implementation-defined whether the value is rounded or truncated.
|
||||
// (https://en.cppreference.com/w/cpp/chrono/system_clock/to_time_t)
|
||||
std::time_t tt = system_clock::to_time_t(time_point_cast<system_clock::duration>(src - us));
|
||||
// this function uses static memory so it's best to copy it out asap just in case
|
||||
// otherwise other code that is using localtime may break this (not just python code)
|
||||
std::tm localtime = *std::localtime(&tt);
|
||||
|
||||
// Declare these special duration types so the conversions happen with the correct primitive types (int)
|
||||
using us_t = duration<int, std::micro>;
|
||||
|
||||
return PyDateTime_FromDateAndTime(localtime.tm_year + 1900,
|
||||
localtime.tm_mon + 1,
|
||||
localtime.tm_mday,
|
||||
localtime.tm_hour,
|
||||
localtime.tm_min,
|
||||
localtime.tm_sec,
|
||||
(duration_cast<us_t>(src.time_since_epoch() % seconds(1))).count());
|
||||
us.count());
|
||||
}
|
||||
PYBIND11_TYPE_CASTER(type, _("datetime.datetime"));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user