1 // Copyright (c) 1999-2018 David Muse
2 // See the file COPYING for more information
3
4 #include <rudiments/datetime.h>
5 #include <rudiments/environment.h>
6 #include <rudiments/stdio.h>
7 #include <rudiments/private/config.h>
8 #include "test.cpp"
9
10 const char *nondstdatestring="02/08/2016 21:54:30 EST";
11 const char *nondstdatestringwithzerousec="02/08/2016 21:54:30:000 EST";
12 time_t nondstsecsinceepoch=1454986470;
13
14 const char *datestring="04/08/2016 21:54:30 EDT";
15 const char *estdatestring="04/08/2016 21:54:30 EDT";
16 const char *cstdatestring="04/08/2016 20:54:30 CDT";
17 const char *mstdatestring="04/08/2016 19:54:30 MDT";
18 const char *pstdatestring="04/08/2016 18:54:30 PDT";
19 const char *datestringwithusec="04/08/2016 21:54:30:500 EDT";
20 const char *datestringwithzerousec="04/08/2016 21:54:30:000 EDT";
21 time_t secsinceepoch=1460166870;
22
main(int argc,const char ** argv)23 int main(int argc, const char **argv) {
24
25 // set timezone so epoch to string will work correctly
26 environment::setValue("TZ","EST5EDT");
27
28 header("datetime");
29
30 datetime dt;
31
32 // init from string
33 stdoutput.printf("non-dst date from string:\n");
34 dt.initialize(nondstdatestring);
35 test("hour",dt.getHour()==21);
36 test("minutes",dt.getMinutes()==54);
37 test("seconds",dt.getSeconds()==30);
38 test("useconds",dt.getMicroseconds()==0);
39 test("month",dt.getMonth()==2);
40 test("month name",
41 !charstring::compare(dt.getMonthName(),"February"));
42 test("month abbr",
43 !charstring::compare(dt.getMonthAbbreviation(),"Feb"));
44 test("day of month",dt.getDayOfMonth()==8);
45 test("day of week",dt.getDayOfWeek()==2);
46 test("day of year",dt.getDayOfYear()==39);
47 test("year",dt.getYear()==2016);
48 test("daylight savings time",!dt.isDaylightSavingsTime());
49
50 // some platforms (haiku) convert EST to EST5EDT,
51 // so we have to allow that
52 test("time zone",
53 !charstring::compare(dt.getTimeZoneString(),"EST") ||
54 !charstring::compare(dt.getTimeZoneString(),"EST5EDT"));
55
56 test("offset from GMT",dt.getTimeZoneOffset()==-18000);
57 test("seconds since 1970",dt.getEpoch()==nondstsecsinceepoch);
58
59 // some platforms (haiku) convert EST to EST5EDT, so we'll truncate
60 // the 5EDT part during these comparisons
61 test("date string",
62 !charstring::compare(dt.getString(),nondstdatestring,
63 charstring::length(nondstdatestring)));
64 test("date string (with usec)",
65 !charstring::compare(dt.getString(true),
66 nondstdatestringwithzerousec,
67 charstring::length(nondstdatestringwithzerousec)));
68
69 stdoutput.printf("\n");
70
71
72 // init from string
73 stdoutput.printf("date from string:\n");
74 dt.initialize(datestringwithusec);
75 test("hour",dt.getHour()==21);
76 test("minutes",dt.getMinutes()==54);
77 test("seconds",dt.getSeconds()==30);
78 test("useconds",dt.getMicroseconds()==500);
79 test("month",dt.getMonth()==4);
80 test("month name",
81 !charstring::compare(dt.getMonthName(),"April"));
82 test("month abbr",
83 !charstring::compare(dt.getMonthAbbreviation(),"Apr"));
84 test("day of month",dt.getDayOfMonth()==8);
85 test("day of week",dt.getDayOfWeek()==6);
86 test("day of year",dt.getDayOfYear()==99);
87 test("year",dt.getYear()==2016);
88 test("daylight savings time",dt.isDaylightSavingsTime());
89 test("time zone",
90 !charstring::compare(dt.getTimeZoneString(),"EDT"));
91 test("offset from GMT",dt.getTimeZoneOffset()==-14400);
92 test("seconds since 1970",dt.getEpoch()==secsinceepoch);
93 test("date string",
94 !charstring::compare(dt.getString(),datestring));
95 test("date string (with usec)",
96 !charstring::compare(dt.getString(true),datestringwithusec));
97 stdoutput.printf("\n");
98
99
100 // init from epoch
101 stdoutput.printf("date from epoch:\n");
102 dt.initialize(secsinceepoch);
103 test("hour",dt.getHour()==21);
104 test("minutes",dt.getMinutes()==54);
105 test("seconds",dt.getSeconds()==30);
106 test("useconds",!dt.getMicroseconds());
107 test("month",dt.getMonth()==4);
108 test("month name",
109 !charstring::compare(dt.getMonthName(),"April"));
110 test("month abbr",
111 !charstring::compare(dt.getMonthAbbreviation(),"Apr"));
112 test("day of month",dt.getDayOfMonth()==8);
113 test("day of week",dt.getDayOfWeek()==6);
114 test("day of year",dt.getDayOfYear()==99);
115 test("year",dt.getYear()==2016);
116 test("daylight savings time",dt.isDaylightSavingsTime());
117 stdoutput.printf("%s\n",dt.getTimeZoneString());
118 test("time zone",
119 !charstring::compare(dt.getTimeZoneString(),"EDT"));
120 test("offset from GMT",dt.getTimeZoneOffset()==-14400);
121 test("seconds since 1970",dt.getEpoch()==secsinceepoch);
122 test("date string",
123 !charstring::compare(dt.getString(),datestring));
124 test("date string (with usec)",
125 !charstring::compare(dt.getString(true),
126 datestringwithzerousec));
127 stdoutput.printf("\n");
128
129
130 // init from epoch+usec
131 stdoutput.printf("date from epoch+usec:\n");
132 dt.initialize(secsinceepoch,500);
133 test("hour",dt.getHour()==21);
134 test("minutes",dt.getMinutes()==54);
135 test("seconds",dt.getSeconds()==30);
136 test("useconds",dt.getMicroseconds()==500);
137 test("month",dt.getMonth()==4);
138 test("month name",
139 !charstring::compare(dt.getMonthName(),"April"));
140 test("month abbr",
141 !charstring::compare(dt.getMonthAbbreviation(),"Apr"));
142 test("day of month",dt.getDayOfMonth()==8);
143 test("day of week",dt.getDayOfWeek()==6);
144 test("day of year",dt.getDayOfYear()==99);
145 test("year",dt.getYear()==2016);
146 test("daylight savings time",dt.isDaylightSavingsTime());
147 test("time zone",
148 !charstring::compare(dt.getTimeZoneString(),"EDT"));
149 test("offset from GMT",dt.getTimeZoneOffset()==-14400);
150 test("seconds since 1970",dt.getEpoch()==secsinceepoch);
151 test("date string",
152 !charstring::compare(dt.getString(),datestring));
153 test("date string (with usec)",
154 !charstring::compare(dt.getString(true),datestringwithusec));
155 stdoutput.printf("\n");
156
157
158 // add/subtract time
159 stdoutput.printf("add/subtract time:");
160 dt.addMicroseconds(1);
161 test("addSeconds(1) hour",dt.getHour()==21);
162 test("addSeconds(1) minutes",dt.getMinutes()==54);
163 test("addSeconds(1) seconds",dt.getSeconds()==30);
164 test("addSeconds(1) useconds",dt.getMicroseconds()==501);
165 test("addSeconds(1) month",dt.getMonth()==4);
166 test("addSeconds(1) day of month",dt.getDayOfMonth()==8);
167 test("addSeconds(1) year",dt.getYear()==2016);
168 dt.addMicroseconds(-1);
169 test("addSeconds(-1) hour",dt.getHour()==21);
170 test("addSeconds(-1) minutes",dt.getMinutes()==54);
171 test("addSeconds(-1) seconds",dt.getSeconds()==30);
172 test("addSeconds(-1) useconds",dt.getMicroseconds()==500);
173 test("addSeconds(-1) month",dt.getMonth()==4);
174 test("addSeconds(-1) day of month",dt.getDayOfMonth()==8);
175 test("addSeconds(-1) year",dt.getYear()==2016);
176 dt.addSeconds(1);
177 test("addSeconds(1) hour",dt.getHour()==21);
178 test("addSeconds(1) minutes",dt.getMinutes()==54);
179 test("addSeconds(1) seconds",dt.getSeconds()==31);
180 test("addSeconds(1) useconds",dt.getMicroseconds()==500);
181 test("addSeconds(1) month",dt.getMonth()==4);
182 test("addSeconds(1) day of month",dt.getDayOfMonth()==8);
183 test("addSeconds(1) year",dt.getYear()==2016);
184 dt.addSeconds(-1);
185 test("addSeconds(-1) hour",dt.getHour()==21);
186 test("addSeconds(-1) minutes",dt.getMinutes()==54);
187 test("addSeconds(-1) seconds",dt.getSeconds()==30);
188 test("addSeconds(-1) useconds",dt.getMicroseconds()==500);
189 test("addSeconds(-1) month",dt.getMonth()==4);
190 test("addSeconds(-1) day of month",dt.getDayOfMonth()==8);
191 test("addSeconds(-1) year",dt.getYear()==2016);
192 dt.addMinutes(1);
193 test("addMinutes(1) hour",dt.getHour()==21);
194 test("addMinutes(1) minutes",dt.getMinutes()==55);
195 test("addMinutes(1) seconds",dt.getSeconds()==30);
196 test("addMinutes(1) useconds",dt.getMicroseconds()==500);
197 test("addMinutes(1) month",dt.getMonth()==4);
198 test("addMinutes(1) day of month",dt.getDayOfMonth()==8);
199 test("addMinutes(1) year",dt.getYear()==2016);
200 dt.addMinutes(-1);
201 test("addMinutes(-1) hour",dt.getHour()==21);
202 test("addMinutes(-1) minutes",dt.getMinutes()==54);
203 test("addMinutes(-1) seconds",dt.getSeconds()==30);
204 test("addMinutes(-1) useconds",dt.getMicroseconds()==500);
205 test("addMinutes(-1) month",dt.getMonth()==4);
206 test("addMinutes(-1) day of month",dt.getDayOfMonth()==8);
207 test("addMinutes(-1) year",dt.getYear()==2016);
208 dt.addHours(1);
209 test("addHours(1) hour",dt.getHour()==22);
210 test("addHours(1) minutes",dt.getMinutes()==54);
211 test("addHours(1) seconds",dt.getSeconds()==30);
212 test("addHours(1) useconds",dt.getMicroseconds()==500);
213 test("addHours(1) month",dt.getMonth()==4);
214 test("addHours(1) day of month",dt.getDayOfMonth()==8);
215 test("addHours(1) year",dt.getYear()==2016);
216 dt.addHours(-1);
217 test("addHours(-1) hour",dt.getHour()==21);
218 test("addHours(-1) minutes",dt.getMinutes()==54);
219 test("addHours(-1) seconds",dt.getSeconds()==30);
220 test("addHours(-1) useconds",dt.getMicroseconds()==500);
221 test("addHours(-1) month",dt.getMonth()==4);
222 test("addHours(-1) day of month",dt.getDayOfMonth()==8);
223 test("addHours(-1) year",dt.getYear()==2016);
224 dt.addDays(1);
225 test("addDays(1) hour",dt.getHour()==21);
226 test("addDays(1) minutes",dt.getMinutes()==54);
227 test("addDays(1) seconds",dt.getSeconds()==30);
228 test("addDays(1) useconds",dt.getMicroseconds()==500);
229 test("addDays(1) month",dt.getMonth()==4);
230 test("addDays(1) day of month",dt.getDayOfMonth()==9);
231 test("addDays(1) year",dt.getYear()==2016);
232 dt.addDays(-1);
233 test("addDays(-1) hour",dt.getHour()==21);
234 test("addDays(-1) minutes",dt.getMinutes()==54);
235 test("addDays(-1) seconds",dt.getSeconds()==30);
236 test("addDays(-1) useconds",dt.getMicroseconds()==500);
237 test("addDays(-1) month",dt.getMonth()==4);
238 test("addDays(-1) day of month",dt.getDayOfMonth()==8);
239 test("addDays(-1) year",dt.getYear()==2016);
240 dt.addMonths(1);
241 test("addMonths(1) hour",dt.getHour()==21);
242 test("addMonths(1) minutes",dt.getMinutes()==54);
243 test("addMonths(1) seconds",dt.getSeconds()==30);
244 test("addMonths(1) useconds",dt.getMicroseconds()==500);
245 test("addMonths(1) month",dt.getMonth()==5);
246 //test("addMonths(1) day of month",dt.getDayOfMonth()==9);
247 test("addMonths(1) year",dt.getYear()==2016);
248 dt.addMonths(-1);
249 test("addMonths(-1) hour",dt.getHour()==21);
250 test("addMonths(-1) minutes",dt.getMinutes()==54);
251 test("addMonths(-1) seconds",dt.getSeconds()==30);
252 test("addMonths(-1) useconds",dt.getMicroseconds()==500);
253 test("addMonths(-1) month",dt.getMonth()==4);
254 test("addMonths(-1) day of month",dt.getDayOfMonth()==8);
255 test("addMonths(-1) year",dt.getYear()==2016);
256 dt.addYears(1);
257 test("addYears(1) hour",dt.getHour()==21);
258 test("addYears(1) minutes",dt.getMinutes()==54);
259 test("addYears(1) seconds",dt.getSeconds()==30);
260 test("addYears(1) useconds",dt.getMicroseconds()==500);
261 test("addYears(1) month",dt.getMonth()==4);
262 //test("addYears(1) day of month",dt.getDayOfMonth()==9);
263 test("addYears(1) year",dt.getYear()==2017);
264 dt.addYears(-1);
265 test("addYears(-1) hour",dt.getHour()==21);
266 test("addYears(-1) minutes",dt.getMinutes()==54);
267 test("addYears(-1) seconds",dt.getSeconds()==30);
268 test("addYears(-1) useconds",dt.getMicroseconds()==500);
269 test("addYears(-1) month",dt.getMonth()==4);
270 test("addYears(-1) day of month",dt.getDayOfMonth()==8);
271 test("addYears(-1) year",dt.getYear()==2016);
272 stdoutput.printf("\n");
273
274
275 // conversions
276 stdoutput.printf("conversions:\n");
277 char *string=datetime::getString(secsinceepoch);
278 test("string from epoch",!charstring::compare(string,datestring));
279 delete[] string;
280 time_t epoch=datetime::getEpoch(datestring);
281 test("epoch from string",epoch==secsinceepoch);
282 string=datetime::getString(secsinceepoch,500);
283 test("string+usec from epoch",
284 !charstring::compare(string,datestringwithusec));
285 delete[] string;
286 epoch=datetime::getEpoch(datestringwithusec);
287 test("epoch from string+usec",epoch==secsinceepoch);
288 stdoutput.printf("\n");
289
290
291 // get time
292 stdoutput.printf("dates from various sources:\n");
293 test("system clock",dt.getSystemDateAndTime());
294 // getHardwareDateAndTime/getAdjustedHardwareDateAndTime
295 // aren't reliable on most systems
296 stdoutput.printf("\n");
297
298
299 // time zones
300 stdoutput.printf("time zones:\n");
301 const char * const *tz=datetime::getTimeZoneAbbreviations();
302 uint32_t i=0;
303 test("",!charstring::compare(tz[i++],"ACST"));
304 test("",!charstring::compare(tz[i++],"ACDT"));
305 test("",!charstring::compare(tz[i++],"ACST-10:30ACDT"));
306 test("",!charstring::compare(tz[i++],"AST"));
307 test("",!charstring::compare(tz[i++],"ADT"));
308 test("",!charstring::compare(tz[i++],"AST4ADT"));
309 test("",!charstring::compare(tz[i++],"AEST"));
310 test("",!charstring::compare(tz[i++],"AEDT"));
311 test("",!charstring::compare(tz[i++],"AEST10AEDT"));
312 test("",!charstring::compare(tz[i++],"AKST"));
313 test("",!charstring::compare(tz[i++],"AKDT"));
314 test("",!charstring::compare(tz[i++],"AKST-9AKDT"));
315 test("",!charstring::compare(tz[i++],"CST"));
316 test("",!charstring::compare(tz[i++],"CDT"));
317 test("",!charstring::compare(tz[i++],"CST6CDT"));
318 test("",!charstring::compare(tz[i++],"CET"));
319 test("",!charstring::compare(tz[i++],"CEST"));
320 test("",!charstring::compare(tz[i++],"CET-1CST"));
321 test("",!charstring::compare(tz[i++],"EST"));
322 test("",!charstring::compare(tz[i++],"EDT"));
323 test("",!charstring::compare(tz[i++],"EST5EDT"));
324 test("",!charstring::compare(tz[i++],"EET"));
325 test("",!charstring::compare(tz[i++],"EEST"));
326 test("",!charstring::compare(tz[i++],"EET-2EEST"));
327 test("",!charstring::compare(tz[i++],"GMT"));
328 test("",!charstring::compare(tz[i++],"BST"));
329 test("",!charstring::compare(tz[i++],"GMT0BST"));
330 test("",!charstring::compare(tz[i++],"HNA"));
331 test("",!charstring::compare(tz[i++],"HAA"));
332 test("",!charstring::compare(tz[i++],"HNA4HAA"));
333 test("",!charstring::compare(tz[i++],"HNC"));
334 test("",!charstring::compare(tz[i++],"HAC"));
335 test("",!charstring::compare(tz[i++],"HNC6HAC"));
336 test("",!charstring::compare(tz[i++],"HAST"));
337 test("",!charstring::compare(tz[i++],"HADT"));
338 test("",!charstring::compare(tz[i++],"HAST10HADT"));
339 test("",!charstring::compare(tz[i++],"HNE"));
340 test("",!charstring::compare(tz[i++],"HAE"));
341 test("",!charstring::compare(tz[i++],"HNE5HAE"));
342 test("",!charstring::compare(tz[i++],"HNP"));
343 test("",!charstring::compare(tz[i++],"HAP"));
344 test("",!charstring::compare(tz[i++],"HNP8HAP"));
345 test("",!charstring::compare(tz[i++],"HNR"));
346 test("",!charstring::compare(tz[i++],"HAR"));
347 test("",!charstring::compare(tz[i++],"HNR7HAR"));
348 test("",!charstring::compare(tz[i++],"HNT"));
349 test("",!charstring::compare(tz[i++],"HAT"));
350 test("",!charstring::compare(tz[i++],"HNT3:30HAT"));
351 test("",!charstring::compare(tz[i++],"HNY"));
352 test("",!charstring::compare(tz[i++],"HAY"));
353 test("",!charstring::compare(tz[i++],"HNY9HAY"));
354 test("",!charstring::compare(tz[i++],"MST"));
355 test("",!charstring::compare(tz[i++],"MDT"));
356 test("",!charstring::compare(tz[i++],"MST7MDT"));
357 test("",!charstring::compare(tz[i++],"MEZ"));
358 test("",!charstring::compare(tz[i++],"MESZ"));
359 test("",!charstring::compare(tz[i++],"MEZ-1MESZ"));
360 test("",!charstring::compare(tz[i++],"NST"));
361 test("",!charstring::compare(tz[i++],"NDT"));
362 test("",!charstring::compare(tz[i++],"NST3:30NDT"));
363 test("",!charstring::compare(tz[i++],"PST"));
364 test("",!charstring::compare(tz[i++],"PDT"));
365 test("",!charstring::compare(tz[i++],"PST8PDT"));
366 test("",!charstring::compare(tz[i++],"WET"));
367 test("",!charstring::compare(tz[i++],"WEST"));
368 test("",!charstring::compare(tz[i++],"WET-1WEST"));
369 stdoutput.printf("\n");
370
371 stdoutput.printf("time zone offsets:\n");
372 const int32_t *tzo=datetime::getTimeZoneOffsets();
373 i=0;
374 test("",tzo[i++]==34200);
375 test("",tzo[i++]==37800);
376 test("",tzo[i++]==34200);
377 test("",tzo[i++]==-14400);
378 test("",tzo[i++]==-10800);
379 test("",tzo[i++]==-14400);
380 test("",tzo[i++]==36000);
381 test("",tzo[i++]==39600);
382 test("",tzo[i++]==36000);
383 test("",tzo[i++]==-32400);
384 test("",tzo[i++]==-28800);
385 test("",tzo[i++]==-32400);
386 test("",tzo[i++]==-21600);
387 test("",tzo[i++]==-18000);
388 test("",tzo[i++]==-21600);
389 test("",tzo[i++]==3600);
390 test("",tzo[i++]==7200);
391 test("",tzo[i++]==3600);
392 test("",tzo[i++]==-18000);
393 test("",tzo[i++]==-14400);
394 test("",tzo[i++]==-18000);
395 test("",tzo[i++]==7200);
396 test("",tzo[i++]==10800);
397 test("",tzo[i++]==7200);
398 test("",tzo[i++]==0);
399 test("",tzo[i++]==3600);
400 test("",tzo[i++]==0);
401 test("",tzo[i++]==-14400);
402 test("",tzo[i++]==-10800);
403 test("",tzo[i++]==-14400);
404 test("",tzo[i++]==-21600);
405 test("",tzo[i++]==-18000);
406 test("",tzo[i++]==-21600);
407 test("",tzo[i++]==-36000);
408 test("",tzo[i++]==-32400);
409 test("",tzo[i++]==-36000);
410 test("",tzo[i++]==-18000);
411 test("",tzo[i++]==-14400);
412 test("",tzo[i++]==-18000);
413 test("",tzo[i++]==-28800);
414 test("",tzo[i++]==-25200);
415 test("",tzo[i++]==-28800);
416 test("",tzo[i++]==-25200);
417 test("",tzo[i++]==-21600);
418 test("",tzo[i++]==-25200);
419 test("",tzo[i++]==-12600);
420 test("",tzo[i++]==-9000);
421 test("",tzo[i++]==-12600);
422 test("",tzo[i++]==-32400);
423 test("",tzo[i++]==-28800);
424 test("",tzo[i++]==-32400);
425 test("",tzo[i++]==-25200);
426 test("",tzo[i++]==-21600);
427 test("",tzo[i++]==-25200);
428 test("",tzo[i++]==3600);
429 test("",tzo[i++]==7200);
430 test("",tzo[i++]==3600);
431 test("",tzo[i++]==-12600);
432 test("",tzo[i++]==-9000);
433 test("",tzo[i++]==-12600);
434 test("",tzo[i++]==-28800);
435 test("",tzo[i++]==-25200);
436 test("",tzo[i++]==-28800);
437 test("",tzo[i++]==0);
438 test("",tzo[i++]==3600);
439 stdoutput.printf("\n");
440
441
442 // FIXME: doesn't work with linux libc
443 #ifndef RUDIMENTS_HAVE_G_CONFIG_H
444 // switch time zones
445 stdoutput.printf("switch time zones:\n");
446 dt.initialize(datestring);
447 dt.adjustTimeZone("CST6CDT");
448 test("CST",!charstring::compare(dt.getString(),cstdatestring));
449 dt.adjustTimeZone("MST7MDT");
450 test("MST",!charstring::compare(dt.getString(),mstdatestring));
451 dt.adjustTimeZone("PST8PDT");
452 test("PST",!charstring::compare(dt.getString(),pstdatestring));
453 dt.adjustTimeZone("EST5EDT");
454 test("EST",!charstring::compare(dt.getString(),estdatestring));
455 stdoutput.printf("\n");
456 #endif
457
458
459 // valid/invalid dates
460 stdoutput.printf("valid/invalid dates:\n");
461 const char *str="02/20/1974 12:00:00";
462 test("",datetime::validDateTime(str));
463 str="02/30/1974 12:00:00";
464 test("",!datetime::validDateTime(str));
465 str="02/20/1974 12:00:00 EST5EDT";
466 test("",datetime::validDateTime(str));
467 str="02/30/1974 12:00:00 EST5EDT";
468 test("",!datetime::validDateTime(str));
469 }
470