Skip to content

Commit 90579c6

Browse files
fix time utils overflow in windows
Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com>
1 parent 328d165 commit 90579c6

3 files changed

Lines changed: 73 additions & 11 deletions

File tree

cpp_utils/include/cpp_utils/time/time_utils.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ using Duration_ms = uint32_t;
3232
/**
3333
* Type used to represent time points
3434
*/
35-
using Timestamp = std::chrono::time_point<std::chrono::system_clock>;
35+
using Timeclock = std::chrono::system_clock;
36+
using Timestamp = std::chrono::time_point<Timeclock>;
3637

3738
/**
3839
* @brief Now time

cpp_utils/src/cpp/time/time_utils.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,25 @@ namespace utils {
3636

3737
Timestamp now() noexcept
3838
{
39-
return std::chrono::system_clock::now();
39+
return Timeclock::now();
4040
}
4141

4242
Timestamp the_end_of_time() noexcept
4343
{
44-
return std::chrono::time_point<std::chrono::system_clock>::max();
44+
#if defined(_WIN32) // In Windows std::gmtime does not support negative values nor values greater than 2^32
45+
return Timeclock::from_time_t(std::numeric_limits<long>::max());
46+
#else
47+
return Timestamp::max();
48+
#endif // if defined(_WIN32)
4549
}
4650

4751
Timestamp the_beginning_of_time() noexcept
4852
{
49-
return std::chrono::time_point<std::chrono::system_clock>::min();
53+
#if defined(_WIN32) // In Windows std::gmtime does not support negative values nor values greater than 2^32
54+
return Timeclock::from_time_t(0);
55+
#else
56+
return Timestamp::min();
57+
#endif // if defined(_WIN32)
5058
}
5159

5260
Timestamp date_to_timestamp(
@@ -66,7 +74,7 @@ Timestamp date_to_timestamp(
6674
tm.tm_mon = static_cast<int>(month) - 1;
6775
tm.tm_year = static_cast<int>(year) - 1900;
6876

69-
return std::chrono::system_clock::from_time_t(timegm(&tm));
77+
return Timeclock::from_time_t(timegm(&tm));
7078
}
7179

7280
Timestamp time_to_timestamp(
@@ -86,7 +94,7 @@ Timestamp time_to_timestamp(
8694
tm.tm_min = static_cast<int>(minute);
8795
tm.tm_hour = static_cast<int>(hour);
8896

89-
return std::chrono::system_clock::from_time_t(timegm(&tm));
97+
return Timeclock::from_time_t(timegm(&tm));
9098
}
9199

92100
std::string timestamp_to_string(
@@ -95,8 +103,12 @@ std::string timestamp_to_string(
95103
bool local_time /* = false */)
96104
{
97105
std::ostringstream ss;
98-
const std::chrono::high_resolution_clock::time_point::duration duration = timestamp.time_since_epoch();
99-
const time_t duration_seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
106+
time_t duration_seconds = std::chrono::duration_cast<std::chrono::seconds>(timestamp.time_since_epoch()).count();
107+
108+
#if defined(_WIN32) // In Windows std::gmtime does not support negative values nor values greater than 2^32
109+
time_t max_value = std::numeric_limits<long>::max();
110+
duration_seconds = std::max((time_t) 0, std::min(max_value, duration_seconds));
111+
#endif // if defined(_WIN32)
100112

101113
std::tm* tm = nullptr;
102114
if (local_time)
@@ -153,7 +165,7 @@ Timestamp string_to_timestamp(
153165
{
154166
utc_time = timegm(&tm);
155167
}
156-
return std::chrono::system_clock::from_time_t(utc_time);
168+
return Timeclock::from_time_t(utc_time);
157169
}
158170

159171
std::chrono::milliseconds duration_to_ms(

cpp_utils/test/unittest/time/time_utils_test.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ using namespace eprosima::utils;
3131
* - now
3232
* - now with alternative format
3333
* - old time
34+
* - the beginning of time
3435
* - future time
36+
* - the end of time
3537
* - some time today
38+
* - wrong date and time
3639
*/
3740
TEST(time_utils_test, timestamp_to_string_to_timestamp)
3841
{
@@ -112,14 +115,37 @@ TEST(time_utils_test, timestamp_to_string_to_timestamp)
112115
ASSERT_EQ(timestamp_to_string(old_time_from_str), expected_string_os.str());
113116
}
114117

118+
// the begininng of time
119+
{
120+
Timestamp beginning_time = the_beginning_of_time();
121+
std::string beginning_time_str = timestamp_to_string(beginning_time);
122+
123+
std::ostringstream expected_string_os;
124+
expected_string_os
125+
<< 1970
126+
<< "-" << "01"
127+
<< "-" << "01"
128+
<< "_" << "00"
129+
<< "-" << "00"
130+
<< "-" << "00";
131+
132+
// Test timestamp_to_string
133+
ASSERT_EQ(beginning_time_str, expected_string_os.str());
134+
135+
// Test string_to_timestamp
136+
Timestamp beginning_time_from_str = string_to_timestamp(beginning_time_str);
137+
// NOTE: cannot directly compare timestamps because some precision is lost during ts->str conversion
138+
ASSERT_EQ(timestamp_to_string(beginning_time_from_str), expected_string_os.str());
139+
}
140+
115141
// future time
116142
{
117-
Timestamp future_time = date_to_timestamp(2233u, 5u, 22u);
143+
Timestamp future_time = date_to_timestamp(2033u, 5u, 22u);
118144
std::string future_time_str = timestamp_to_string(future_time);
119145

120146
std::ostringstream expected_string_os;
121147
expected_string_os
122-
<< 2233
148+
<< 2033
123149
<< "-" << "05"
124150
<< "-" << 22
125151
<< "_" << "00"
@@ -135,6 +161,29 @@ TEST(time_utils_test, timestamp_to_string_to_timestamp)
135161
ASSERT_EQ(timestamp_to_string(future_time_from_str), expected_string_os.str());
136162
}
137163

164+
// the end of time
165+
{
166+
Timestamp end_time = the_end_of_time();
167+
std::string end_time_str = timestamp_to_string(end_time);
168+
169+
std::ostringstream expected_string_os;
170+
expected_string_os
171+
<< 2038
172+
<< "-" << "01"
173+
<< "-" << 19
174+
<< "_" << "03"
175+
<< "-" << "14"
176+
<< "-" << "07";
177+
178+
// Test timestamp_to_string
179+
ASSERT_EQ(end_time_str, expected_string_os.str());
180+
181+
// Test string_to_timestamp
182+
Timestamp end_time_from_str = string_to_timestamp(end_time_str);
183+
// NOTE: cannot directly compare timestamps because some precision is lost during ts->str conversion
184+
ASSERT_EQ(timestamp_to_string(end_time_from_str), expected_string_os.str());
185+
}
186+
138187
// some time today
139188
{
140189
Timestamp some_time_today = time_to_timestamp(13u, 13u, 13u);

0 commit comments

Comments
 (0)