8 #include "xclox/date.hpp"
10 using namespace xclox;
11 using namespace std::chrono;
15 constexpr seconds NtpDeltaSeconds { 2208988800 };
16 constexpr seconds UnixRolloverSeconds { 2147483647 };
18 TEST_CASE(
"constructible")
25 CHECK(d.
month() == 0);
28 SUBCASE(
"year, month, day")
31 CHECK(d1.year() == 2012);
32 CHECK(d1.month() == 3);
33 CHECK(d1.day() == 27);
35 Date d2(-4714, 11, 24);
36 CHECK(d2.year() == -4714);
37 CHECK(d2.month() == 11);
38 CHECK(d2.day() == 24);
40 SUBCASE(
"number of days since epoch")
42 Date d1(-duration_cast<Date::Days>(NtpDeltaSeconds));
43 CHECK(d1.year() == 1900);
44 CHECK(d1.month() == 1);
48 CHECK(d2.year() == 1970);
49 CHECK(d2.month() == 1);
52 Date d3(duration_cast<Date::Days>(UnixRolloverSeconds));
53 CHECK(d3.year() == 2038);
54 CHECK(d3.month() == 1);
55 CHECK(d3.day() == 19);
59 TEST_CASE(
"validatable")
61 CHECK(
Date().isValid() ==
false);
62 CHECK(
Date(0, 0, 0).isValid() ==
false);
63 CHECK(
Date(0, 1, 1).isValid() ==
false);
64 CHECK(
Date(2017, -1, 1).isValid() ==
false);
65 CHECK(
Date(2018, 1, -1).isValid() ==
false);
66 CHECK(
Date(2018, -1, -1).isValid() ==
false);
67 CHECK(
Date(1, 1, 1).isValid() ==
true);
87 TEST_CASE(
"comparable")
89 CHECK(
Date(2012, 3, 27) ==
Date(2012, 3, 27));
90 CHECK(
Date(2012, 3, 1) !=
Date(2012, 3, 2));
91 CHECK(
Date(2012, 3, 1) <
Date(2012, 3, 2));
92 CHECK(
Date(2012, 3, 2) <=
Date(2012, 3, 2));
93 CHECK(
Date(2012, 3, 2) <=
Date(2012, 3, 3));
94 CHECK(
Date(2012, 3, 3) >
Date(2012, 3, 2));
95 CHECK(
Date(2012, 3, 3) >=
Date(2012, 3, 3));
96 CHECK(
Date(2012, 3, 4) >=
Date(2012, 3, 3));
105 SUBCASE(
"construction")
109 Date d6(std::move(d3));
115 SUBCASE(
"assignment")
119 Date d6 = std::move(d3);
127 TEST_CASE(
"current date")
129 CHECK(
Date::current() ==
Date(duration_cast<Date::Days>(system_clock::now().time_since_epoch())));
137 TEST_CASE(
"addition & subtraction")
141 CHECK(
Date(2045, 3, 27).addDays(5) ==
Date(2045, 4, 1));
142 CHECK(
Date(2045, 4, 1).subtractDays(5) ==
Date(2045, 3, 27));
146 CHECK(
Date(2018, 1, 1).addDays(0) ==
Date(2018, 1, 1));
147 CHECK(
Date(2018, 1, 1).subtractDays(0) ==
Date(2018, 1, 1));
148 CHECK(
Date(2018, 1, 2).addDays(-1) ==
Date(2018, 1, 1));
149 CHECK(
Date(2018, 1, 1).subtractDays(-1) ==
Date(2018, 1, 2));
170 CHECK(
Date(2012, 3, 27).addMonths(5) ==
Date(2012, 8, 27));
172 CHECK(
Date(2012, 8, 27).addMonths(10) ==
Date(2013, 6, 27));
174 CHECK(
Date(2012, 8, 27).addMonths(4) ==
Date(2012, 12, 27));
176 CHECK(
Date(2012, 3, 27).addMonths(-5) ==
Date(2011, 10, 27));
178 CHECK(
Date(2013, 6, 27).subtractMonths(5) ==
Date(2013, 1, 27));
180 CHECK(
Date(2013, 1, 27).subtractMonths(10) ==
Date(2012, 3, 27));
182 CHECK(
Date(2013, 1, 27).subtractMonths(1) ==
Date(2012, 12, 27));
184 CHECK(
Date(2011, 10, 27).subtractMonths(-5) ==
Date(2012, 3, 27));
186 CHECK(
Date(2013, 1, 31).addMonths(1) ==
Date(2013, 2, 28));
187 CHECK(
Date(2013, 2, 28).addMonths(1) ==
Date(2013, 3, 28));
188 CHECK(
Date(2012, 3, 31).subtractMonths(1) ==
Date(2012, 2, 29));
192 CHECK(
Date(2018, 1, 1).addMonths(0) ==
Date(2018, 1, 1));
193 CHECK(
Date(2018, 1, 1).subtractMonths(0) ==
Date(2018, 1, 1));
197 CHECK(
Date(1966, 11, 2).addYears(40) ==
Date(2006, 11, 2));
198 CHECK(
Date(2006, 11, 2).subtractYears(40) ==
Date(1966, 11, 2));
202 CHECK(
Date(2018, 1, 1).addYears(0) ==
Date(2018, 1, 1));
203 CHECK(
Date(2018, 1, 1).subtractYears(0) ==
Date(2018, 1, 1));
204 CHECK(
Date(2018, 1, 1).addYears(-1) ==
Date(2017, 1, 1));
205 CHECK(
Date(2018, 1, 1).subtractYears(-1) ==
Date(2019, 1, 1));
209 TEST_CASE(
"leap year")
211 CHECK(
Date(2012, 1, 1).isLeapYear());
252 TEST_CASE(
"extraction of individual components")
254 int year, month, day;
269 TEST_CASE(
"calculation")
271 SUBCASE(
"day of week")
273 CHECK(
Date(1970, 1, 1).dayOfWeek() ==
static_cast<int>(Date::Weekday::Thursday));
274 CHECK(
Date(2001, 1, 1).dayOfWeek() == 1);
275 CHECK(
Date(2002, 1, 1).dayOfWeek() == 2);
276 CHECK(
Date(2003, 1, 1).dayOfWeek() == 3);
277 CHECK(
Date(2004, 1, 1).dayOfWeek() == 4);
278 CHECK(
Date(2010, 1, 1).dayOfWeek() == 5);
279 CHECK(
Date(2005, 1, 1).dayOfWeek() == 6);
280 CHECK(
Date(2006, 1, 1).dayOfWeek() == 7);
282 SUBCASE(
"day of year")
284 CHECK(
Date(1970, 1, 1).dayOfYear() == 1);
285 CHECK(
Date(2017, 12, 2).dayOfYear() == 336);
286 CHECK(
Date(2064, 2, 29).dayOfYear() == 60);
288 SUBCASE(
"days in month")
293 CHECK(
Date(1970, 1, 1).daysInMonth() == 31);
294 CHECK(
Date(1970, 2, 1).daysInMonth() == 28);
295 CHECK(
Date(2012, 2, 1).daysInMonth() == 29);
296 CHECK(
Date(2055, 3, 1).daysInMonth() == 31);
297 CHECK(
Date(2013, 4, 1).daysInMonth() == 30);
298 CHECK(
Date(2025, 5, 1).daysInMonth() == 31);
299 CHECK(
Date(2036, 6, 1).daysInMonth() == 30);
300 CHECK(
Date(2057, 7, 1).daysInMonth() == 31);
301 CHECK(
Date(2088, 8, 1).daysInMonth() == 31);
302 CHECK(
Date(2009, 9, 1).daysInMonth() == 30);
303 CHECK(
Date(2001, 10, 1).daysInMonth() == 31);
304 CHECK(
Date(2023, 11, 1).daysInMonth() == 30);
305 CHECK(
Date(2023, 12, 1).daysInMonth() == 31);
307 SUBCASE(
"days in year")
309 CHECK(
Date(1970, 1, 1).daysInYear() == 365);
310 CHECK(
Date(2012, 2, 2).daysInYear() == 366);
312 SUBCASE(
"number of days between two dates")
320 SUBCASE(
"week of year")
325 CHECK(
Date(2017, 12, 3).weekOfYear(&weekYear) == 48);
326 CHECK(weekYear == 2017);
329 CHECK(
Date(2002, 12, 31).weekOfYear(&weekYear) == 1);
330 CHECK(weekYear == 2003);
333 CHECK(
Date(2000, 1, 1).weekOfYear(&weekYear) == 52);
334 CHECK(weekYear == 1999);
337 CHECK(
Date(2010, 1, 1).weekOfYear(&weekYear) == 53);
338 CHECK(weekYear == 2009);
342 TEST_CASE(
"conversion")
344 SUBCASE(
"to Julian day")
346 CHECK(
Date(-4714, 11, 24).toJulianDay() == 0);
347 CHECK(
Date(-4714, 11, 25).toJulianDay() == 1);
348 CHECK(
Date(1970, 1, 1).toJulianDay() == 2440588);
349 CHECK(
Date(2000, 1, 1).toJulianDay() == 2451545);
350 CHECK(
Date(2017, 12, 4).toJulianDay() == 2458092);
368 SUBCASE(
"from Julian day")
384 SUBCASE(
"to days since epoch")
386 CHECK(
Date(1970, 1, 1).toDaysSinceEpoch() == 0);
387 CHECK(
Date(1971, 1, 1).toDaysSinceEpoch() == 365);
391 TEST_CASE(
"formatting")
395 CHECK(
Date(572, 4, 22).toString(
"y") ==
"572");
396 CHECK(
Date(1999, 4, 13).toString(
"yy") ==
"99");
397 CHECK(
Date(1901, 6, 11).toString(
"yy") ==
"01");
398 CHECK(
Date(1999, 7, 4).toString(
"yyyy") ==
"1999");
399 CHECK(
Date(-795, 7, 23).toString(
"yyyy") ==
"0795");
400 CHECK(
Date(-1795, 7, 23).toString(
"#yyyy") ==
"-1795");
401 CHECK(
Date(1795, 7, 23).toString(
"#yyyy") ==
"+1795");
402 CHECK(
Date(-1795, 7, 23).toString(
"yyyy E") ==
"1795 BCE");
403 CHECK(
Date(1795, 7, 23).toString(
"yyyy E") ==
"1795 CE");
404 CHECK(
Date(1795, 7, 23).toString(
"yy . yy") ==
"95 . 95");
408 CHECK(
Date(572, 4, 22).toString(
"M") ==
"4");
409 CHECK(
Date(1999, 5, 13).toString(
"MM") ==
"05");
410 CHECK(
Date(1999, 11, 13).toString(
"MM") ==
"11");
411 CHECK(
Date(1901, 6, 11).toString(
"MMM") ==
"Jun");
412 CHECK(
Date(1999, 7, 30).toString(
"MMMM") ==
"July");
416 CHECK(
Date(572, 4, 22).toString(
"d") ==
"22");
417 CHECK(
Date(1999, 4, 3).toString(
"dd") ==
"03");
418 CHECK(
Date(1901, 6, 11).toString(
"dd") ==
"11");
419 CHECK(
Date(1999, 7, 4).toString(
"ddd") ==
"Sun");
420 CHECK(
Date(2017, 12, 15).toString(
"dddd") ==
"Friday");
425 CHECK(
Date(2017, 12, 19).toString(
"yyyyMMdd ieee") ==
"20171219 ieee");
427 CHECK(
Date().toString(
"yyyy-MM-dd E") ==
"");
431 CHECK(
Date(0, 0, 0).toString(
"") ==
"");
432 CHECK(
Date(0, 0, 0).toString(
"yyyy-MM-dd E") ==
"");
433 CHECK(
Date(0, -1, 1).toString(
"yyyy-MM-dd E") ==
"");
434 CHECK(
Date(0, 1, -1).toString(
"yyyy-MM-dd E") ==
"");
435 CHECK(
Date(0, -1, -1).toString(
"yyyy-MM-dd E") ==
"");
436 CHECK(
Date(572, 4, 22).toString(
"y.M.d") ==
"572.4.22");
437 CHECK(
Date(2017, 4, 3).toString(
"yy.MM.dd") ==
"17.04.03");
438 CHECK(
Date(2007, 5, 11).toString(
"yy.MMM.dd") ==
"07.May.11");
439 CHECK(
Date(2017, 12, 10).toString(
"ddd dd.MM.yyyy") ==
"Sun 10.12.2017");
440 CHECK(
Date(2017, 12, 15).toString(
"dddd dd MMMM yyyy") ==
"Friday 15 December 2017");
441 CHECK(
Date(2017, 12, 16).toString(
"yyyy-MM-dd E") ==
"2017-12-16 CE");
442 CHECK(
Date(-2017, 12, 16).toString(
"#yyyy.MM.dd") ==
"-2017.12.16");
443 CHECK(
Date(2017, 12, 19).toString(
"yyyyMMdd") ==
"20171219");
493 TEST_CASE(
"serialization & deserialization")
496 std::stringstream ss;
497 ss <<
Date(2014, 11, 9);
499 CHECK(d ==
Date(2014, 11, 9));
Date is an immutable class representing a date without a time zone in the ISO-8601 calendar system,...
Definition: date.hpp:84
internal::Days Days
Day duration.
Definition: date.hpp:91
void getYearMonthDay(int *year, int *month, int *day) const
Set the year, month, and day of this date in the parameters year, month, and day, respectively.
Definition: date.hpp:254
int year() const
Returns the year of this date as a number.
Definition: date.hpp:280
static int daysInMonthOfYear(int year, int month)
Returns the number of days in month of year. It ranges between 28 and 31.
Definition: date.hpp:744
static Date fromJulianDay(long julianDay)
Returns a Date object corresponding to the Julian day julianDay.
Definition: date.hpp:688
static Date current()
Returns a Date object set to the current date obtained from the system clock.
Definition: date.hpp:597
int month() const
Returns the month of the year of this date as a number between 1 and 12, which corresponds to the enu...
Definition: date.hpp:271
static Date epoch()
Returns a Date object set to the epoch "1970-01-01".
Definition: date.hpp:603
int day() const
Returns the day of the month of this date as a number between 1 and 31.
Definition: date.hpp:265
static long weeksBetween(const Date &from, const Date &to)
Returns the number of weeks between from and to.
Definition: date.hpp:719
static long daysBetween(const Date &from, const Date &to)
Returns the number of days between from and to.
Definition: date.hpp:707
static Date fromString(const std::string &date, const std::string &format)
Returns a Date object from the date string date according to the format string format.
Definition: date.hpp:612
bool isLeapYear() const
Returns whether the year of this date is a leap year.
Definition: date.hpp:310