Repository navigation
changed localtime to gmtime to fix daylight savings issues #3805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,15 +99,15 @@ class duration_caster { | |
| 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 (localtime_s(buf, time)) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function needs to be swapped out too to stop the tests from failing |
||
| return nullptr; | ||
| return buf; | ||
| #else | ||
| static std::mutex 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) { | ||
| *buf = *tm_ptr; | ||
| } | ||
|
|
@@ -166,7 +166,7 @@ class type_caster<std::chrono::time_point<std::chrono::system_clock, Duration>> | |
| 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); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
#if defined(_MSC_VER)
time_t tt = _mkgmtime(&cal);
#else
time_t tt = timegm(&cal);
#endif
value = time_point_cast<Duration>(system_clock::from_time_t(tt) + msecs);
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As @Skylion007 pointed out before, we don't have to go to UTC to solve the roundtrip problem: #3805 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. with that solution would C++ system_clock is Unix Time (so UTC modulo leap seconds and such), so the time zone conversions are a little surprising.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe python datetime objects should be in local time in both? I am not sure we are actually attaching the time zone to the Python objects (we should but it doesn't seem straight forward using the raw C - API). If it's too tricky, we might want to call the Python datetime function directly if we need to. |
||
| return true; | ||
| } | ||
|
|
||
|
|
@@ -194,17 +194,17 @@ class type_caster<std::chrono::time_point<std::chrono::system_clock, Duration>> | |
| std::time_t tt | ||
| = system_clock::to_time_t(time_point_cast<system_clock::duration>(src - us)); | ||
|
|
||
| std::tm localtime; | ||
| std::tm *localtime_ptr = localtime_thread_safe(&tt, &localtime); | ||
| if (!localtime_ptr) { | ||
| throw cast_error("Unable to represent system_clock in local time"); | ||
| std::tm gmtime; | ||
| std::tm *gmtime_ptr = gmtime_thread_safe(&tt, &gmtime); | ||
| if (!gmtime_ptr) { | ||
| throw cast_error("Unable to represent system_clock in GMT time"); | ||
| } | ||
| return PyDateTime_FromDateAndTime(localtime.tm_year + 1900, | ||
| localtime.tm_mon + 1, | ||
| localtime.tm_mday, | ||
| localtime.tm_hour, | ||
| localtime.tm_min, | ||
| localtime.tm_sec, | ||
| return PyDateTime_FromDateAndTime(gmtime.tm_year + 1900, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this change the behavior? Same question from a different angle: as-is this PR fixes the roundtrip issue, i.e. fixes an internal consistency issue, but is it still externally inconsistent? Do we have to tell I just looked a bit, seeing this warning 3 times under https://docs.python.org/3/library/datetime.html:
How can handle this correctly from the C API?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @JamesUnicomb I am not sure about the UTC issue, but the datetime roundtrip issue can be easily resolved. We just need to use |
||
| gmtime.tm_mon + 1, | ||
| gmtime.tm_mday, | ||
| gmtime.tm_hour, | ||
| gmtime.tm_min, | ||
| gmtime.tm_sec, | ||
| us.count()); | ||
| } | ||
| PYBIND11_TYPE_CASTER(type, const_name("datetime.datetime")); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the Windows tests are failing. Do you already have a plan for that? Could we simply remove the
#ifand use the same code, withmutex, everywhere?