1 | // |
2 | // LocalDateTimeTest.cpp |
3 | // |
4 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
5 | // and Contributors. |
6 | // |
7 | // SPDX-License-Identifier: BSL-1.0 |
8 | // |
9 | |
10 | |
11 | #include "LocalDateTimeTest.h" |
12 | #include "Poco/CppUnit/TestCaller.h" |
13 | #include "Poco/CppUnit/TestSuite.h" |
14 | #include "Poco/LocalDateTime.h" |
15 | #include "Poco/DateTime.h" |
16 | #include "Poco/Timestamp.h" |
17 | #include "Poco/Timespan.h" |
18 | #include "Poco/Timezone.h" |
19 | #include "Poco/DateTimeFormat.h" |
20 | #include "Poco/DateTimeFormatter.h" |
21 | #include <ctime> |
22 | #include <iostream> |
23 | #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 |
24 | #include "wce_time.h" |
25 | #endif |
26 | |
27 | using Poco::LocalDateTime; |
28 | using Poco::DateTime; |
29 | using Poco::Timestamp; |
30 | using Poco::Timespan; |
31 | using Poco::Timezone; |
32 | #ifndef _WIN32_WCE |
33 | using std::strftime; |
34 | #endif |
35 | |
36 | |
37 | LocalDateTimeTest::LocalDateTimeTest(const std::string& rName): CppUnit::TestCase(rName) |
38 | { |
39 | } |
40 | |
41 | |
42 | LocalDateTimeTest::~LocalDateTimeTest() |
43 | { |
44 | } |
45 | |
46 | |
47 | void LocalDateTimeTest::testGregorian1() |
48 | { |
49 | LocalDateTime dt(1970, 1, 1); |
50 | assertTrue (dt.year() == 1970); |
51 | assertTrue (dt.month() == 1); |
52 | assertTrue (dt.day() == 1); |
53 | assertTrue (dt.hour() == 0); |
54 | assertTrue (dt.minute() == 0); |
55 | assertTrue (dt.second() == 0); |
56 | assertTrue (dt.millisecond() == 0); |
57 | assertTrue (dt.dayOfWeek() == 4); |
58 | // REMOVED: this fails when the current DST offset differs from |
59 | // the one on 1970-1-1 |
60 | //assertTrue (dt.tzd() == Timezone::tzd()); |
61 | assertTrue (dt.julianDay() == 2440587.5); |
62 | |
63 | dt.assign(2001, 9, 9, 1, 46, 40); |
64 | assertTrue (dt.year() == 2001); |
65 | assertTrue (dt.month() == 9); |
66 | assertTrue (dt.day() == 9); |
67 | assertTrue (dt.hour() == 1); |
68 | assertTrue (dt.minute() == 46); |
69 | assertTrue (dt.second() == 40); |
70 | assertTrue (dt.millisecond() == 0); |
71 | assertTrue (dt.dayOfWeek() == 0); |
72 | //assertTrue (dt.tzd() == Timezone::tzd()); |
73 | assertEqualDelta (dt.julianDay(), 2452161.574074, 0.000001); |
74 | } |
75 | |
76 | |
77 | void LocalDateTimeTest::testGregorian2() |
78 | { |
79 | LocalDateTime dt(2*3600, 1970, 1, 1, 0, 0, 0, 0, 0); |
80 | assertTrue (dt.year() == 1970); |
81 | assertTrue (dt.month() == 1); |
82 | assertTrue (dt.day() == 1); |
83 | assertTrue (dt.hour() == 0); |
84 | assertTrue (dt.minute() == 0); |
85 | assertTrue (dt.second() == 0); |
86 | assertTrue (dt.millisecond() == 0); |
87 | assertTrue (dt.dayOfWeek() == 4); |
88 | assertTrue (dt.tzd() == 2*3600); |
89 | |
90 | dt.assign(-7*3600, 2001, 9, 9, 1, 46, 40, 0, 0); |
91 | assertTrue (dt.year() == 2001); |
92 | assertTrue (dt.month() == 9); |
93 | assertTrue (dt.day() == 9); |
94 | assertTrue (dt.hour() == 1); |
95 | assertTrue (dt.minute() == 46); |
96 | assertTrue (dt.second() == 40); |
97 | assertTrue (dt.millisecond() == 0); |
98 | assertTrue (dt.dayOfWeek() == 0); |
99 | assertTrue (dt.tzd() == -7*3600); |
100 | } |
101 | |
102 | |
103 | void LocalDateTimeTest::testConversions() |
104 | { |
105 | LocalDateTime dt1(2*3600, 2005, 1, 28, 14, 24, 44, 234, 0); |
106 | LocalDateTime dt2(dt1.tzd(), dt1.utc()); |
107 | LocalDateTime dt3; |
108 | dt3 = dt1; |
109 | LocalDateTime dt4(dt2); |
110 | LocalDateTime dt5(-4*3600, dt1.utc()); |
111 | |
112 | assertTrue (dt2.year() == 2005); |
113 | assertTrue (dt2.month() == 1); |
114 | assertTrue (dt2.day() == 28); |
115 | assertTrue (dt2.hour() == 14); |
116 | assertTrue (dt2.minute() == 24); |
117 | assertTrue (dt2.second() == 44); |
118 | assertTrue (dt2.millisecond() == 234); |
119 | assertTrue (dt2.dayOfWeek() == 5); |
120 | assertTrue (dt2.tzd() == 2*3600); |
121 | |
122 | assertTrue (dt5.year() == 2005); |
123 | assertTrue (dt5.month() == 1); |
124 | assertTrue (dt5.day() == 28); |
125 | assertTrue (dt5.hour() == 8); |
126 | assertTrue (dt5.minute() == 24); |
127 | assertTrue (dt5.second() == 44); |
128 | assertTrue (dt5.millisecond() == 234); |
129 | assertTrue (dt5.dayOfWeek() == 5); |
130 | assertTrue (dt5.tzd() == -4*3600); |
131 | |
132 | DateTime dt6(2005, 1, 28, 14, 24, 44, 234, 0); |
133 | LocalDateTime dt7(3600, dt6); |
134 | LocalDateTime dt8(3600, dt6, false); |
135 | LocalDateTime dt9(3600, dt6, true); |
136 | |
137 | assertTrue (dt7.hour() == 15); |
138 | assertTrue (dt8.hour() == 14); |
139 | assertTrue (dt9.hour() == 15); |
140 | } |
141 | |
142 | |
143 | void LocalDateTimeTest::testCalcs() |
144 | { |
145 | LocalDateTime dt1(2005, 1, 1); |
146 | assertTrue (dt1.dayOfYear() == 1); |
147 | assertTrue (dt1.week(DateTime::MONDAY) == 0); |
148 | dt1.assign(2005, 1, 3); |
149 | assertTrue (dt1.dayOfYear() == 3); |
150 | assertTrue (dt1.week(DateTime::MONDAY) == 1); |
151 | dt1.assign(2005, 1, 9); |
152 | assertTrue (dt1.dayOfYear() == 9); |
153 | assertTrue (dt1.week(DateTime::MONDAY) == 1); |
154 | dt1.assign(2005, 1, 10); |
155 | assertTrue (dt1.dayOfYear() == 10); |
156 | assertTrue (dt1.week(DateTime::MONDAY) == 2); |
157 | dt1.assign(2005, 2, 1); |
158 | assertTrue (dt1.dayOfYear() == 32); |
159 | assertTrue (dt1.week(DateTime::MONDAY) == 5); |
160 | dt1.assign(2005, 12, 31); |
161 | assertTrue (dt1.week(DateTime::MONDAY) == 52); |
162 | dt1.assign(2007, 1, 1); |
163 | assertTrue (dt1.week(DateTime::MONDAY) == 1); |
164 | dt1.assign(2007, 12, 31); |
165 | assertTrue (dt1.week(DateTime::MONDAY) == 53); |
166 | |
167 | // Jan 1 is Mon |
168 | dt1.assign(2001, 1, 1); |
169 | assertTrue (dt1.week() == 1); |
170 | dt1.assign(2001, 1, 7); |
171 | assertTrue (dt1.week() == 1); |
172 | dt1.assign(2001, 1, 8); |
173 | assertTrue (dt1.week() == 2); |
174 | dt1.assign(2001, 1, 21); |
175 | assertTrue (dt1.week() == 3); |
176 | dt1.assign(2001, 1, 22); |
177 | assertTrue (dt1.week() == 4); |
178 | |
179 | // Jan 1 is Tue |
180 | dt1.assign(2002, 1, 1); |
181 | assertTrue (dt1.week() == 1); |
182 | dt1.assign(2002, 1, 6); |
183 | assertTrue (dt1.week() == 1); |
184 | dt1.assign(2002, 1, 7); |
185 | assertTrue (dt1.week() == 2); |
186 | dt1.assign(2002, 1, 20); |
187 | assertTrue (dt1.week() == 3); |
188 | dt1.assign(2002, 1, 21); |
189 | assertTrue (dt1.week() == 4); |
190 | |
191 | // Jan 1 is Wed |
192 | dt1.assign(2003, 1, 1); |
193 | assertTrue (dt1.week() == 1); |
194 | dt1.assign(2003, 1, 5); |
195 | assertTrue (dt1.week() == 1); |
196 | dt1.assign(2003, 1, 6); |
197 | assertTrue (dt1.week() == 2); |
198 | dt1.assign(2003, 1, 19); |
199 | assertTrue (dt1.week() == 3); |
200 | dt1.assign(2003, 1, 20); |
201 | assertTrue (dt1.week() == 4); |
202 | |
203 | // Jan 1 is Thu |
204 | dt1.assign(2004, 1, 1); |
205 | assertTrue (dt1.week() == 1); |
206 | dt1.assign(2004, 1, 4); |
207 | assertTrue (dt1.week() == 1); |
208 | dt1.assign(2004, 1, 5); |
209 | assertTrue (dt1.week() == 2); |
210 | dt1.assign(2004, 1, 18); |
211 | assertTrue (dt1.week() == 3); |
212 | dt1.assign(2004, 1, 19); |
213 | assertTrue (dt1.week() == 4); |
214 | |
215 | // Jan 1 is Fri |
216 | dt1.assign(1999, 1, 1); |
217 | assertTrue (dt1.week() == 0); |
218 | dt1.assign(1999, 1, 3); |
219 | assertTrue (dt1.week() == 0); |
220 | dt1.assign(1999, 1, 4); |
221 | assertTrue (dt1.week() == 1); |
222 | dt1.assign(1999, 1, 17); |
223 | assertTrue (dt1.week() == 2); |
224 | dt1.assign(1999, 1, 18); |
225 | assertTrue (dt1.week() == 3); |
226 | |
227 | // Jan 1 is Sat |
228 | dt1.assign(2000, 1, 1); |
229 | assertTrue (dt1.week() == 0); |
230 | dt1.assign(2000, 1, 2); |
231 | assertTrue (dt1.week() == 0); |
232 | dt1.assign(2000, 1, 3); |
233 | assertTrue (dt1.week() == 1); |
234 | dt1.assign(2000, 1, 16); |
235 | assertTrue (dt1.week() == 2); |
236 | dt1.assign(2000, 1, 17); |
237 | assertTrue (dt1.week() == 3); |
238 | |
239 | // Jan 1 is Sun |
240 | dt1.assign(1995, 1, 1); |
241 | assertTrue (dt1.week() == 0); |
242 | dt1.assign(1995, 1, 2); |
243 | assertTrue (dt1.week() == 1); |
244 | dt1.assign(1995, 1, 3); |
245 | assertTrue (dt1.week() == 1); |
246 | dt1.assign(1995, 1, 15); |
247 | assertTrue (dt1.week() == 2); |
248 | dt1.assign(1995, 1, 16); |
249 | assertTrue (dt1.week() == 3); |
250 | } |
251 | |
252 | |
253 | void LocalDateTimeTest::testAMPM() |
254 | { |
255 | LocalDateTime dt1(2005, 1, 1, 0, 15, 30); |
256 | assertTrue (dt1.isAM()); |
257 | assertTrue (!dt1.isPM()); |
258 | assertTrue (dt1.hourAMPM() == 12); |
259 | |
260 | dt1.assign(2005, 1, 1, 12, 15, 30); |
261 | assertTrue (!dt1.isAM()); |
262 | assertTrue (dt1.isPM()); |
263 | assertTrue (dt1.hourAMPM() == 12); |
264 | |
265 | dt1.assign(2005, 1, 1, 13, 15, 30); |
266 | assertTrue (!dt1.isAM()); |
267 | assertTrue (dt1.isPM()); |
268 | assertTrue (dt1.hourAMPM() == 1); |
269 | } |
270 | |
271 | |
272 | void LocalDateTimeTest::testRelational1() |
273 | { |
274 | LocalDateTime dt1(2005, 1, 1, 0, 15, 30); |
275 | LocalDateTime dt2(2005, 1, 2, 0, 15, 30); |
276 | LocalDateTime dt3(dt1); |
277 | |
278 | assertTrue (dt1 < dt2); |
279 | assertTrue (dt1 <= dt2); |
280 | assertTrue (dt2 > dt1); |
281 | assertTrue (dt2 >= dt1); |
282 | assertTrue (dt1 != dt2); |
283 | assertTrue (!(dt1 == dt2)); |
284 | |
285 | assertTrue (dt1 == dt3); |
286 | assertTrue (!(dt1 != dt3)); |
287 | assertTrue (dt1 >= dt3); |
288 | assertTrue (dt1 <= dt3); |
289 | assertTrue (!(dt1 > dt3)); |
290 | assertTrue (!(dt1 < dt3)); |
291 | } |
292 | |
293 | |
294 | void LocalDateTimeTest::testRelational2() |
295 | { |
296 | LocalDateTime dt1(2*3600, 2005, 1, 1, 15, 30, 0, 0, 0); |
297 | LocalDateTime dt2(2*3600, 2005, 1, 1, 17, 30, 0, 0, 0); |
298 | LocalDateTime dt3(5*3600, 2005, 1, 1, 18, 30, 0, 0, 0); |
299 | |
300 | assertTrue (dt1 < dt2); |
301 | assertTrue (dt1 <= dt2); |
302 | assertTrue (dt2 > dt1); |
303 | assertTrue (dt2 >= dt1); |
304 | assertTrue (dt1 != dt2); |
305 | assertTrue (!(dt1 == dt2)); |
306 | |
307 | assertTrue (dt1 == dt3); |
308 | assertTrue (!(dt1 != dt3)); |
309 | assertTrue (dt1 >= dt3); |
310 | assertTrue (dt1 <= dt3); |
311 | assertTrue (!(dt1 > dt3)); |
312 | assertTrue (!(dt1 < dt3)); |
313 | } |
314 | |
315 | |
316 | void LocalDateTimeTest::testArithmetics1() |
317 | { |
318 | LocalDateTime dt1(2005, 1, 1, 0, 15, 30); |
319 | LocalDateTime dt2(2005, 1, 2, 0, 15, 30); |
320 | |
321 | Timespan s = dt2 - dt1; |
322 | assertTrue (s.days() == 1); |
323 | |
324 | LocalDateTime dt3 = dt1 + s; |
325 | assertTrue (dt3 == dt2); |
326 | |
327 | dt3 -= s; |
328 | assertTrue (dt3 == dt1); |
329 | dt1 += s; |
330 | assertTrue (dt1 == dt2); |
331 | } |
332 | |
333 | |
334 | void LocalDateTimeTest::testArithmetics2() |
335 | { |
336 | LocalDateTime dt1(2*3600, 2005, 1, 1, 15, 30, 0, 0, 0); |
337 | LocalDateTime dt2(5*3600, 2005, 1, 2, 18, 30, 0, 0, 0); |
338 | |
339 | Timespan s = dt2 - dt1; |
340 | assertTrue (s.days() == 1); |
341 | |
342 | LocalDateTime dt3 = dt1 + s; |
343 | assertTrue (dt3 == dt2); |
344 | |
345 | dt3 -= s; |
346 | assertTrue (dt3 == dt1); |
347 | dt1 += s; |
348 | assertTrue (dt1 == dt2); |
349 | } |
350 | |
351 | |
352 | void LocalDateTimeTest::testSwap() |
353 | { |
354 | LocalDateTime dt1(2005, 1, 1, 0, 15, 30); |
355 | LocalDateTime dt2(2005, 1, 2, 0, 15, 30); |
356 | |
357 | assertTrue (dt1 < dt2); |
358 | dt1.swap(dt2); |
359 | assertTrue (dt2 < dt1); |
360 | } |
361 | |
362 | |
363 | void LocalDateTimeTest::testTimezone() |
364 | { |
365 | #if !defined(_WIN32_WCE) |
366 | std::time_t tINCREMENT = (30 * 24 * 60 * 60); // 30 days |
367 | Timespan tsINCREMENT(30*Timespan::DAYS); |
368 | LocalDateTime now; |
369 | std::time_t t = std::time(NULL); |
370 | std::tm then; |
371 | bool foundDST = false; |
372 | |
373 | then = *std::localtime(&t); |
374 | if (then.tm_isdst >= 0) |
375 | { |
376 | std::string tzNow, tzThen; |
377 | char tzBuf[48] = {0}; |
378 | if (0 == std::strftime(&tzBuf[0], sizeof(tzBuf), "%Z" , &then)) |
379 | fail ("Insufficient character array length." ); |
380 | |
381 | tzNow = tzThen = tzBuf; |
382 | int iterations = 0; |
383 | while (iterations < 14) |
384 | { |
385 | // Add one month until the timezone changes or we roll |
386 | // over 13 months. |
387 | t += tINCREMENT; |
388 | then = *std::localtime(&t); |
389 | std::strftime(&tzBuf[0], sizeof(tzBuf), "%Z" , &then); |
390 | tzThen = tzBuf; |
391 | foundDST = (tzNow == tzThen); |
392 | if (foundDST) break; |
393 | ++iterations; |
394 | } |
395 | if (foundDST) |
396 | { |
397 | // We found a timezone change that was induced by changing |
398 | // the month, so we crossed a DST boundary. Now we can |
399 | // actually do the test... |
400 | // |
401 | // Start with the current time and add 30 days for 13 |
402 | // iterations. Do this with both a LocalDateTime object and |
403 | // a ANSI C time_t. Then create a LocalDateTime based on the |
404 | // time_t and verify that the time_t calculated value is equal |
405 | // to the LocalDateTime value. The comparison operator |
406 | // verifies the _dateTime and _tzd members. |
407 | LocalDateTime dt2; |
408 | t = std::time(NULL); |
409 | for (iterations = 0; iterations < 14; ++iterations) |
410 | { |
411 | t += tINCREMENT; |
412 | dt2 += tsINCREMENT; |
413 | then = *std::localtime(&t); |
414 | |
415 | // This is the tricky part. We have to use the constructor |
416 | // from a UTC DateTime object that is constructed from the |
417 | // time_t. The LocalDateTime constructor with integer |
418 | // arguments, LocalDateTime(yr, mon, day, ...), assumes that |
419 | // the time is already adjusted with respect to the time |
420 | // zone. The DateTime conversion constructor, however, does |
421 | // not. So we want to construct from the UTC time. |
422 | // |
423 | // The second tricky part is that we want to use the |
424 | // sub-second information from the LocalDateTime object |
425 | // since ANSI C time routines are not sub-second accurate. |
426 | then = *std::gmtime(&t); |
427 | LocalDateTime calcd(DateTime((then.tm_year + 1900), |
428 | (then.tm_mon + 1), |
429 | then.tm_mday, |
430 | then.tm_hour, |
431 | then.tm_min, |
432 | then.tm_sec, |
433 | dt2.millisecond(), |
434 | dt2.microsecond())); |
435 | assertTrue (dt2 == calcd); |
436 | } |
437 | } |
438 | } |
439 | |
440 | if (!foundDST) |
441 | { |
442 | std::cerr |
443 | << __FILE__ << ":" << __LINE__ |
444 | << " - failed to locate DST boundary, timezone test skipped." |
445 | << std::endl; |
446 | } |
447 | #endif |
448 | } |
449 | |
450 | |
451 | void LocalDateTimeTest::setUp() |
452 | { |
453 | } |
454 | |
455 | |
456 | void LocalDateTimeTest::tearDown() |
457 | { |
458 | } |
459 | |
460 | |
461 | CppUnit::Test* LocalDateTimeTest::suite() |
462 | { |
463 | CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("LocalDateTimeTest" ); |
464 | |
465 | CppUnit_addTest(pSuite, LocalDateTimeTest, testGregorian1); |
466 | CppUnit_addTest(pSuite, LocalDateTimeTest, testGregorian2); |
467 | CppUnit_addTest(pSuite, LocalDateTimeTest, testConversions); |
468 | CppUnit_addTest(pSuite, LocalDateTimeTest, testCalcs); |
469 | CppUnit_addTest(pSuite, LocalDateTimeTest, testAMPM); |
470 | CppUnit_addTest(pSuite, LocalDateTimeTest, testRelational1); |
471 | CppUnit_addTest(pSuite, LocalDateTimeTest, testRelational2); |
472 | CppUnit_addTest(pSuite, LocalDateTimeTest, testArithmetics1); |
473 | CppUnit_addTest(pSuite, LocalDateTimeTest, testArithmetics2); |
474 | CppUnit_addTest(pSuite, LocalDateTimeTest, testSwap); |
475 | CppUnit_addTest(pSuite, LocalDateTimeTest, testTimezone); |
476 | |
477 | return pSuite; |
478 | } |
479 | |