C++ Utilities: tests/chronotests.cpp Source File

C++ Utilities 5.33.0 Useful C++ classes and routines such as argument parser, IO and conversion utilities

Loading...
Searching...
No Matches
chronotests.cpp
Go to the documentation of this file.
1#define CHRONO_UTILITIES_TIMESPAN_INTEGER_SCALE_OVERLOADS
2
3#include "../chrono/datetime.h"
4#include "../chrono/format.h"
5#include "../chrono/period.h"
6#include "../chrono/timespan.h"
7#include "../conversion/conversionexception.h"
8#include "../tests/testutils.h"
9
10#include <cppunit/TestFixture.h>
11#include <cppunit/extensions/HelperMacros.h>
12
13#include <chrono>
14#include <cmath>
15#include <iostream>
16
17using namespace std;
18using namespace CppUtilities;
19using namespace CppUtilities::Literals;
20
21using namespace CPPUNIT_NS;
22
23// compile-time checks for DateTime class
24static_assert(DateTime().isNull(), "isNull()");
25static_assert(DateTime(1).totalTicks() == 1, "construction with ticks");
26static_assert(DateTime(2) == DateTime(2), "operator ==");
27static_assert(DateTime(2) != DateTime(3), "operator !=");
28static_assert(DateTime(2) < DateTime(3), "operator <");
29static_assert(DateTime(3) > DateTime(2), "operator >");
30static_assert(DateTime::eternity().isEternity() && !DateTime().isEternity(), "isEternity()");
31static constexpr auto dateFromUnixEpoch(
32 DateTime::unixEpochStart() + TimeSpan::fromHours(1.0) + TimeSpan::fromMinutes(2.0) + TimeSpan::fromSeconds(3.1256789));
33static_assert(dateFromUnixEpoch.dayOfWeek() == DayOfWeek::Thursday, "dayOfWeek()");
34static_assert(dateFromUnixEpoch.hour() == 1, "hour()");
35static_assert(dateFromUnixEpoch.minute() == 2, "minute()");
36static_assert(dateFromUnixEpoch.second() == 3, "second()");
37static_assert(dateFromUnixEpoch.millisecond() == 125, "millisecond()");
38static_assert(dateFromUnixEpoch.microsecond() == 678, "microsecond()");
39static_assert(dateFromUnixEpoch.nanosecond() == 900, "nanosecond()");
40static_assert(dateFromUnixEpoch.isSameDay(DateTime::unixEpochStart()), "isSameDay()");
41static_assert(!dateFromUnixEpoch.isSameDay(DateTime::unixEpochStart() + TimeSpan::fromHours(24.0)), "!isSameDay()");
42
43// compile-time checks for TimeSpan class
44static_assert(TimeSpan().isNull(), "isNull()");
45static_assert(TimeSpan(1).totalTicks() == 1, "construction with ticks");
46static_assert(TimeSpan(-1).isNegative() && !TimeSpan(1).isNegative(), "isNegative()");
47static_assert(TimeSpan::infinity().isInfinity() && !TimeSpan().isInfinity(), "isInfinity()");
48static_assert(TimeSpan::negativeInfinity().isNegativeInfinity() && !TimeSpan().isNegativeInfinity(), "isNegativeInfinity()");
49static_assert(TimeSpan::fromMilliseconds(1.0125).nanoseconds() == 500, "fromMilliseconds()/nanoseconds()");
50static_assert(TimeSpan::fromMilliseconds(1.0125).microseconds() == 12, "fromMilliseconds()/microseconds()");
51static_assert(TimeSpan::fromMilliseconds(1.0125).milliseconds() == 1, "fromMilliseconds()/milliseconds()");
52static_assert(TimeSpan::fromSeconds(TimeSpan::TickType(61)).seconds() == 1, "fromSeconds()/seconds()");
53static_assert(TimeSpan::fromSeconds(TimeSpan::TickType(61)).minutes() == 1, "fromSeconds()/minutes()");
54static_assert(TimeSpan::fromMinutes(TimeSpan::TickType(61)).minutes() == 1, "fromMinutes()/minutes()");
55static_assert(TimeSpan::fromHours(TimeSpan::TickType(25)).hours() == 1, "fromMinutes()/hours()");
56static_assert(TimeSpan::fromDays(20.5).days() == 20, "fromDays()/days()");
57static_assert(TimeSpan::fromMinutes(1.5).totalMicroseconds() == 90e6, "totalMicroseconds()");
58static_assert(TimeSpan::fromMinutes(1.5).totalMilliseconds() == 90e3, "totalMilliseconds()");
59static_assert(TimeSpan::fromMinutes(1.5).totalSeconds() == 90.0, "totalSeconds()");
60static_assert(TimeSpan::fromHours(1.5).totalMinutes() == 90.0, "totalMinutes()");
61static_assert(TimeSpan::fromDays(1.5).totalHours() == 36.0, "totalHours()");
62static_assert(TimeSpan::fromDays(20.5).totalDays() == 20.5, "totalDays()");
63
70 class ChronoTests : public TestFixture {
71 CPPUNIT_TEST_SUITE(ChronoTests);
72 CPPUNIT_TEST(testDateTime);
73 CPPUNIT_TEST(testDateTimeExpression);
74 CPPUNIT_TEST(testTimeSpan);
75 CPPUNIT_TEST(testOperators);
76 CPPUNIT_TEST(testPeriod);
77 CPPUNIT_TEST(testHashing);
78 CPPUNIT_TEST_SUITE_END();
79
80public:
81 void setUp()
82 {
83 }
84 void tearDown()
85 {
86 }
87
88 void testDateTime();
89 void testDateTimeExpression();
90 void testTimeSpan();
91 void testOperators();
92 void testPeriod();
93 void testHashing();
94};
95
96CPPUNIT_TEST_SUITE_REGISTRATION(ChronoTests);
97
101 void ChronoTests::testDateTime()
102{
103 // test year(), month(), ...
104 CPPUNIT_ASSERT_EQUAL(DateTime::daysInMonth(2000, 2), 29);
105 CPPUNIT_ASSERT_EQUAL(DateTime::daysInMonth(2001, 2), 28);
106 CPPUNIT_ASSERT_EQUAL(DateTime::daysInMonth(2100, 2), 28);
107 const auto test1 = DateTime::fromDateAndTime(2012, 2, 29, 15, 34, 20, 33.0);
108 CPPUNIT_ASSERT_EQUAL(2012, test1.year());
109 CPPUNIT_ASSERT_EQUAL(2, test1.month());
110 CPPUNIT_ASSERT_EQUAL(29, test1.day());
111 CPPUNIT_ASSERT_EQUAL(15, test1.hour());
112 CPPUNIT_ASSERT_EQUAL(34, test1.minute());
113 CPPUNIT_ASSERT_EQUAL(20, test1.second());
114 CPPUNIT_ASSERT_EQUAL(33, test1.millisecond());
115 CPPUNIT_ASSERT_EQUAL(DayOfWeek::Wednesday, test1.dayOfWeek());
116 CPPUNIT_ASSERT_EQUAL((31 + 29), test1.dayOfYear());
117 CPPUNIT_ASSERT(test1.isLeapYear());
118 CPPUNIT_ASSERT(test1.isSameDay(test1 + TimeSpan::fromHours(8.0)));
119 CPPUNIT_ASSERT(!test1.isSameDay(test1 + TimeSpan::fromHours(9.0)));
120 CPPUNIT_ASSERT_EQUAL("Wed 2012-02-29 15:34:20.033"s, test1.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
121 const auto test2 = DateTime::fromDateAndTime(1, 1, 1, 15, 34, 20, 33.0);
122 CPPUNIT_ASSERT_EQUAL(1, test2.year());
123 CPPUNIT_ASSERT_EQUAL(1, test2.month());
124 CPPUNIT_ASSERT_EQUAL(1, test2.day());
125 CPPUNIT_ASSERT_EQUAL(15, test2.hour());
126 CPPUNIT_ASSERT_EQUAL(34, test2.minute());
127 CPPUNIT_ASSERT_EQUAL(20, test2.second());
128 CPPUNIT_ASSERT_EQUAL(33, test2.millisecond());
129
130 // test fromTimeStamp()/toTimeStamp()
131 const auto timeStamp = static_cast<time_t>(1453840331);
132 const auto fromTimeStampGmt = DateTime::fromTimeStampGmt(timeStamp), fromTimeStamp = DateTime::fromTimeStamp(timeStamp);
133 CPPUNIT_ASSERT_EQUAL("Tue 2016-01-26 20:32:11"s, fromTimeStampGmt.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
134 CPPUNIT_ASSERT(fabs((fromTimeStamp - fromTimeStampGmt).totalDays()) <= 1.0);
135 CPPUNIT_ASSERT_EQUAL(DateTime(), DateTime::fromTimeStamp(0));
136 CPPUNIT_ASSERT_EQUAL(timeStamp, fromTimeStampGmt.toTimeStamp());
137
138 // test fromChronoTimePointGmt()
139 const auto fromChronoTimePointGmt = DateTime::fromChronoTimePointGmt(chrono::system_clock::from_time_t(timeStamp));
140 CPPUNIT_ASSERT_EQUAL("Tue 2016-01-26 20:32:11"s, fromChronoTimePointGmt.toString(DateTimeOutputFormat::DateTimeAndShortWeekday));
141
142 // test whether ConversionException() is thrown when invalid values are specified
143 CPPUNIT_ASSERT_THROW(DateTime::fromDate(0, 1, 1), ConversionException);
144 CPPUNIT_ASSERT_THROW(DateTime::fromDate(2012, 15, 1), ConversionException);
145 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(0, 2, 29, 15, 34, 20, 33), ConversionException);
146 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2013, 2, 29, 15, 34, 20, 33), ConversionException);
147 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 2, 29, 15, 61, 20, 33), ConversionException);
148 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 4, 31, 15, 0, 20, 33), ConversionException);
149 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 3, 31, 15, 0, 61, 33), ConversionException);
150 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 1, 1, 61, 2, 1), ConversionException);
151 CPPUNIT_ASSERT_THROW(DateTime::fromDateAndTime(2012, 1, 1, 15, 2, 1, 2000.0), ConversionException);
152
153 // test fromString()/toString()
154 CPPUNIT_ASSERT_EQUAL(test1, DateTime::fromString("2012-02-29 15:34:20.033"));
155 CPPUNIT_ASSERT_EQUAL_MESSAGE("surplus parts ignored", test1, DateTime::fromString("2012-02-29 15:34:20.033:12"));
156 CPPUNIT_ASSERT_EQUAL("2012-02-29 15:34:20.033"s, test1.toString(DateTimeOutputFormat::DateAndTime, false));
157 CPPUNIT_ASSERT_THROW(TimeSpan::fromString("2012-02-29 15:34:34:20.033"), ConversionException);
158 const auto test3 = DateTime::fromIsoString("2016-08-29T21:32:31.125+02:00");
159 CPPUNIT_ASSERT_EQUAL("2016-08-29T21:32:31.125+02:00"s, test3.first.toIsoString(test3.second));
160 CPPUNIT_ASSERT_THROW(DateTime::fromString("#"), ConversionException);
161 // test accuracy (of 100 nanoseconds)
162 const auto test4 = DateTime::fromIsoString("2017-08-23T19:40:15.985077682+02:30");
163 CPPUNIT_ASSERT_EQUAL(2.5, test4.second.totalHours());
164 CPPUNIT_ASSERT_EQUAL(15, test4.first.second());
165 CPPUNIT_ASSERT_EQUAL(985, test4.first.millisecond());
166 CPPUNIT_ASSERT_EQUAL(77, test4.first.microsecond());
167 CPPUNIT_ASSERT_EQUAL(600, test4.first.nanosecond());
168 CPPUNIT_ASSERT_EQUAL("2017-08-23T19:40:15.9850776+02:30"s, test4.first.toIsoString(test4.second));
169 // test negative delta
170 const auto test5 = DateTime::fromIsoString("2017-08-23T19:40:15.985077682-02:30");
171 CPPUNIT_ASSERT_EQUAL(-2.5, test5.second.totalHours());
172 CPPUNIT_ASSERT_EQUAL(15, test5.first.second());
173 CPPUNIT_ASSERT_EQUAL(985, test5.first.millisecond());
174 CPPUNIT_ASSERT_EQUAL(77, test5.first.microsecond());
175 CPPUNIT_ASSERT_EQUAL(600, test5.first.nanosecond());
176 CPPUNIT_ASSERT_EQUAL("2017-08-23T19:40:15.9850776-02:30"s, test5.first.toIsoString(test5.second));
177 // test further variants
178 CPPUNIT_ASSERT_EQUAL_MESSAGE("only year", DateTime::fromDate(2008), DateTime::fromIsoStringGmt("2008"));
179 CPPUNIT_ASSERT_EQUAL_MESSAGE("only year and month", DateTime::fromDate(2008, 12), DateTime::fromIsoStringGmt("2008-12"));
180 CPPUNIT_ASSERT_EQUAL_MESSAGE("only date", DateTime::fromDate(2008, 12, 5), DateTime::fromIsoStringGmt("2008-12-05"));
181 CPPUNIT_ASSERT_EQUAL_MESSAGE("Zulu time", TimeSpan(), DateTime::fromIsoString("2017-08-23T19:40:15.985077682Z").second);
182 CPPUNIT_ASSERT_EQUAL_MESSAGE("no minutes", TimeSpan::fromHours(3.0), DateTime::fromIsoString("2017-08-23T19:40:15.985077682+03").second);
183 const auto test6 = DateTime::fromIsoString("1970-01-01T01:02:03+01:00");
184 CPPUNIT_ASSERT_EQUAL_MESSAGE("no seconds fraction (positive timezone offset, 1)", DateTime::fromDateAndTime(1970, 1, 1, 1, 2, 3), test6.first);
185 CPPUNIT_ASSERT_EQUAL_MESSAGE("no seconds fraction (positive timezone offset, 2)", TimeSpan::fromHours(1.0), test6.second);
186 const auto test7 = DateTime::fromIsoString("2021-05-20T23:02:45-04:00");
187 CPPUNIT_ASSERT_EQUAL_MESSAGE("no seconds fraction (negative timezone offset, 1)", DateTime::fromDateAndTime(2021, 5, 20, 23, 2, 45), test7.first);
188 CPPUNIT_ASSERT_EQUAL_MESSAGE("no seconds fraction (negative timezone offset, 2)", TimeSpan::fromHours(-4.0), test7.second);
189 // implied separators / too many digits
190 CPPUNIT_ASSERT_EQUAL_MESSAGE("no separators", test5.first - test5.second, DateTime::fromIsoStringGmt("20170823T194015.985077682-0230"));
191 CPPUNIT_ASSERT_EQUAL_MESSAGE(
192 "not even T separator", DateTime::fromDateAndTime(2017, 8, 23, 19, 40, 15), DateTime::fromIsoStringGmt("20170823194015"));
193 CPPUNIT_ASSERT_THROW_MESSAGE("too many digits after seconds", DateTime::fromIsoString("2017082319401516"), ConversionException);
194 CPPUNIT_ASSERT_THROW_MESSAGE("too many digits after timezone offset", DateTime::fromIsoString("20170823194015.16+02300"), ConversionException);
195 // test invalid characters
196 CPPUNIT_ASSERT_THROW_MESSAGE("digits after Z", DateTime::fromIsoString("2017-O8-23T19:40:15.985077682Z02:00"), ConversionException);
197 CPPUNIT_ASSERT_THROW_MESSAGE("invalid letter", DateTime::fromIsoString("2017-O8-23T19:40:15.985077682:+02:00"), ConversionException);
198 CPPUNIT_ASSERT_THROW_MESSAGE("invalid T", DateTime::fromIsoString("2017-08-23T19:T40:15.985077682+02:00"), ConversionException);
199 CPPUNIT_ASSERT_THROW_MESSAGE("invalid -", DateTime::fromIsoString("2017-08-23T19:40-15.985077682+02:00"), ConversionException);
200 CPPUNIT_ASSERT_THROW_MESSAGE("invalid .", DateTime::fromIsoString("2017-08.5-23T19:40:15.985077682+02:00"), ConversionException);
201 CPPUNIT_ASSERT_THROW_MESSAGE("invalid :", DateTime::fromIsoString("2017:08-23T19:40:15.985077682+02:00"), ConversionException);
202 CPPUNIT_ASSERT_THROW_MESSAGE("invalid :", DateTime::fromIsoString("2017-08-23T19:40:15:985077682+02:00"), ConversionException);
203 // ISO string via toString() format option
204 CPPUNIT_ASSERT_EQUAL("1234-05-06T07:08:09.0105005"s, DateTime::fromDateAndTime(1234, 5, 6, 7, 8, 9, 10.5005).toString(DateTimeOutputFormat::Iso));
205 CPPUNIT_ASSERT_EQUAL("1234-05-06T07:08:09.0105005"s,
206 DateTime::fromDateAndTime(1234, 5, 6, 7, 8, 9, 10.5005).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
207 CPPUNIT_ASSERT_EQUAL("1234-05-06T07:08:09.010500"s,
208 DateTime::fromDateAndTime(1234, 5, 6, 7, 8, 9, 10.500).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
209 CPPUNIT_ASSERT_EQUAL(
210 "1234-05-06T07:08:09.010"s, DateTime::fromDateAndTime(1234, 5, 6, 7, 8, 9, 10).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
211 CPPUNIT_ASSERT_EQUAL(
212 "1234-05-06T07:08:09"s, DateTime::fromDateAndTime(1234, 5, 6, 7, 8, 9).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
213 CPPUNIT_ASSERT_EQUAL(
214 "1234-05-06T07:08"s, DateTime::fromDateAndTime(1234, 5, 6, 7, 8).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
215 CPPUNIT_ASSERT_EQUAL("1234-05-06T07"s, DateTime::fromDateAndTime(1234, 5, 6, 7).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
216 CPPUNIT_ASSERT_EQUAL("1234-05-06"s, DateTime::fromDateAndTime(1234, 5, 6).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
217 CPPUNIT_ASSERT_EQUAL("1234-05"s, DateTime::fromDateAndTime(1234, 5).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
218 CPPUNIT_ASSERT_EQUAL("1234"s, DateTime::fromDateAndTime(1234).toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
219 CPPUNIT_ASSERT_EQUAL("0001"s, DateTime().toString(DateTimeOutputFormat::IsoOmittingDefaultComponents));
220
221 // test now() and exactNow() (or at least whether both behave the same)
222 const auto delta = DateTime::gmtNow() - DateTime::exactGmtNow();
223 CPPUNIT_ASSERT(delta < TimeSpan::fromSeconds(2.0) && delta > TimeSpan::fromSeconds(-2.0));
224}
225
229 void ChronoTests::testDateTimeExpression()
230{
231 // check adding ISO timestamp parts one-by-one and serialization back to string
232 auto expr = DateTimeExpression::fromIsoString("1");
233 auto parts = DateTimeParts::Year;
234 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
235 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
236 CPPUNIT_ASSERT_EQUAL(parts, expr.parts);
237 CPPUNIT_ASSERT_EQUAL("0001"s, expr.toIsoString());
238 expr = DateTimeExpression::fromIsoString("1-1");
239 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
240 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
241 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Month, expr.parts);
242 CPPUNIT_ASSERT_EQUAL("0001-01"s, expr.toIsoString());
243 expr = DateTimeExpression::fromIsoString("1-1-1");
244 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
245 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
246 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Day, expr.parts);
247 CPPUNIT_ASSERT_EQUAL("0001-01-01"s, expr.toIsoString());
248 expr = DateTimeExpression::fromIsoString("1-1-1T0");
249 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
250 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
251 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Hour, expr.parts);
252 CPPUNIT_ASSERT_EQUAL("0001-01-01T00"s, expr.toIsoString());
253 expr = DateTimeExpression::fromIsoString("1-1-1T0:0");
254 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
255 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
256 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Minute, expr.parts);
257 CPPUNIT_ASSERT_EQUAL("0001-01-01T00:00"s, expr.toIsoString());
258 expr = DateTimeExpression::fromIsoString("1-1-1T0:0:0");
259 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
260 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
261 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Second, expr.parts);
262 CPPUNIT_ASSERT_EQUAL("0001-01-01T00:00:00"s, expr.toIsoString());
263 expr = DateTimeExpression::fromIsoString("1-1-1T0:0:0.0");
264 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
265 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
266 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::SubSecond, expr.parts);
267 CPPUNIT_ASSERT_EQUAL("0001-01-01T00:00:00.000"s, expr.toIsoString());
268 expr = DateTimeExpression::fromIsoString("1-1-1T0:0:0.0+0");
269 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
270 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
271 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::DeltaHour, expr.parts);
272 CPPUNIT_ASSERT_EQUAL("0001-01-01T00:00:00.000+00"s, expr.toIsoString());
273 expr = DateTimeExpression::fromIsoString("1-1-1T0:0:0.0-0:0");
274 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
275 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
276 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::DeltaMinute, expr.parts);
277 CPPUNIT_ASSERT_EQUAL("0001-01-01T00:00:00.000+00:00"s, expr.toIsoString());
278
279 // check that omitting parts in the middle is not possible anyways
280 CPPUNIT_ASSERT_THROW(DateTimeExpression::fromIsoString("1-1T0"), ConversionException);
281
282 // check ::fromString()
283 expr = DateTimeExpression::fromString("1");
284 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
285 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
286 CPPUNIT_ASSERT_EQUAL(parts = DateTimeParts::Year, expr.parts);
287 expr = DateTimeExpression::fromString("1/1");
288 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
289 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
290 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Month, expr.parts);
291 expr = DateTimeExpression::fromString("1/1/1");
292 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
293 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
294 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Day, expr.parts);
295 expr = DateTimeExpression::fromString("1/1/1 0");
296 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
297 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
298 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Hour, expr.parts);
299 expr = DateTimeExpression::fromString("1/1/1 0:0");
300 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
301 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
302 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Minute, expr.parts);
303 expr = DateTimeExpression::fromString("1/1/1 0:0:0");
304 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
305 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
306 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::Second, expr.parts);
307 expr = DateTimeExpression::fromString("1/1/1 0:0:0.0");
308 CPPUNIT_ASSERT_EQUAL(DateTime(), expr.value);
309 CPPUNIT_ASSERT_EQUAL(TimeSpan(), expr.delta);
310 CPPUNIT_ASSERT_EQUAL(parts |= DateTimeParts::SubSecond, expr.parts);
311}
312
316 void ChronoTests::testTimeSpan()
317{
318 // test various usages of fromString(...), all other from...() functions and the plus operator
319 CPPUNIT_ASSERT_EQUAL(TimeSpan(), TimeSpan::fromString(string()));
320 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromSeconds(5.0), TimeSpan::fromString("5.0"));
321 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromMinutes(5.5), TimeSpan::fromString("5:30"));
322 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromHours(7.0) + TimeSpan::fromMinutes(5.5), TimeSpan::fromString("7:5:30"));
323 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(14.0), TimeSpan::fromString("14:::"));
324 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(14.0), TimeSpan::fromString("14d"));
325 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(14.0) + TimeSpan::fromHours(5.0), TimeSpan::fromString("14d 5h"));
326 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(14.0) + TimeSpan::fromMinutes(5.0), TimeSpan::fromString(" 14d 5m"));
327 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(14.0) + TimeSpan::fromMinutes(5.0) + TimeSpan::fromSeconds(24.5), TimeSpan::fromString("2 w 24.5s 5m "));
328 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(14.0) + TimeSpan::fromSeconds(24.5), TimeSpan::fromString("2 w 24.5"));
329 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(14.0) + TimeSpan::fromString("1:2:3:4"), TimeSpan::fromString("2 w 1:2:3:4"));
330 CPPUNIT_ASSERT_THROW(TimeSpan::fromString("2:34a:53:32.5"), ConversionException);
331 CPPUNIT_ASSERT_THROW(TimeSpan::fromString("1:2:3:4:5"), ConversionException);
332
333 // test fromString(...) again and days(), hours(), ...
334 const auto test1 = TimeSpan::fromString("2:34:53:2.5");
335 CPPUNIT_ASSERT_EQUAL(3, test1.days());
336 CPPUNIT_ASSERT_EQUAL(10, test1.hours());
337 CPPUNIT_ASSERT_EQUAL(53, test1.minutes());
338 CPPUNIT_ASSERT_EQUAL(2, test1.seconds());
339 CPPUNIT_ASSERT_EQUAL(500, test1.milliseconds());
340 CPPUNIT_ASSERT(test1.totalDays() > 3.0 && test1.totalDays() < 4.0);
341 CPPUNIT_ASSERT(test1.totalHours() > (2 * 24 + 34) && test1.totalHours() < (2 * 24 + 35));
342 CPPUNIT_ASSERT(test1.totalMinutes() > (2 * 24 * 60 + 34 * 60 + 53) && test1.totalHours() < (2 * 24 * 60 + 34 * 60 + 54));
343
344 // test toString(...)
345 CPPUNIT_ASSERT_EQUAL("3 d 10 h 53 min 2 s 500 ms"s, test1.toString(TimeSpanOutputFormat::WithMeasures, false));
346 CPPUNIT_ASSERT_EQUAL("07:05:30"s, (TimeSpan::fromHours(7.0) + TimeSpan::fromMinutes(5.5)).toString());
347 CPPUNIT_ASSERT_EQUAL("-5 s"s, TimeSpan::fromSeconds(-5.0).toString(TimeSpanOutputFormat::WithMeasures, false));
348 CPPUNIT_ASSERT_EQUAL("0 s"s, TimeSpan().toString(TimeSpanOutputFormat::WithMeasures, false));
349 CPPUNIT_ASSERT_EQUAL("5e+02 µs"s, TimeSpan::fromMilliseconds(0.5).toString(TimeSpanOutputFormat::WithMeasures, false));
350
351 // test accuracy (of 100 nanoseconds)
352 const auto test2 = TimeSpan::fromString("15.985077682");
353 CPPUNIT_ASSERT_EQUAL(15.9850776, test2.totalSeconds());
354 CPPUNIT_ASSERT_EQUAL(15, test2.seconds());
355 CPPUNIT_ASSERT_EQUAL(985, test2.milliseconds());
356 CPPUNIT_ASSERT_EQUAL(77, test2.microseconds());
357 CPPUNIT_ASSERT_EQUAL(600, test2.nanoseconds());
358 CPPUNIT_ASSERT_EQUAL("00:00:15.9850776"s, test2.toString());
359 CPPUNIT_ASSERT_EQUAL("15 s 985 ms 77 µs 600 ns"s, test2.toString(TimeSpanOutputFormat::WithMeasures));
360 CPPUNIT_ASSERT_EQUAL("15.9850776"s, test2.toString(TimeSpanOutputFormat::TotalSeconds));
361}
362
366 void ChronoTests::testOperators()
367{
368 auto dateTime = DateTime::fromDateAndTime(1999, 1, 5, 4, 16);
369 CPPUNIT_ASSERT_EQUAL(7, (dateTime + TimeSpan::fromDays(2.0)).day());
370 CPPUNIT_ASSERT_EQUAL(6, (dateTime + TimeSpan::fromHours(24.0)).day());
371 CPPUNIT_ASSERT_EQUAL(3, (dateTime + TimeSpan::fromHours(24.0) + TimeSpan::fromHours(-1.0)).hour());
372 CPPUNIT_ASSERT_EQUAL(17, (dateTime + TimeSpan::fromHours(24.0) - TimeSpan::fromMinutes(-1.0)).minute());
373 dateTime += TimeSpan::fromDays(365.0);
374 CPPUNIT_ASSERT_EQUAL(2000, dateTime.year());
375 CPPUNIT_ASSERT_EQUAL(5, dateTime.day());
376 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(1.0), TimeSpan::fromHours(12.0) * 2.0);
377 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromHours(12.0), TimeSpan::fromDays(1.0) / 2.0);
378 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromDays(1.0), TimeSpan::fromHours(12.0) * TimeSpan::TickType(2));
379 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromHours(12.0), TimeSpan::fromDays(1.0) / TimeSpan::TickType(2));
380 CPPUNIT_ASSERT_EQUAL(2.0, TimeSpan::fromDays(1.0) / TimeSpan::fromHours(12.0));
381}
382
386 void ChronoTests::testPeriod()
387{
388 const auto begin(DateTime::fromDateAndTime(1994, 7, 18, 15, 30, 21)), end(DateTime::fromDateAndTime(2017, 12, 2, 15, 30, 21));
389 const Period period(begin, end);
390 CPPUNIT_ASSERT_EQUAL(23, period.years());
391 CPPUNIT_ASSERT_EQUAL(4, period.months());
392 CPPUNIT_ASSERT_EQUAL(14, period.days());
393 CPPUNIT_ASSERT_EQUAL(end.toString(), (begin + period).toString());
394
395 const auto end2(DateTime::fromDateAndTime(2018, 1, 2, 15, 30, 21));
396 const Period period2(begin, end2);
397 CPPUNIT_ASSERT_EQUAL(23, period2.years());
398 CPPUNIT_ASSERT_EQUAL(5, period2.months());
399 CPPUNIT_ASSERT_EQUAL_MESSAGE("one more day, because December has 31 days", 15, period2.days());
400 CPPUNIT_ASSERT_EQUAL(end2.toString(), (begin + period2).toString());
401}
402
406 void ChronoTests::testHashing()
407{
408 set<DateTime> dateTimes;
409 dateTimes.emplace(DateTime::fromDate(2500, 2, 1));
410 dateTimes.emplace(DateTime::fromDate(2500, 2, 2));
411 dateTimes.emplace(DateTime::fromDate(2500, 2, 1));
412 CPPUNIT_ASSERT_EQUAL(2_st, dateTimes.size());
413
414 set<TimeSpan> timeSpans;
415 timeSpans.emplace(TimeSpan::fromDays(5.0));
416 timeSpans.emplace(TimeSpan::fromDays(10.0));
417 timeSpans.emplace(TimeSpan::fromDays(5.0));
418 CPPUNIT_ASSERT_EQUAL(2_st, timeSpans.size());
419}
CPPUNIT_TEST_SUITE_REGISTRATION
CPPUNIT_TEST_SUITE_REGISTRATION(ChronoTests)
ChronoTests
The ChronoTests class tests classes and functions provided by the files inside the chrono directory.
Definition chronotests.cpp:70
ChronoTests::setUp
void setUp()
Definition chronotests.cpp:81
ChronoTests::testTimeSpan
void testTimeSpan()
Tests most important TimeSpan features.
Definition chronotests.cpp:316
ChronoTests::testHashing
void testHashing()
Tests hashing DateTime / TimeSpan by using in a set.
Definition chronotests.cpp:406
ChronoTests::testOperators
void testOperators()
Tests operators of DateTime / TimeSpan.
Definition chronotests.cpp:366
ChronoTests::testDateTime
void testDateTime()
Tests most important DateTime features.
Definition chronotests.cpp:101
ChronoTests::testPeriod
void testPeriod()
Tests Period.
Definition chronotests.cpp:386
ChronoTests::testDateTimeExpression
void testDateTimeExpression()
Tests parsing a DateTimeExpression.
Definition chronotests.cpp:229
ChronoTests::tearDown
void tearDown()
Definition chronotests.cpp:84
CppUtilities::ConversionException
The ConversionException class is thrown by the various conversion functions of this library when a co...
Definition conversionexception.h:11
CppUtilities::DateTime::fromTimeStampGmt
static constexpr DateTime fromTimeStampGmt(std::time_t timeStamp)
Constructs a new DateTime object with the GMT time from the specified UNIX timeStamp.
Definition datetime.h:272
CppUtilities::DateTime::unixEpochStart
static constexpr DateTime unixEpochStart()
Returns the DateTime object for the "1970-01-01T00:00:00Z".
Definition datetime.h:492
CppUtilities::DateTime::fromChronoTimePointGmt
static constexpr DateTime fromChronoTimePointGmt(TimePoint timePoint)
Constructs a new DateTime object with the GMT time from the specified std::chrono::time_point.
Definition datetime.h:292
CppUtilities::DateTime::fromIsoString
static std::pair< DateTime, TimeSpan > fromIsoString(const char *str)
Parses the specified ISO date time denotation provided as C-style string.
Definition datetime.cpp:112
CppUtilities::DateTime::exactGmtNow
static DateTime exactGmtNow()
Returns a DateTime object that is set to the current date and time on this computer,...
Definition datetime.cpp:284
CppUtilities::DateTime::fromString
static DateTime fromString(const std::string &str)
Parses the given std::string as DateTime.
Definition datetime.h:242
CppUtilities::DateTime::fromDateAndTime
static DateTime fromDateAndTime(int year=1, int month=1, int day=1, int hour=0, int minute=0, int second=0, double millisecond=0.0)
Constructs a DateTime to the specified year, month, day, hour, minute, second and millisecond.
Definition datetime.h:228
CppUtilities::DateTime::fromDate
static DateTime fromDate(int year=1, int month=1, int day=1)
Constructs a DateTime to the specified year, month, and day.
Definition datetime.h:209
CppUtilities::DateTime::gmtNow
static DateTime gmtNow()
Returns a DateTime object that is set to the current date and time on this computer,...
Definition datetime.h:510
CppUtilities::DateTime::fromTimeStamp
static DateTime fromTimeStamp(std::time_t timeStamp)
Constructs a new DateTime object with the local time from the specified UNIX timeStamp.
Definition datetime.cpp:76
CppUtilities::DateTime::isEternity
constexpr bool isEternity() const
Returns whether the instance has the maximal number of ticks.
Definition datetime.h:432
CppUtilities::DateTime::fromIsoStringGmt
static DateTime fromIsoStringGmt(const char *str)
Parses the specified ISO date time denotation provided as C-style string.
Definition datetime.h:253
CppUtilities::DateTime::daysInMonth
static int daysInMonth(int year, int month)
Returns the number of days in the specified month and year.
Definition datetime.h:448
CppUtilities::DateTime::eternity
static constexpr DateTime eternity()
Constructs a new instance of the DateTime class with the maximal number of ticks.
Definition datetime.h:484
CppUtilities::Period
Represents a period of time.
Definition period.h:8
CppUtilities::Period::days
constexpr int days() const
Returns the days component of the period represented by the current instance.
Definition period.h:48
CppUtilities::Period::years
constexpr int years() const
Returns the years component of the period represented by the current instance.
Definition period.h:32
CppUtilities::Period::months
constexpr int months() const
Returns the months component of the period represented by the current instance.
Definition period.h:40
CppUtilities::TimeSpan
Represents a time interval.
Definition timespan.h:25
CppUtilities::TimeSpan::totalHours
constexpr double totalHours() const
Returns the value of the current TimeSpan class expressed in whole and fractional hours.
Definition timespan.h:289
CppUtilities::TimeSpan::totalSeconds
constexpr double totalSeconds() const
Returns the value of the current TimeSpan class expressed in whole and fractional seconds.
Definition timespan.h:273
CppUtilities::TimeSpan::isNull
constexpr bool isNull() const
Returns true if the time interval represented by the current TimeSpan class is null.
Definition timespan.h:538
CppUtilities::TimeSpan::seconds
constexpr int seconds() const
Returns the seconds component of the time interval represented by the current TimeSpan class.
Definition timespan.h:331
CppUtilities::TimeSpan::isNegativeInfinity
constexpr bool isNegativeInfinity() const
Returns whether the time interval represented by the current instance is the smallest representable T...
Definition timespan.h:554
CppUtilities::TimeSpan::minutes
constexpr int minutes() const
Returns the minutes component of the time interval represented by the current TimeSpan class.
Definition timespan.h:339
CppUtilities::TimeSpan::totalMicroseconds
constexpr double totalMicroseconds() const
Returns the value of the current TimeSpan class expressed in whole and fractional microseconds.
Definition timespan.h:257
CppUtilities::TimeSpan::totalTicks
constexpr TickType totalTicks() const
Returns the number of ticks that represent the value of the current TimeSpan class.
Definition timespan.h:249
CppUtilities::TimeSpan::days
constexpr int days() const
Returns the days component of the time interval represented by the current TimeSpan class.
Definition timespan.h:355
CppUtilities::TimeSpan::TickType
std::int64_t TickType
Definition timespan.h:29
CppUtilities::TimeSpan::milliseconds
constexpr int milliseconds() const
Returns the milliseconds component of the time interval represented by the current TimeSpan class.
Definition timespan.h:323
CppUtilities::TimeSpan::fromDays
static constexpr TimeSpan fromDays(double days)
Constructs a new instance of the TimeSpan class with the specified number of days.
Definition timespan.h:162
CppUtilities::TimeSpan::fromHours
static constexpr TimeSpan fromHours(double hours)
Constructs a new instance of the TimeSpan class with the specified number of hours.
Definition timespan.h:154
CppUtilities::TimeSpan::fromMinutes
static constexpr TimeSpan fromMinutes(double minutes)
Constructs a new instance of the TimeSpan class with the specified number of minutes.
Definition timespan.h:146
CppUtilities::TimeSpan::infinity
static constexpr TimeSpan infinity()
Constructs a new instance of the TimeSpan class with the maximal number of ticks.
Definition timespan.h:233
CppUtilities::TimeSpan::fromSeconds
static constexpr TimeSpan fromSeconds(double seconds)
Constructs a new instance of the TimeSpan class with the specified number of seconds.
Definition timespan.h:138
CppUtilities::TimeSpan::isInfinity
constexpr bool isInfinity() const
Returns whether the time interval represented by the current instance is the longest representable Ti...
Definition timespan.h:562
CppUtilities::TimeSpan::negativeInfinity
static constexpr TimeSpan negativeInfinity()
Constructs a new instance of the TimeSpan class with the minimal number of ticks.
Definition timespan.h:225
CppUtilities::TimeSpan::microseconds
constexpr int microseconds() const
Returns the microseconds component of the time interval represented by the current TimeSpan class.
Definition timespan.h:315
CppUtilities::TimeSpan::totalDays
constexpr double totalDays() const
Returns the value of the current TimeSpan class expressed in whole and fractional days.
Definition timespan.h:297
CppUtilities::TimeSpan::fromString
static TimeSpan fromString(const std::string &str, char separator=':')
Parses the given std::string as TimeSpan.
Definition timespan.h:217
CppUtilities::TimeSpan::totalMilliseconds
constexpr double totalMilliseconds() const
Returns the value of the current TimeSpan class expressed in whole and fractional milliseconds.
Definition timespan.h:265
CppUtilities::TimeSpan::isNegative
constexpr bool isNegative() const
Returns true if the time interval represented by the current TimeSpan class is negative.
Definition timespan.h:546
CppUtilities::TimeSpan::hours
constexpr int hours() const
Returns the hours component of the time interval represented by the current TimeSpan class.
Definition timespan.h:347
CppUtilities::TimeSpan::totalMinutes
constexpr double totalMinutes() const
Returns the value of the current TimeSpan class expressed in whole and fractional minutes.
Definition timespan.h:281
CppUtilities::TimeSpan::nanoseconds
constexpr int nanoseconds() const
Returns the nanoseconds component of the time interval represented by the current TimeSpan class.
Definition timespan.h:307
CppUtilities::TimeSpan::fromMilliseconds
static constexpr TimeSpan fromMilliseconds(double milliseconds)
Constructs a new instance of the TimeSpan class with the specified number of milliseconds.
Definition timespan.h:130
conversionexception.h
datetime.h
format.h
CppUtilities::Literals
Contains literals to ease asserting with CPPUNIT_ASSERT_EQUAL.
Definition testutils.h:366
CppUtilities
Contains all utilities provided by the c++utilities library.
Definition argumentparser.h:18
CppUtilities::TimeSpanOutputFormat::TotalSeconds
@ TotalSeconds
Definition timespan.h:22
CppUtilities::TimeSpanOutputFormat::WithMeasures
@ WithMeasures
Definition timespan.h:21
CppUtilities::DateTimeParts::Day
@ Day
Definition datetime.h:147
CppUtilities::DateTimeParts::SubSecond
@ SubSecond
Definition datetime.h:151
CppUtilities::DateTimeParts::Year
@ Year
Definition datetime.h:145
CppUtilities::DateTimeParts::Minute
@ Minute
Definition datetime.h:149
CppUtilities::DateTimeParts::Month
@ Month
Definition datetime.h:146
CppUtilities::DateTimeParts::DateTime
@ DateTime
Definition datetime.h:156
CppUtilities::DateTimeParts::DeltaMinute
@ DeltaMinute
Definition datetime.h:153
CppUtilities::DateTimeParts::Hour
@ Hour
Definition datetime.h:148
CppUtilities::DateTimeParts::Second
@ Second
Definition datetime.h:150
CppUtilities::DateTimeParts::DeltaHour
@ DeltaHour
Definition datetime.h:152
CppUtilities::DateTimeOutputFormat::DateTimeAndShortWeekday
@ DateTimeAndShortWeekday
Definition datetime.h:24
CppUtilities::DateTimeOutputFormat::Iso
@ Iso
Definition datetime.h:25
CppUtilities::DateTimeOutputFormat::DateAndTime
@ DateAndTime
Definition datetime.h:20
CppUtilities::DateTimeOutputFormat::IsoOmittingDefaultComponents
@ IsoOmittingDefaultComponents
Definition datetime.h:26
CppUtilities::DayOfWeek::Thursday
@ Thursday
Definition datetime.h:37
CppUtilities::DayOfWeek::Wednesday
@ Wednesday
Definition datetime.h:36
std
STL namespace.
period.h
CppUtilities::DateTimeExpression::fromString
static DateTimeExpression fromString(const char *str)
Parses the given C-style string.
Definition datetime.cpp:499
CppUtilities::DateTimeExpression::fromIsoString
static DateTimeExpression fromIsoString(const char *str)
Parses the specified ISO date time denotation provided as C-style string.
Definition datetime.cpp:399
testutils.h
timespan.h