# # # patch "dates.cc" # from [9bcad49bcaea432aa27a368de34027c582c0c960] # to [03361eb8785e764d5f5c18c258bc46fe539062d8] # # patch "dates.hh" # from [bea2c2fefa4a7464ec575bdcc2ae8f4ad40961b8] # to [466009e8661de2563c003594a3d6e53d63a45d01] # ============================================================ --- dates.cc 9bcad49bcaea432aa27a368de34027c582c0c960 +++ dates.cc 03361eb8785e764d5f5c18c258bc46fe539062d8 @@ -39,8 +39,10 @@ date_t::date_t(u64 d) date_t::date_t(u64 d) : d(d) { - // year 10000 limit - I(d < u64_C(253402300800000)); + // When initialized from a millisecods since Unix epoch value, we require + // that to be in a valid range. Use the constructor without any argument + // to generate an invalid date. + I(valid()); } date_t::date_t(int sec, int min, int hour, int day, int month, int year) @@ -62,8 +64,17 @@ date_t::date_t(int sec, int min, int hou t.tm_year = year - 1900; mktime(t); + + I(valid()); } +bool +date_t::valid() const +{ + // year 10000 limit + return d < u64_C(253402300800000); +} + std::ostream & operator<< (std::ostream & o, date_t const & d) { @@ -290,6 +301,8 @@ date_t::mktime(struct tm const & tm) // add leap days for every 400th year (since 2000), subtracting one again d += DAY * (((tm.tm_year + 300 - 1) / 400) - 1); + + I(valid()); } // We might want to consider teaching this routine more time formats. @@ -439,15 +452,13 @@ date_t::operator +=(s64 const other) date_t & date_t::operator +=(s64 const other) { - // only operate on vaild dates (i..e. d != 0) + // only operate on vaild dates, prevent turning an invalid + // date into a valid one. I(valid()); d += other; // make sure we are still before year 10'000 - I(d < u64_C(253402300800000)); - - // make sure the date is still valid I(valid()); return *this; @@ -757,10 +768,10 @@ UNIT_TEST(date, comparisons) UNIT_TEST_CHECK(v == jun); // check limits for subtractions - v = date_t(12345000 + 1000); + v = date_t(12345000); v -= 12345000; - UNIT_TEST_CHECK(v == date_t::from_string("1970-01-01T00:00:01")); - UNIT_TEST_CHECK_THROW(v -= 1000, std::logic_error); + UNIT_TEST_CHECK(v == date_t::from_string("1970-01-01T00:00:00")); + UNIT_TEST_CHECK_THROW(v -= 1, std::logic_error); // check limits for additions v = date_t::from_string("9999-12-31T23:59:00"); ============================================================ --- dates.hh bea2c2fefa4a7464ec575bdcc2ae8f4ad40961b8 +++ dates.hh 466009e8661de2563c003594a3d6e53d63a45d01 @@ -19,7 +19,8 @@ struct date_t struct date_t { - date_t() : d(0) {} + // initialize to an invalid date + date_t() : d(-1) {} // initialize from a unix timestamp date_t(u64 d); @@ -27,7 +28,7 @@ struct date_t // initialize from multiple values date_t(int sec, int min, int hour, int day, int month, int year); - bool valid() const { return d != 0; } + bool valid() const; // Return the local system's idea of the current date. static date_t now();