mirror of
https://github.com/fmtlib/fmt.git
synced 2026-11-09 14:50:24 +08:00
Check the truncated count in float to integral duration_cast
This commit is contained in:
parent
7dc456208e
commit
c9b66420b5
@ -524,11 +524,13 @@ auto duration_cast(std::chrono::duration<FromRep, FromPeriod> from) -> To {
|
||||
auto count = detail::duration_cast<
|
||||
std::chrono::duration<FromRep, typename To::period>>(from)
|
||||
.count();
|
||||
// The conversion truncates toward zero so check the truncated value.
|
||||
// max + 1 is a power of 2 so the cast to FromRep is exact even when max
|
||||
// itself is rounded up by the conversion; the comparison is false for NaN.
|
||||
auto upper = static_cast<FromRep>(max_value<to_rep>()) + 1;
|
||||
auto lower = static_cast<FromRep>((std::numeric_limits<to_rep>::min)());
|
||||
if (!(count >= lower && count < upper)) throw_duration_error();
|
||||
auto truncated = std::trunc(count);
|
||||
if (!(truncated >= lower && truncated < upper)) throw_duration_error();
|
||||
return To(static_cast<to_rep>(count));
|
||||
#else
|
||||
return std::chrono::duration_cast<To>(from);
|
||||
|
||||
@ -1006,6 +1006,33 @@ TEST(chrono_test, out_of_range) {
|
||||
EXPECT_THROW((void)fmt::format("{:%F}", flocal), fmt::format_error);
|
||||
}
|
||||
|
||||
TEST(chrono_test, float_to_integral_duration_cast) {
|
||||
using fsec = std::chrono::duration<double>;
|
||||
// Values that truncate toward zero into range are valid.
|
||||
EXPECT_EQ(
|
||||
fmt::detail::duration_cast<std::chrono::duration<unsigned>>(fsec(-0.5))
|
||||
.count(),
|
||||
0u);
|
||||
auto min = (std::numeric_limits<int>::min)();
|
||||
EXPECT_EQ(
|
||||
fmt::detail::duration_cast<std::chrono::duration<int>>(fsec(min - 0.5))
|
||||
.count(),
|
||||
min);
|
||||
auto max = (std::numeric_limits<int>::max)();
|
||||
EXPECT_EQ(
|
||||
fmt::detail::duration_cast<std::chrono::duration<int>>(fsec(max + 0.5))
|
||||
.count(),
|
||||
max);
|
||||
if (FMT_SAFE_DURATION_CAST) {
|
||||
EXPECT_THROW(
|
||||
fmt::detail::duration_cast<std::chrono::duration<unsigned>>(fsec(-1)),
|
||||
fmt::format_error);
|
||||
EXPECT_THROW(
|
||||
fmt::detail::duration_cast<std::chrono::duration<int>>(fsec(min - 1.0)),
|
||||
fmt::format_error);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(chrono_test, calendar_padding) {
|
||||
EXPECT_EQ("05 ", fmt::format("{:5}", fmt::day(5)));
|
||||
EXPECT_EQ(" Jan", fmt::format("{:>5}", fmt::month(1)));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user