diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 6ff84ae65..6f272178a 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1052,7 +1053,8 @@ String Utility::FormatDuration(double duration) String Utility::FormatDateTime(const char *format, double ts) { char timestamp[128]; - auto tempts = (time_t)ts; /* We don't handle sub-second timestamps here just yet. */ + // Sub-second precision is removed, strftime() has no format specifiers for that anyway. + auto tempts = boost::numeric_cast(ts); tm tmthen; #ifdef _MSC_VER diff --git a/test/base-utility.cpp b/test/base-utility.cpp index 77d91f47a..ced81ae4a 100644 --- a/test/base-utility.cpp +++ b/test/base-utility.cpp @@ -137,6 +137,9 @@ BOOST_AUTO_TEST_CASE(TruncateUsingHash) BOOST_AUTO_TEST_CASE(FormatDateTime) { using time_t_limit = std::numeric_limits; + using double_limit = std::numeric_limits; + using boost::numeric::negative_overflow; + using boost::numeric::positive_overflow; // Helper to repeat a given string a number of times. auto repeat = [](const std::string& s, size_t n) { @@ -182,6 +185,10 @@ BOOST_AUTO_TEST_CASE(FormatDateTime) { // timestamps, so localtime_r() returns EOVERFLOW which makes the implementation throw an exception. BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::min(), 0)), posix_error); BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::max(), 0)), posix_error); + + // Out of range timestamps. + BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::min(), -double_limit::infinity())), negative_overflow); + BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::max(), +double_limit::infinity())), positive_overflow); } BOOST_AUTO_TEST_SUITE_END()