From e5456c222624134d2b98759dbd4f4f1d32c45b2a Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Sat, 11 Mar 2017 22:29:25 -0400 Subject: [PATCH] Fix for floating point durations The duration calculation was using %, but that's only supported on duration objects when the arithmetic type supports %, and hence fails for floats. Fixed by subtracting off the calculated values instead. --- include/pybind11/chrono.h | 8 +++++--- tests/test_chrono.cpp | 6 ++++++ tests/test_chrono.py | 6 +++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/pybind11/chrono.h b/include/pybind11/chrono.h index 2b37f56f1..8a41d08b0 100644 --- a/include/pybind11/chrono.h +++ b/include/pybind11/chrono.h @@ -85,9 +85,11 @@ public: using ss_t = duration>; using us_t = duration; - return PyDelta_FromDSU(duration_cast(d).count(), - duration_cast(d % days(1)).count(), - duration_cast(d % seconds(1)).count()); + auto dd = duration_cast(d); + auto subd = d - dd; + auto ss = duration_cast(subd); + auto us = duration_cast(subd - ss); + return PyDelta_FromDSU(dd.count(), ss.count(), us.count()); } PYBIND11_TYPE_CASTER(type, _("datetime.timedelta")); diff --git a/tests/test_chrono.cpp b/tests/test_chrono.cpp index b86f57adf..fcc1b6185 100644 --- a/tests/test_chrono.cpp +++ b/tests/test_chrono.cpp @@ -48,6 +48,11 @@ std::chrono::microseconds test_chrono7(std::chrono::microseconds t) { return t; } +// Float durations (issue #719) +std::chrono::duration test_chrono_float_diff(std::chrono::duration a, std::chrono::duration b) { + return a - b; +} + test_initializer chrono([] (py::module &m) { m.def("test_chrono1", &test_chrono1); m.def("test_chrono2", &test_chrono2); @@ -56,4 +61,5 @@ test_initializer chrono([] (py::module &m) { m.def("test_chrono5", &test_chrono5); m.def("test_chrono6", &test_chrono6); m.def("test_chrono7", &test_chrono7); + m.def("test_chrono_float_diff", &test_chrono_float_diff); }); diff --git a/tests/test_chrono.py b/tests/test_chrono.py index 94ca55c76..55094edbf 100644 --- a/tests/test_chrono.py +++ b/tests/test_chrono.py @@ -104,7 +104,7 @@ def test_chrono_steady_clock_roundtrip(): def test_floating_point_duration(): - from pybind11_tests import test_chrono7 + from pybind11_tests import test_chrono7, test_chrono_float_diff import datetime # Test using 35.525123 seconds as an example floating point number in seconds @@ -114,3 +114,7 @@ def test_floating_point_duration(): assert time.seconds == 35 assert 525122 <= time.microseconds <= 525123 + + diff = test_chrono_float_diff(43.789012, 1.123456) + assert diff.seconds == 42 + assert 665556 <= diff.microseconds <= 665557