From 0f0fdfbf5ecfeb88b46e3fa426c121466b140bb5 Mon Sep 17 00:00:00 2001 From: fhgffy <102001626+fhgffy@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:38:26 +0800 Subject: [PATCH] Fix timestamp96 decoding at zero seconds Treat zero seconds as nonnegative when converting the timestamp96 fraction to chrono durations. This keeps truncation consistent with timestamp64 and leaves negative-second handling unchanged. Add an explicit microsecond-resolution regression for both as and convert. --- include/msgpack/v1/adaptor/cpp11/chrono.hpp | 4 ++-- test/msgpack_cpp11.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/msgpack/v1/adaptor/cpp11/chrono.hpp b/include/msgpack/v1/adaptor/cpp11/chrono.hpp index 22c3da2bc..85e5d7b31 100644 --- a/include/msgpack/v1/adaptor/cpp11/chrono.hpp +++ b/include/msgpack/v1/adaptor/cpp11/chrono.hpp @@ -161,7 +161,7 @@ struct as> { int64_t sec; _msgpack_load64(int64_t, o.via.ext.data() + 4, &sec); - if (sec > 0) { + if (sec >= 0) { tp += std::chrono::seconds(sec); tp += std::chrono::duration_cast( std::chrono::nanoseconds(nanosec)); @@ -215,7 +215,7 @@ struct convert> { int64_t sec; _msgpack_load64(int64_t, o.via.ext.data() + 4, &sec); - if (sec > 0) { + if (sec >= 0) { tp += std::chrono::seconds(sec); tp += std::chrono::duration_cast( std::chrono::nanoseconds(nanosec)); diff --git a/test/msgpack_cpp11.cpp b/test/msgpack_cpp11.cpp index 3375a27bf..2a42c9774 100644 --- a/test/msgpack_cpp11.cpp +++ b/test/msgpack_cpp11.cpp @@ -1008,6 +1008,24 @@ BOOST_AUTO_TEST_CASE(system_clock_64_max) BOOST_CHECK(val1 == val3); } +BOOST_AUTO_TEST_CASE(system_clock_96_zero_seconds) +{ + // Timestamp96 can also encode a nonnegative subsecond value. + typedef std::chrono::time_point time_point; + char packed[] = { + static_cast(0xc7u), 12, static_cast(-1), + 0, 0, 1, static_cast(0xf4u), // 500 nanoseconds + 0, 0, 0, 0, 0, 0, 0, 0 // zero seconds + }; + msgpack::object_handle oh = + msgpack::unpack(packed, sizeof(packed)); + BOOST_CHECK_EQUAL(oh.get().as().time_since_epoch().count(), 0); + + time_point converted(std::chrono::microseconds(123)); + oh.get().convert(converted); + BOOST_CHECK_EQUAL(converted.time_since_epoch().count(), 0); +} + BOOST_AUTO_TEST_CASE(system_clock_impl_min) { std::chrono::system_clock::time_point val1(std::chrono::system_clock::time_point::min());