1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
6#include <userver/proto-structs/exceptions.hpp>
7#include <userver/proto-structs/time_of_day.hpp>
8#include <userver/utils/impl/internal_tag.hpp>
10using namespace std::literals::chrono_literals;
12USERVER_NAMESPACE_BEGIN
14namespace proto_structs::tests {
16TEST(TimeOfDayTest, IsValid) {
17 using OverflowingDuration = std::chrono::duration<std::chrono::seconds::rep, std::chrono::hours::period>;
18 constexpr auto kMaxInt = std::numeric_limits<std::int32_t>::max();
19 constexpr auto kMinInt = std::numeric_limits<std::int32_t>::min();
21 EXPECT_FALSE(TimeOfDay::IsValid(-1h, 0min, 0s, 0ns));
22 EXPECT_FALSE(TimeOfDay::IsValid(25h, 0min, 0s, 0ns));
23 EXPECT_FALSE(TimeOfDay::IsValid(24h, 0min, 0s, 1ns));
24 EXPECT_FALSE(TimeOfDay::IsValid(10h, -1min, 0s, 0ns));
25 EXPECT_FALSE(TimeOfDay::IsValid(10h, 100min, 0s, 0ns));
26 EXPECT_FALSE(TimeOfDay::IsValid(10h, 30min, -1s, 0ns));
27 EXPECT_FALSE(TimeOfDay::IsValid(10h, 30min, 100s, 0ns));
28 EXPECT_FALSE(TimeOfDay::IsValid(10h, 30min, 45s, -1ns));
29 EXPECT_FALSE(TimeOfDay::IsValid(10h, 30min, 45s, std::chrono::duration<int64_t, std::pico>{-1}));
30 EXPECT_FALSE(TimeOfDay::IsValid(10h, 30min, 45s, std::chrono::duration<int64_t, std::pico>{1'000'000'000'000LL}));
32 EXPECT_THROW([[maybe_unused]]
auto val = TimeOfDay(-1h, 0min, 0s, 0ns), ValueError);
33 EXPECT_THROW([[maybe_unused]]
auto val = TimeOfDay(std::chrono::hh_mm_ss{25h + 30min + 123ns}), ValueError);
35 [[maybe_unused]]
auto val = TimeOfDay(std::chrono::hh_mm_ss<std::chrono::minutes>{24h + 1min}), ValueError
38 [[maybe_unused]]
auto val = TimeOfDay(std::chrono::duration_cast<std::chrono::milliseconds>(48h)), ValueError
40 EXPECT_THROW([[maybe_unused]]
auto val = TimeOfDay(OverflowingDuration::max()), ValueError);
42 [[maybe_unused]]
auto val = TimeOfDay(
utils::impl::InternalTag{}, kMaxInt, kMaxInt, kMaxInt, kMaxInt),
46 [[maybe_unused]]
auto val = TimeOfDay(
utils::impl::InternalTag{}, kMinInt, kMinInt, kMinInt, kMinInt),
50 []() { [[maybe_unused]] TimeOfDay t(25h, 30min, 0s, 123ns); },
51 ::testing::ThrowsMessage<ValueError>(::testing::HasSubstr(
"25:30:0.123ns"))
54 []() { [[maybe_unused]] TimeOfDay t(std::chrono::duration<int64_t, std::pico>{-1}); },
55 ::testing::ThrowsMessage<ValueError>(::testing::HasSubstr(
"negative"))
58 EXPECT_TRUE(TimeOfDay::IsValid(0h, 0min, 0s, 0ns));
59 EXPECT_TRUE(TimeOfDay::IsValid(23h, 59min, 59s, 999'999'999ns));
60 EXPECT_TRUE(TimeOfDay::IsValid(23h, 59min, 60s, 999'999'999ns));
61 EXPECT_TRUE(TimeOfDay::IsValid(23h, 59min, 59s, std::chrono::duration<int64_t, std::pico>{999'999'999'999LL}));
62 EXPECT_TRUE(TimeOfDay::IsValid(23h, 59min, 60s, std::chrono::duration<int64_t, std::pico>{999'999'999'999LL}));
63 EXPECT_TRUE(TimeOfDay::IsValid(24h, 0min, 0s, 0ns));
66TEST(TimeOfDayTest, Conversions) {
69 EXPECT_EQ(t.Hours(), 0h);
70 EXPECT_EQ(t.Minutes(), 0min);
71 EXPECT_EQ(t.Seconds(), 0s);
72 EXPECT_EQ(t.Nanos(), 0ns);
74 t = TimeOfDay{12h, 30min, 45s, 123'456'789ns};
76 EXPECT_EQ(t.Hours(), 12h);
77 EXPECT_EQ(t.Minutes(), 30min);
78 EXPECT_EQ(t.Seconds(), 45s);
79 EXPECT_EQ(t.Nanos(), 123'456'789ns);
80 EXPECT_EQ(t.ToChronoDuration(), 12h + 30min + 45s + 123'456'789ns);
81 EXPECT_EQ(t.ToChronoDuration<std::chrono::microseconds>(), 12h + 30min + 45s + 123'456us);
82 EXPECT_EQ(
static_cast<std::chrono::milliseconds>(t), 12h + 30min + 45s + 123ms);
83 EXPECT_EQ(t.ToChronoTimeOfDay().hours(), 12h);
84 EXPECT_EQ(t.ToChronoTimeOfDay().minutes(), 30min);
85 EXPECT_EQ(t.ToChronoTimeOfDay().seconds(), 45s);
86 EXPECT_EQ(t.ToChronoTimeOfDay().subseconds(), 123'456'789ns);
87 EXPECT_EQ(t.ToChronoTimeOfDay<std::chrono::milliseconds>().hours(), 12h);
88 EXPECT_EQ(t.ToChronoTimeOfDay<std::chrono::milliseconds>().minutes(), 30min);
89 EXPECT_EQ(t.ToChronoTimeOfDay<std::chrono::milliseconds>().seconds(), 45s);
90 EXPECT_EQ(t.ToChronoTimeOfDay<std::chrono::milliseconds>().subseconds(), 123ms);
91 EXPECT_EQ(
static_cast<std::chrono::hh_mm_ss<std::chrono::microseconds>>(t).hours(), 12h);
92 EXPECT_EQ(
static_cast<std::chrono::hh_mm_ss<std::chrono::microseconds>>(t).minutes(), 30min);
93 EXPECT_EQ(
static_cast<std::chrono::hh_mm_ss<std::chrono::microseconds>>(t).seconds(), 45s);
94 EXPECT_EQ(
static_cast<std::chrono::hh_mm_ss<std::chrono::microseconds>>(t).subseconds(), 123'456us);
95 EXPECT_EQ(t.ToUserverDuration().Seconds().count(), (12 * 60 * 60) + (30 * 60) + 45);
96 EXPECT_EQ(t.ToUserverDuration().Nanos(), 123'456'789ns);
97 EXPECT_EQ(
static_cast<Duration>(t).Seconds().count(), (12 * 60 * 60) + (30 * 60) + 45);
98 EXPECT_EQ(
static_cast<Duration>(t).Nanos(), 123'456'789ns);
99 EXPECT_EQ(t.ToUserverTimeOfDay().Hours(), 12h);
100 EXPECT_EQ(t.ToUserverTimeOfDay().Minutes(), 30min);
101 EXPECT_EQ(t.ToUserverTimeOfDay().Seconds(), 45s);
102 EXPECT_EQ(t.ToUserverTimeOfDay().Subseconds(), 123'456'789ns);
103 EXPECT_EQ(t.ToUserverTimeOfDay<std::chrono::milliseconds>().Hours(), 12h);
104 EXPECT_EQ(t.ToUserverTimeOfDay<std::chrono::milliseconds>().Minutes(), 30min);
105 EXPECT_EQ(t.ToUserverTimeOfDay<std::chrono::milliseconds>().Seconds(), 45s);
106 EXPECT_EQ(t.ToUserverTimeOfDay<std::chrono::milliseconds>().Subseconds(), 123ms);
107 EXPECT_EQ(
static_cast<utils::datetime::TimeOfDay<std::chrono::microseconds>>(t).Hours(), 12h);
108 EXPECT_EQ(
static_cast<utils::datetime::TimeOfDay<std::chrono::microseconds>>(t).Minutes(), 30min);
109 EXPECT_EQ(
static_cast<utils::datetime::TimeOfDay<std::chrono::microseconds>>(t).Seconds(), 45s);
110 EXPECT_EQ(
static_cast<utils::datetime::TimeOfDay<std::chrono::microseconds>>(t).Subseconds(), 123'456us);
112 t = std::chrono::hh_mm_ss{1h + 15min + 10s + 999ms};
114 EXPECT_EQ(t.Hours(), 1h);
115 EXPECT_EQ(t.Minutes(), 15min);
116 EXPECT_EQ(t.Seconds(), 10s);
117 EXPECT_EQ(t.Nanos(), 999'000'000ns);
119 t = utils::datetime::TimeOfDay<std::chrono::microseconds>{10h + 11min + 12s + 123456789ns};
121 EXPECT_EQ(t.Hours(), 10h);
122 EXPECT_EQ(t.Minutes(), 11min);
123 EXPECT_EQ(t.Seconds(), 12s);
124 EXPECT_EQ(t.Nanos(), 123'456'000ns);
126 t = TimeOfDay{1h + 2min + 3s};
128 EXPECT_EQ(t.Hours(), 1h);
129 EXPECT_EQ(t.Minutes(), 2min);
130 EXPECT_EQ(t.Seconds(), 3s);
131 EXPECT_EQ(t.Nanos(), 0ns);
134 std::chrono::time_point_cast<std::chrono::system_clock::duration>(std::chrono::sys_days{2025y / 6 / 3});
135 point += 22h + 0min + 13s + 555ms;
136 t = TimeOfDay{point};
138 EXPECT_EQ(t.Hours(), 22h);
139 EXPECT_EQ(t.Minutes(), 0min);
140 EXPECT_EQ(t.Seconds(), 13s);
141 EXPECT_EQ(t.Nanos(), 555'000'000ns);
143 t = TimeOfDay{0h, 0min, 60s, 0ns};
145 EXPECT_EQ(t.Seconds(), 60s);
146 EXPECT_EQ(t.ToChronoTimeOfDay().minutes(), 1min);
147 EXPECT_EQ(t.ToChronoTimeOfDay().seconds(), 0s);
149 t = TimeOfDay{24h, 0min, 0s, 0ns};
151 EXPECT_EQ(t.Hours(), 24h);
152 EXPECT_EQ(t.ToUserverTimeOfDay().Hours(), 0h);
153 EXPECT_EQ(t.ToUserverTimeOfDay().Minutes(), 0min);
154 EXPECT_EQ(t.ToUserverTimeOfDay().Seconds(), 0s);
155 EXPECT_EQ(t.ToUserverTimeOfDay().Subseconds(), 0ns);
157 t = TimeOfDay{utils::impl::InternalTag{}, 12, 59, 59, 123'456};
159 EXPECT_EQ(t.Hours(), 12h);
160 EXPECT_EQ(t.Minutes(), 59min);
161 EXPECT_EQ(t.Seconds(), 59s);
162 EXPECT_EQ(t.Nanos(), 123'456ns);