@@ -183,8 +183,12 @@ BOOST_AUTO_TEST_CASE(FormatDateTime) {
183
183
//
184
184
// These are expected to result in an error due to the intermediate struct tm not being able to represent these
185
185
// timestamps, so localtime_r() returns EOVERFLOW which makes the implementation throw an exception.
186
- BOOST_CHECK_THROW (Utility::FormatDateTime (" %Y" , std::nextafter (time_t_limit::min (), 0 )), posix_error);
187
- BOOST_CHECK_THROW (Utility::FormatDateTime (" %Y" , std::nextafter (time_t_limit::max (), 0 )), posix_error);
186
+ if constexpr (sizeof (time_t ) > sizeof (int32_t )) {
187
+ BOOST_CHECK_THROW (Utility::FormatDateTime (" %Y" , std::nextafter (time_t_limit::min (), 0 )), posix_error);
188
+ BOOST_CHECK_THROW (Utility::FormatDateTime (" %Y" , std::nextafter (time_t_limit::max (), 0 )), posix_error);
189
+ } else {
190
+ BOOST_WARN_MESSAGE (false , " skipping test for struct tm overflow due to 32 bit time_t" );
191
+ }
188
192
189
193
// Excessive format strings can result in something too large for the buffer, errors out to the empty string.
190
194
// Note: both returning the proper result or throwing an exception would be fine too, unfortunately, that's
@@ -205,8 +209,16 @@ BOOST_AUTO_TEST_CASE(FormatDateTime) {
205
209
}
206
210
207
211
// Out of range timestamps.
208
- BOOST_CHECK_THROW (Utility::FormatDateTime (" %Y" , std::nextafter (time_t_limit::min (), -double_limit::infinity ())), negative_overflow);
209
- BOOST_CHECK_THROW (Utility::FormatDateTime (" %Y" , std::nextafter (time_t_limit::max (), +double_limit::infinity ())), positive_overflow);
212
+ //
213
+ // At the limits of a 64 bit time_t, doubles can no longer represent each integer value, so a simple x+1 or x-1 can
214
+ // have x as the result, hence std::nextafter() is used to get the next representable value. However, around the
215
+ // limits of a 32 bit time_t, doubles still can represent decimal places and less than 1 is added or subtracted by
216
+ // std::nextafter() and casting back to time_t simply results in the limit again, so std::ceil()/std::floor() is
217
+ // used to round it to the next integer value that is actually out of range.
218
+ double negative_out_of_range = std::floor (std::nextafter (time_t_limit::min (), -double_limit::infinity ()));
219
+ double positive_out_of_range = std::ceil (std::nextafter (time_t_limit::max (), +double_limit::infinity ()));
220
+ BOOST_CHECK_THROW (Utility::FormatDateTime (" %Y" , negative_out_of_range), negative_overflow);
221
+ BOOST_CHECK_THROW (Utility::FormatDateTime (" %Y" , positive_out_of_range), positive_overflow);
210
222
}
211
223
212
224
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments