1 #include "../chrono/datetime.h"
2 #include "../chrono/format.h"
3 #include "../chrono/period.h"
4 #include "../chrono/timespan.h"
5 #include "../conversion/conversionexception.h"
6 #include "../tests/testutils.h"
8 #include <cppunit/TestFixture.h>
9 #include <cppunit/extensions/HelperMacros.h>
19 using namespace CPPUNIT_NS;
22 static_assert(
DateTime().isNull(),
"isNull()");
23 static_assert(
DateTime(1).totalTicks() == 1,
"construction with ticks");
28 static_assert(DateTime::eternity().isEternity() && !
DateTime().isEternity(),
"isEternity()");
29 static constexpr
auto dateFromUnixEpoch(
30 DateTime::unixEpochStart() + TimeSpan::fromHours(1) + TimeSpan::fromMinutes(2) + TimeSpan::fromSeconds(3.1256789));
31 static_assert(dateFromUnixEpoch.dayOfWeek() == DayOfWeek::Thursday,
"dayOfWeek()");
32 static_assert(dateFromUnixEpoch.hour() == 1,
"hour()");
33 static_assert(dateFromUnixEpoch.minute() == 2,
"minute()");
34 static_assert(dateFromUnixEpoch.second() == 3,
"second()");
35 static_assert(dateFromUnixEpoch.millisecond() == 125,
"millisecond()");
36 static_assert(dateFromUnixEpoch.microsecond() == 678,
"microsecond()");
37 static_assert(dateFromUnixEpoch.nanosecond() == 900,
"nanosecond()");
38 static_assert(dateFromUnixEpoch.isSameDay(DateTime::unixEpochStart()),
"isSameDay()");
39 static_assert(!dateFromUnixEpoch.isSameDay(DateTime::unixEpochStart() + TimeSpan::fromHours(24)),
"!isSameDay()");
42 static_assert(
TimeSpan().isNull(),
"isNull()");
43 static_assert(
TimeSpan(1).totalTicks() == 1,
"construction with ticks");
44 static_assert(
TimeSpan(-1).isNegative() && !
TimeSpan(1).isNegative(),
"isNegative()");
45 static_assert(TimeSpan::infinity().isInfinity() && !
TimeSpan().isInfinity(),
"isInfinity()");
46 static_assert(TimeSpan::negativeInfinity().isNegativeInfinity() && !
TimeSpan().isNegativeInfinity(),
"isNegativeInfinity()");
47 static_assert(TimeSpan::fromMilliseconds(1.0125).nanoseconds() == 500,
"fromMilliseconds()/nanoseconds()");
48 static_assert(TimeSpan::fromMilliseconds(1.0125).microseconds() == 12,
"fromMilliseconds()/microseconds()");
49 static_assert(TimeSpan::fromMilliseconds(1.0125).milliseconds() == 1,
"fromMilliseconds()/milliseconds()");
50 static_assert(TimeSpan::fromSeconds(61).seconds() == 1,
"fromSeconds()/seconds()");
51 static_assert(TimeSpan::fromSeconds(61).minutes() == 1,
"fromSeconds()/minutes()");
52 static_assert(TimeSpan::fromMinutes(61).minutes() == 1,
"fromMinutes()/minutes()");
53 static_assert(TimeSpan::fromHours(25).hours() == 1,
"fromMinutes()/hours()");
54 static_assert(TimeSpan::fromDays(20.5).days() == 20,
"fromDays()/days()");
55 static_assert(TimeSpan::fromMinutes(1.5).totalMicroseconds() == 90e6,
"totalMicroseconds()");
56 static_assert(TimeSpan::fromMinutes(1.5).totalMilliseconds() == 90e3,
"totalMilliseconds()");
57 static_assert(TimeSpan::fromMinutes(1.5).totalSeconds() == 90.0,
"totalSeconds()");
58 static_assert(TimeSpan::fromHours(1.5).totalMinutes() == 90.0,
"totalMinutes()");
59 static_assert(TimeSpan::fromDays(1.5).totalHours() == 36.0,
"totalHours()");
60 static_assert(TimeSpan::fromDays(20.5).totalDays() == 20.5,
"totalDays()");
70 CPPUNIT_TEST(testDateTime);
71 CPPUNIT_TEST(testTimeSpan);
72 CPPUNIT_TEST(testOperators);
73 CPPUNIT_TEST(testPeriod);
74 CPPUNIT_TEST(testHashing);
75 CPPUNIT_TEST_SUITE_END();
100 CPPUNIT_ASSERT_EQUAL(DateTime::daysInMonth(2000, 2), 29);
101 CPPUNIT_ASSERT_EQUAL(DateTime::daysInMonth(2001, 2), 28);
102 CPPUNIT_ASSERT_EQUAL(DateTime::daysInMonth(2100, 2), 28);
103 const auto test1 = DateTime::fromDateAndTime(2012, 2, 29, 15, 34, 20, 33.0);
104 CPPUNIT_ASSERT_EQUAL(2012, test1.year());
105 CPPUNIT_ASSERT_EQUAL(2, test1.month());
106 CPPUNIT_ASSERT_EQUAL(29, test1.day());
107 CPPUNIT_ASSERT_EQUAL(15, test1.hour());
108 CPPUNIT_ASSERT_EQUAL(34, test1.minute());
109 CPPUNIT_ASSERT_EQUAL(20, test1.second());
110 CPPUNIT_ASSERT_EQUAL(33, test1.millisecond());
111 CPPUNIT_ASSERT_EQUAL(DayOfWeek::Wednesday, test1.dayOfWeek());
112 CPPUNIT_ASSERT_EQUAL((31 + 29), test1.dayOfYear());
113 CPPUNIT_ASSERT(test1.isLeapYear());
114 CPPUNIT_ASSERT(test1.isSameDay(test1 + TimeSpan::fromHours(8)));
115 CPPUNIT_ASSERT(!test1.isSameDay(test1 + TimeSpan::fromHours(9)));
116 CPPUNIT_ASSERT_EQUAL(
"Wed 2012-02-29 15:34:20.033"s, test1.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
119 const auto timeStamp =
static_cast<time_t
>(1453840331);
120 const auto fromTimeStampGmt = DateTime::fromTimeStampGmt(timeStamp), fromTimeStamp = DateTime::fromTimeStamp(timeStamp);
121 CPPUNIT_ASSERT_EQUAL(
"Tue 2016-01-26 20:32:11"s, fromTimeStampGmt.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
122 CPPUNIT_ASSERT(fabs((fromTimeStamp - fromTimeStampGmt).totalDays()) <= 1.0);
123 CPPUNIT_ASSERT_EQUAL(
DateTime(), DateTime::fromTimeStamp(0));
124 CPPUNIT_ASSERT_EQUAL(timeStamp, fromTimeStampGmt.toTimeStamp());
127 const auto fromChronoTimePointGmt = DateTime::fromChronoTimePointGmt(chrono::system_clock::from_time_t(timeStamp));
128 CPPUNIT_ASSERT_EQUAL(
"Tue 2016-01-26 20:32:11"s, fromChronoTimePointGmt.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
133 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(0, 2, 29, 15, 34, 20, 33),
ConversionException);
134 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2013, 2, 29, 15, 34, 20, 33),
ConversionException);
135 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 2, 29, 15, 61, 20, 33),
ConversionException);
136 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 4, 31, 15, 0, 20, 33),
ConversionException);
137 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 3, 31, 15, 0, 61, 33),
ConversionException);
138 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 1, 1, 61, 2, 1),
ConversionException);
139 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 1, 1, 15, 2, 1, 2000.0),
ConversionException);
142 CPPUNIT_ASSERT_EQUAL(test1, DateTime::fromString(
"2012-02-29 15:34:20.033"));
143 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"surplus parts ignored", test1, DateTime::fromString(
"2012-02-29 15:34:20.033:12"));
144 CPPUNIT_ASSERT_EQUAL(
"2012-02-29 15:34:20.033"s, test1.toString(DateTimeOutputFormat::DateAndTime,
false));
145 CPPUNIT_ASSERT_THROW(TimeSpan::fromString(
"2012-02-29 15:34:34:20.033"),
ConversionException);
146 const auto test3 = DateTime::fromIsoString(
"2016-08-29T21:32:31.125+02:00");
147 CPPUNIT_ASSERT_EQUAL(
"2016-08-29T21:32:31.125+02:00"s, test3.first.toIsoString(test3.second));
150 const auto test4 = DateTime::fromIsoString(
"2017-08-23T19:40:15.985077682+02:30");
151 CPPUNIT_ASSERT_EQUAL(2.5, test4.second.totalHours());
152 CPPUNIT_ASSERT_EQUAL(15, test4.first.second());
153 CPPUNIT_ASSERT_EQUAL(985, test4.first.millisecond());
154 CPPUNIT_ASSERT_EQUAL(77, test4.first.microsecond());
155 CPPUNIT_ASSERT_EQUAL(600, test4.first.nanosecond());
156 CPPUNIT_ASSERT_EQUAL(
"2017-08-23T19:40:15.9850776+02:30"s, test4.first.toIsoString(test4.second));
158 const auto test5 = DateTime::fromIsoString(
"2017-08-23T19:40:15.985077682-02:30");
159 CPPUNIT_ASSERT_EQUAL(-2.5, test5.second.totalHours());
160 CPPUNIT_ASSERT_EQUAL(15, test5.first.second());
161 CPPUNIT_ASSERT_EQUAL(985, test5.first.millisecond());
162 CPPUNIT_ASSERT_EQUAL(77, test5.first.microsecond());
163 CPPUNIT_ASSERT_EQUAL(600, test5.first.nanosecond());
164 CPPUNIT_ASSERT_EQUAL(
"2017-08-23T19:40:15.9850776-02:30"s, test5.first.toIsoString(test5.second));
166 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"Zulu time",
TimeSpan(), DateTime::fromIsoString(
"2017-08-23T19:40:15.985077682Z").second);
167 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"no minutes", TimeSpan::fromHours(3), DateTime::fromIsoString(
"2017-08-23T19:40:15.985077682+03").second);
168 const auto test6 = DateTime::fromIsoString(
"1970-01-01T01:02:03+01:00");
169 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"no seconds fraction", DateTime::fromDateAndTime(1970, 1, 1, 1, 2, 3), test6.first);
170 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"no seconds fraction", TimeSpan::fromHours(1.0), test6.second);
172 CPPUNIT_ASSERT_THROW_MESSAGE(
"digits after Z", DateTime::fromIsoString(
"2017-O8-23T19:40:15.985077682Z02:00"),
ConversionException);
173 CPPUNIT_ASSERT_THROW_MESSAGE(
"invalid letter", DateTime::fromIsoString(
"2017-O8-23T19:40:15.985077682:+02:00"),
ConversionException);
174 CPPUNIT_ASSERT_THROW_MESSAGE(
"invalid T", DateTime::fromIsoString(
"2017-08-23T19:T40:15.985077682+02:00"),
ConversionException);
175 CPPUNIT_ASSERT_THROW_MESSAGE(
"invalid -", DateTime::fromIsoString(
"2017-08-23T19:40-15.985077682+02:00"),
ConversionException);
176 CPPUNIT_ASSERT_THROW_MESSAGE(
"invalid .", DateTime::fromIsoString(
"2017-08.5-23T19:40:15.985077682+02:00"),
ConversionException);
177 CPPUNIT_ASSERT_THROW_MESSAGE(
"invalid :", DateTime::fromIsoString(
"2017:08-23T19:40:15.985077682+02:00"),
ConversionException);
178 CPPUNIT_ASSERT_THROW_MESSAGE(
"invalid :", DateTime::fromIsoString(
"2017-08-23T19:40:15:985077682+02:00"),
ConversionException);
181 #if defined(PLATFORM_UNIX)
182 const auto delta = DateTime::gmtNow() - DateTime::exactGmtNow();
183 CPPUNIT_ASSERT(delta < TimeSpan::fromSeconds(2) && delta > TimeSpan::fromSeconds(-2));
193 CPPUNIT_ASSERT_EQUAL(
TimeSpan(), TimeSpan::fromString(
string()));
194 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromSeconds(5.0), TimeSpan::fromString(
"5.0"));
195 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromMinutes(5.5), TimeSpan::fromString(
"5:30"));
196 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromHours(7) + TimeSpan::fromMinutes(5.5), TimeSpan::fromString(
"7:5:30"));
197 const auto test1 = TimeSpan::fromString(
"2:34:53:2.5");
199 CPPUNIT_ASSERT_EQUAL(3, test1.days());
200 CPPUNIT_ASSERT_EQUAL(10, test1.hours());
201 CPPUNIT_ASSERT_EQUAL(53, test1.minutes());
202 CPPUNIT_ASSERT_EQUAL(2, test1.seconds());
203 CPPUNIT_ASSERT_EQUAL(500, test1.milliseconds());
204 CPPUNIT_ASSERT(test1.totalDays() > 3.0 && test1.totalDays() < 4.0);
205 CPPUNIT_ASSERT(test1.totalHours() > (2 * 24 + 34) && test1.totalHours() < (2 * 24 + 35));
206 CPPUNIT_ASSERT(test1.totalMinutes() > (2 * 24 * 60 + 34 * 60 + 53) && test1.totalHours() < (2 * 24 * 60 + 34 * 60 + 54));
208 CPPUNIT_ASSERT_EQUAL(
"3 d 10 h 53 min 2 s 500 ms"s, test1.toString(TimeSpanOutputFormat::WithMeasures,
false));
209 CPPUNIT_ASSERT_EQUAL(
"07:05:30"s, (TimeSpan::fromHours(7) + TimeSpan::fromMinutes(5.5)).toString());
210 CPPUNIT_ASSERT_EQUAL(
"-5 s"s, TimeSpan::fromSeconds(-5.0).toString(TimeSpanOutputFormat::WithMeasures,
false));
211 CPPUNIT_ASSERT_EQUAL(
"0 s"s,
TimeSpan().toString(TimeSpanOutputFormat::WithMeasures,
false));
212 CPPUNIT_ASSERT_EQUAL(
"5e+02 µs"s, TimeSpan::fromMilliseconds(0.5).toString(TimeSpanOutputFormat::WithMeasures,
false));
214 const auto test2 = TimeSpan::fromString(
"15.985077682");
215 CPPUNIT_ASSERT_EQUAL(15.9850776, test2.totalSeconds());
216 CPPUNIT_ASSERT_EQUAL(15, test2.seconds());
217 CPPUNIT_ASSERT_EQUAL(985, test2.milliseconds());
218 CPPUNIT_ASSERT_EQUAL(77, test2.microseconds());
219 CPPUNIT_ASSERT_EQUAL(600, test2.nanoseconds());
220 CPPUNIT_ASSERT_EQUAL(
"00:00:15.9850776"s, test2.toString());
221 CPPUNIT_ASSERT_EQUAL(
"15 s 985 ms 77 µs 600 ns"s, test2.toString(TimeSpanOutputFormat::WithMeasures));
222 CPPUNIT_ASSERT_EQUAL(
"15.9850776"s, test2.toString(TimeSpanOutputFormat::TotalSeconds));
233 auto dateTime = DateTime::fromDateAndTime(1999, 1, 5, 4, 16);
234 CPPUNIT_ASSERT_EQUAL(7, (dateTime + TimeSpan::fromDays(2)).day());
235 CPPUNIT_ASSERT_EQUAL(6, (dateTime + TimeSpan::fromHours(24)).day());
236 CPPUNIT_ASSERT_EQUAL(3, (dateTime + TimeSpan::fromHours(24) + TimeSpan::fromHours(-1)).hour());
237 CPPUNIT_ASSERT_EQUAL(17, (dateTime + TimeSpan::fromHours(24) - TimeSpan::fromMinutes(-1)).minute());
238 dateTime += TimeSpan::fromDays(365);
239 CPPUNIT_ASSERT_EQUAL(2000, dateTime.year());
240 CPPUNIT_ASSERT_EQUAL(5, dateTime.day());
248 const auto begin(DateTime::fromDateAndTime(1994, 7, 18, 15, 30, 21)), end(DateTime::fromDateAndTime(2017, 12, 2, 15, 30, 21));
249 const Period period(begin, end);
250 CPPUNIT_ASSERT_EQUAL(23, period.
years());
251 CPPUNIT_ASSERT_EQUAL(4, period.
months());
252 CPPUNIT_ASSERT_EQUAL(14, period.
days());
253 CPPUNIT_ASSERT_EQUAL(end.toString(), (begin + period).toString());
255 const auto end2(DateTime::fromDateAndTime(2018, 1, 2, 15, 30, 21));
256 const Period period2(begin, end2);
257 CPPUNIT_ASSERT_EQUAL(23, period2.
years());
258 CPPUNIT_ASSERT_EQUAL(5, period2.
months());
259 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"one more day, because December has 31 days", 15, period2.
days());
260 CPPUNIT_ASSERT_EQUAL(end2.toString(), (begin + period2).toString());
268 set<DateTime> dateTimes;
269 dateTimes.emplace(DateTime::fromDate(2500, 2, 1));
270 dateTimes.emplace(DateTime::fromDate(2500, 2, 2));
271 dateTimes.emplace(DateTime::fromDate(2500, 2, 1));
272 CPPUNIT_ASSERT_EQUAL(2_st, dateTimes.size());
274 set<TimeSpan> timeSpans;
275 timeSpans.emplace(TimeSpan::fromDays(5));
276 timeSpans.emplace(TimeSpan::fromDays(10));
277 timeSpans.emplace(TimeSpan::fromDays(5));
278 CPPUNIT_ASSERT_EQUAL(2_st, timeSpans.size());