Skip to content

Commit

Permalink
tests: check more timezones
Browse files Browse the repository at this point in the history
  • Loading branch information
henryiii committed Aug 27, 2020
1 parent 4cca280 commit 13d2275
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 15 deletions.
19 changes: 5 additions & 14 deletions include/pybind11/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,30 +150,21 @@ template <typename Duration> class type_caster<std::chrono::time_point<std::chro
// Lazy initialise the PyDateTime import
if (!PyDateTimeAPI) { PyDateTime_IMPORT; }

// Declare these special duration types so the conversions happen with the correct primitive types (int)
using us_t = duration<int, std::micro>;

// 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)
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));
std::time_t tt = system_clock::to_time_t(time_point_cast<system_clock::duration>(src));
// 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,
us.count());
(duration_cast<us_t>(src.time_since_epoch() % seconds(1))).count());
}
PYBIND11_TYPE_CASTER(type, _("datetime.datetime"));
};
Expand Down
9 changes: 8 additions & 1 deletion tests/test_chrono.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,14 @@ def test_chrono_system_clock_roundtrip_date():
datetime.time(5, 59, 59, 0),
datetime.time(5, 59, 59, 1),
])
def test_chrono_system_clock_roundtrip_time(time1):
@pytest.mark.parametrize("tz", [
"/usr/share/zoneinfo/Europe/Brussels",
"/usr/share/zoneinfo/Asia/Pyongyang",
"/usr/share/zoneinfo/America/New_York",
])
def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch):
monkeypatch.setenv("TZ", tz)

# Roundtrip the time
datetime2 = m.test_chrono2(time1)
date2 = datetime2.date()
Expand Down

0 comments on commit 13d2275

Please sign in to comment.