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
27using Poco::LocalDateTime;
28using Poco::DateTime;
29using Poco::Timestamp;
30using Poco::Timespan;
31using Poco::Timezone;
32#ifndef _WIN32_WCE
33using std::strftime;
34#endif
35
36
37LocalDateTimeTest::LocalDateTimeTest(const std::string& rName): CppUnit::TestCase(rName)
38{
39}
40
41
42LocalDateTimeTest::~LocalDateTimeTest()
43{
44}
45
46
47void 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
77void 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
103void 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
143void 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
253void 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
272void 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
294void 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
316void 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
334void 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
352void 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
363void 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
451void LocalDateTimeTest::setUp()
452{
453}
454
455
456void LocalDateTimeTest::tearDown()
457{
458}
459
460
461CppUnit::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