xref: /openbsd-src/regress/lib/libc/time/time_conversion/timetest.c (revision 1a002d0cc87be27bd009614b4fdde92f667b4cd9)
1 /*	$OpenBSD: timetest.c,v 1.4 2023/04/13 11:32:06 mbuhl Exp $ */
2 
3 /*
4  * Copyright (c) 2022 Bob Beck <beck@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/stat.h>
20 #include <sys/stdint.h>
21 #include <sys/types.h>
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 
28 struct timetest {
29 	char *descr;
30 	char *timezone;
31 	time_t time;
32 	struct tm local_tm;
33 	struct tm gmt_tm;
34 };
35 
tm_match(struct tm * tm1,struct tm * tm2)36 static int tm_match(struct tm * tm1, struct tm *tm2) {
37 	if (tm2->tm_year != tm1->tm_year ||
38 	    tm2->tm_mon != tm1->tm_mon ||
39 	    tm2->tm_mday != tm1->tm_mday ||
40 	    tm2->tm_hour != tm1->tm_hour ||
41 	    tm2->tm_min != tm1->tm_min ||
42 	    tm2->tm_sec != tm1->tm_sec ||
43 	    tm2->tm_wday != tm1->tm_wday ||
44 	    tm2->tm_yday != tm1->tm_yday ||
45 	    tm2->tm_yday != tm1->tm_yday ||
46 	    tm2->tm_isdst != tm1->tm_isdst ||
47 	    tm2->tm_gmtoff != tm1->tm_gmtoff ||
48 	    strcmp(tm2->tm_zone, tm1->tm_zone) != 0)
49 		return 0;
50 	return 1;
51 }
52 
53 struct timetest timetests[] = {
54 	{
55 		.descr="moon",
56 		.timezone="posix/America/Edmonton",
57 		.time=-16751025,
58 		.local_tm=		{
59 			.tm_year=69,
60 			.tm_mon=5,
61 			.tm_mday=20,
62 			.tm_hour=19,
63 			.tm_min=56,
64 			.tm_sec=15,
65 			.tm_wday=5,
66 			.tm_yday=170,
67 			.tm_isdst=0,
68 			.tm_gmtoff=-25200,
69 			.tm_zone="MST"
70 		},
71 		.gmt_tm=		{
72 			.tm_year=69,
73 			.tm_mon=5,
74 			.tm_mday=21,
75 			.tm_hour=2,
76 			.tm_min=56,
77 			.tm_sec=15,
78 			.tm_wday=6,
79 			.tm_yday=171,
80 			.tm_isdst=0,
81 			.tm_gmtoff=0,
82 			.tm_zone="GMT"
83 		},
84 	},
85 	{
86 		.descr="moon",
87 		.timezone="right/UTC",
88 		.time=-16751025,
89 		.local_tm=		{
90 			.tm_year=69,
91 			.tm_mon=5,
92 			.tm_mday=21,
93 			.tm_hour=2,
94 			.tm_min=56,
95 			.tm_sec=15,
96 			.tm_wday=6,
97 			.tm_yday=171,
98 			.tm_isdst=0,
99 			.tm_gmtoff=0,
100 			.tm_zone="UTC"
101 		},
102 		.gmt_tm=		{
103 			.tm_year=69,
104 			.tm_mon=5,
105 			.tm_mday=21,
106 			.tm_hour=2,
107 			.tm_min=56,
108 			.tm_sec=15,
109 			.tm_wday=6,
110 			.tm_yday=171,
111 			.tm_isdst=0,
112 			.tm_gmtoff=0,
113 			.tm_zone="GMT"
114 		},
115 	},
116 	{
117 		.descr="moon",
118 		.timezone="right/America/Edmonton",
119 		.time=-16751025,
120 		.local_tm=		{
121 			.tm_year=69,
122 			.tm_mon=5,
123 			.tm_mday=20,
124 			.tm_hour=19,
125 			.tm_min=56,
126 			.tm_sec=15,
127 			.tm_wday=5,
128 			.tm_yday=170,
129 			.tm_isdst=0,
130 			.tm_gmtoff=-25200,
131 			.tm_zone="MST"
132 		},
133 		.gmt_tm=		{
134 			.tm_year=69,
135 			.tm_mon=5,
136 			.tm_mday=21,
137 			.tm_hour=2,
138 			.tm_min=56,
139 			.tm_sec=15,
140 			.tm_wday=6,
141 			.tm_yday=171,
142 			.tm_isdst=0,
143 			.tm_gmtoff=0,
144 			.tm_zone="GMT"
145 		},
146 	},
147 	{
148 		.descr="epoch",
149 		.timezone="posix/America/Edmonton",
150 		.time=0,
151 		.local_tm=		{
152 			.tm_year=69,
153 			.tm_mon=11,
154 			.tm_mday=31,
155 			.tm_hour=17,
156 			.tm_min=0,
157 			.tm_sec=0,
158 			.tm_wday=3,
159 			.tm_yday=364,
160 			.tm_isdst=0,
161 			.tm_gmtoff=-25200,
162 			.tm_zone="MST"
163 		},
164 		.gmt_tm=		{
165 			.tm_year=70,
166 			.tm_mon=0,
167 			.tm_mday=1,
168 			.tm_hour=0,
169 			.tm_min=0,
170 			.tm_sec=0,
171 			.tm_wday=4,
172 			.tm_yday=0,
173 			.tm_isdst=0,
174 			.tm_gmtoff=0,
175 			.tm_zone="GMT"
176 		},
177 	},
178 	{
179 		.descr="epoch",
180 		.timezone="right/UTC",
181 		.time=0,
182 		.local_tm=		{
183 			.tm_year=70,
184 			.tm_mon=0,
185 			.tm_mday=1,
186 			.tm_hour=0,
187 			.tm_min=0,
188 			.tm_sec=0,
189 			.tm_wday=4,
190 			.tm_yday=0,
191 			.tm_isdst=0,
192 			.tm_gmtoff=0,
193 			.tm_zone="UTC"
194 		},
195 		.gmt_tm=		{
196 			.tm_year=70,
197 			.tm_mon=0,
198 			.tm_mday=1,
199 			.tm_hour=0,
200 			.tm_min=0,
201 			.tm_sec=0,
202 			.tm_wday=4,
203 			.tm_yday=0,
204 			.tm_isdst=0,
205 			.tm_gmtoff=0,
206 			.tm_zone="GMT"
207 		},
208 	},
209 	{
210 		.descr="epoch",
211 		.timezone="right/America/Edmonton",
212 		.time=0,
213 		.local_tm=		{
214 			.tm_year=69,
215 			.tm_mon=11,
216 			.tm_mday=31,
217 			.tm_hour=17,
218 			.tm_min=0,
219 			.tm_sec=0,
220 			.tm_wday=3,
221 			.tm_yday=364,
222 			.tm_isdst=0,
223 			.tm_gmtoff=-25200,
224 			.tm_zone="MST"
225 		},
226 		.gmt_tm=		{
227 			.tm_year=70,
228 			.tm_mon=0,
229 			.tm_mday=1,
230 			.tm_hour=0,
231 			.tm_min=0,
232 			.tm_sec=0,
233 			.tm_wday=4,
234 			.tm_yday=0,
235 			.tm_isdst=0,
236 			.tm_gmtoff=0,
237 			.tm_zone="GMT"
238 		},
239 	},
240 	{
241 		.descr="epoch - 1",
242 		.timezone="posix/America/Edmonton",
243 		.time=-1,
244 		.local_tm=		{
245 			.tm_year=69,
246 			.tm_mon=11,
247 			.tm_mday=31,
248 			.tm_hour=16,
249 			.tm_min=59,
250 			.tm_sec=59,
251 			.tm_wday=3,
252 			.tm_yday=364,
253 			.tm_isdst=0,
254 			.tm_gmtoff=-25200,
255 			.tm_zone="MST"
256 		},
257 		.gmt_tm=		{
258 			.tm_year=69,
259 			.tm_mon=11,
260 			.tm_mday=31,
261 			.tm_hour=23,
262 			.tm_min=59,
263 			.tm_sec=59,
264 			.tm_wday=3,
265 			.tm_yday=364,
266 			.tm_isdst=0,
267 			.tm_gmtoff=0,
268 			.tm_zone="GMT"
269 		},
270 	},
271 	{
272 		.descr="epoch - 1",
273 		.timezone="right/UTC",
274 		.time=-1,
275 		.local_tm=		{
276 			.tm_year=69,
277 			.tm_mon=11,
278 			.tm_mday=31,
279 			.tm_hour=23,
280 			.tm_min=59,
281 			.tm_sec=59,
282 			.tm_wday=3,
283 			.tm_yday=364,
284 			.tm_isdst=0,
285 			.tm_gmtoff=0,
286 			.tm_zone="UTC"
287 		},
288 		.gmt_tm=		{
289 			.tm_year=69,
290 			.tm_mon=11,
291 			.tm_mday=31,
292 			.tm_hour=23,
293 			.tm_min=59,
294 			.tm_sec=59,
295 			.tm_wday=3,
296 			.tm_yday=364,
297 			.tm_isdst=0,
298 			.tm_gmtoff=0,
299 			.tm_zone="GMT"
300 		},
301 	},
302 	{
303 		.descr="epoch - 1",
304 		.timezone="right/America/Edmonton",
305 		.time=-1,
306 		.local_tm=		{
307 			.tm_year=69,
308 			.tm_mon=11,
309 			.tm_mday=31,
310 			.tm_hour=16,
311 			.tm_min=59,
312 			.tm_sec=59,
313 			.tm_wday=3,
314 			.tm_yday=364,
315 			.tm_isdst=0,
316 			.tm_gmtoff=-25200,
317 			.tm_zone="MST"
318 		},
319 		.gmt_tm=		{
320 			.tm_year=69,
321 			.tm_mon=11,
322 			.tm_mday=31,
323 			.tm_hour=23,
324 			.tm_min=59,
325 			.tm_sec=59,
326 			.tm_wday=3,
327 			.tm_yday=364,
328 			.tm_isdst=0,
329 			.tm_gmtoff=0,
330 			.tm_zone="GMT"
331 		},
332 	},
333 	{
334 		.descr="legacy min",
335 		.timezone="posix/America/Edmonton",
336 		.time=-2147483648,
337 		.local_tm=		{
338 			.tm_year=1,
339 			.tm_mon=11,
340 			.tm_mday=13,
341 			.tm_hour=13,
342 			.tm_min=12,
343 			.tm_sec=0,
344 			.tm_wday=5,
345 			.tm_yday=346,
346 			.tm_isdst=0,
347 			.tm_gmtoff=-27232,
348 			.tm_zone="LMT"
349 		},
350 		.gmt_tm=		{
351 			.tm_year=1,
352 			.tm_mon=11,
353 			.tm_mday=13,
354 			.tm_hour=20,
355 			.tm_min=45,
356 			.tm_sec=52,
357 			.tm_wday=5,
358 			.tm_yday=346,
359 			.tm_isdst=0,
360 			.tm_gmtoff=0,
361 			.tm_zone="GMT"
362 		},
363 	},
364 	{
365 		.descr="legacy min",
366 		.timezone="right/UTC",
367 		.time=-2147483648,
368 		.local_tm=		{
369 			.tm_year=1,
370 			.tm_mon=11,
371 			.tm_mday=13,
372 			.tm_hour=20,
373 			.tm_min=45,
374 			.tm_sec=52,
375 			.tm_wday=5,
376 			.tm_yday=346,
377 			.tm_isdst=0,
378 			.tm_gmtoff=0,
379 			.tm_zone="UTC"
380 		},
381 		.gmt_tm=		{
382 			.tm_year=1,
383 			.tm_mon=11,
384 			.tm_mday=13,
385 			.tm_hour=20,
386 			.tm_min=45,
387 			.tm_sec=52,
388 			.tm_wday=5,
389 			.tm_yday=346,
390 			.tm_isdst=0,
391 			.tm_gmtoff=0,
392 			.tm_zone="GMT"
393 		},
394 	},
395 	{
396 		.descr="legacy min - 1",
397 		.timezone="posix/America/Edmonton",
398 		.time=-2147483649,
399 		.local_tm=		{
400 			.tm_year=1,
401 			.tm_mon=11,
402 			.tm_mday=13,
403 			.tm_hour=13,
404 			.tm_min=11,
405 			.tm_sec=59,
406 			.tm_wday=5,
407 			.tm_yday=346,
408 			.tm_isdst=0,
409 			.tm_gmtoff=-27232,
410 			.tm_zone="LMT"
411 		},
412 		.gmt_tm=		{
413 			.tm_year=1,
414 			.tm_mon=11,
415 			.tm_mday=13,
416 			.tm_hour=20,
417 			.tm_min=45,
418 			.tm_sec=51,
419 			.tm_wday=5,
420 			.tm_yday=346,
421 			.tm_isdst=0,
422 			.tm_gmtoff=0,
423 			.tm_zone="GMT"
424 		},
425 	},
426 	{
427 		.descr="legacy min - 1",
428 		.timezone="right/UTC",
429 		.time=-2147483649,
430 		.local_tm=		{
431 			.tm_year=1,
432 			.tm_mon=11,
433 			.tm_mday=13,
434 			.tm_hour=20,
435 			.tm_min=45,
436 			.tm_sec=51,
437 			.tm_wday=5,
438 			.tm_yday=346,
439 			.tm_isdst=0,
440 			.tm_gmtoff=0,
441 			.tm_zone="UTC"
442 		},
443 		.gmt_tm=		{
444 			.tm_year=1,
445 			.tm_mon=11,
446 			.tm_mday=13,
447 			.tm_hour=20,
448 			.tm_min=45,
449 			.tm_sec=51,
450 			.tm_wday=5,
451 			.tm_yday=346,
452 			.tm_isdst=0,
453 			.tm_gmtoff=0,
454 			.tm_zone="GMT"
455 		},
456 	},
457 	{
458 		.descr="legacy max",
459 		.timezone="posix/America/Edmonton",
460 		.time=2147483647,
461 		.local_tm=		{
462 			.tm_year=138,
463 			.tm_mon=0,
464 			.tm_mday=18,
465 			.tm_hour=20,
466 			.tm_min=14,
467 			.tm_sec=7,
468 			.tm_wday=1,
469 			.tm_yday=17,
470 			.tm_isdst=0,
471 			.tm_gmtoff=-25200,
472 			.tm_zone="MST"
473 		},
474 		.gmt_tm=		{
475 			.tm_year=138,
476 			.tm_mon=0,
477 			.tm_mday=19,
478 			.tm_hour=3,
479 			.tm_min=14,
480 			.tm_sec=7,
481 			.tm_wday=2,
482 			.tm_yday=18,
483 			.tm_isdst=0,
484 			.tm_gmtoff=0,
485 			.tm_zone="GMT"
486 		},
487 	},
488 	{
489 		.descr="legacy max",
490 		.timezone="right/UTC",
491 		.time=2147483647,
492 		.local_tm=		{
493 			.tm_year=138,
494 			.tm_mon=0,
495 			.tm_mday=19,
496 			.tm_hour=3,
497 			.tm_min=13,
498 			.tm_sec=40,
499 			.tm_wday=2,
500 			.tm_yday=18,
501 			.tm_isdst=0,
502 			.tm_gmtoff=0,
503 			.tm_zone="UTC"
504 		},
505 		.gmt_tm=		{
506 			.tm_year=138,
507 			.tm_mon=0,
508 			.tm_mday=19,
509 			.tm_hour=3,
510 			.tm_min=14,
511 			.tm_sec=7,
512 			.tm_wday=2,
513 			.tm_yday=18,
514 			.tm_isdst=0,
515 			.tm_gmtoff=0,
516 			.tm_zone="GMT"
517 		},
518 	},
519 	{
520 		.descr="legacy max + 1",
521 		.timezone="posix/America/Edmonton",
522 		.time=2147483648,
523 		.local_tm=		{
524 			.tm_year=138,
525 			.tm_mon=0,
526 			.tm_mday=18,
527 			.tm_hour=20,
528 			.tm_min=14,
529 			.tm_sec=8,
530 			.tm_wday=1,
531 			.tm_yday=17,
532 			.tm_isdst=0,
533 			.tm_gmtoff=-25200,
534 			.tm_zone="MST"
535 		},
536 		.gmt_tm=		{
537 			.tm_year=138,
538 			.tm_mon=0,
539 			.tm_mday=19,
540 			.tm_hour=3,
541 			.tm_min=14,
542 			.tm_sec=8,
543 			.tm_wday=2,
544 			.tm_yday=18,
545 			.tm_isdst=0,
546 			.tm_gmtoff=0,
547 			.tm_zone="GMT"
548 		},
549 	},
550 	{
551 		.descr="legacy max + 1",
552 		.timezone="right/UTC",
553 		.time=2147483648,
554 		.local_tm=		{
555 			.tm_year=138,
556 			.tm_mon=0,
557 			.tm_mday=19,
558 			.tm_hour=3,
559 			.tm_min=13,
560 			.tm_sec=41,
561 			.tm_wday=2,
562 			.tm_yday=18,
563 			.tm_isdst=0,
564 			.tm_gmtoff=0,
565 			.tm_zone="UTC"
566 		},
567 		.gmt_tm=		{
568 			.tm_year=138,
569 			.tm_mon=0,
570 			.tm_mday=19,
571 			.tm_hour=3,
572 			.tm_min=14,
573 			.tm_sec=8,
574 			.tm_wday=2,
575 			.tm_yday=18,
576 			.tm_isdst=0,
577 			.tm_gmtoff=0,
578 			.tm_zone="GMT"
579 		},
580 	},
581 	{
582 		.descr="min",
583 		.timezone="posix/America/Edmonton",
584 		.time=INT64_MIN,
585 		.local_tm=		{
586 			.tm_year=0,
587 			.tm_mon=0,
588 			.tm_mday=0,
589 			.tm_hour=0,
590 			.tm_min=0,
591 			.tm_sec=0,
592 			.tm_wday=0,
593 			.tm_yday=0,
594 			.tm_isdst=0,
595 			.tm_gmtoff=0,
596 			.tm_zone="FAILURE"
597 		},
598 		.gmt_tm=		{
599 			.tm_year=0,
600 			.tm_mon=0,
601 			.tm_mday=0,
602 			.tm_hour=0,
603 			.tm_min=0,
604 			.tm_sec=0,
605 			.tm_wday=0,
606 			.tm_yday=0,
607 			.tm_isdst=0,
608 			.tm_gmtoff=0,
609 			.tm_zone="FAILURE"
610 		},
611 	},
612 	{
613 		.descr="min",
614 		.timezone="right/UTC",
615 		.time=INT64_MIN,
616 		.local_tm=		{
617 			.tm_year=0,
618 			.tm_mon=0,
619 			.tm_mday=0,
620 			.tm_hour=0,
621 			.tm_min=0,
622 			.tm_sec=0,
623 			.tm_wday=0,
624 			.tm_yday=0,
625 			.tm_isdst=0,
626 			.tm_gmtoff=0,
627 			.tm_zone="FAILURE"
628 		},
629 		.gmt_tm=		{
630 			.tm_year=0,
631 			.tm_mon=0,
632 			.tm_mday=0,
633 			.tm_hour=0,
634 			.tm_min=0,
635 			.tm_sec=0,
636 			.tm_wday=0,
637 			.tm_yday=0,
638 			.tm_isdst=0,
639 			.tm_gmtoff=0,
640 			.tm_zone="FAILURE"
641 		},
642 	},
643 	{
644 		.descr="max",
645 		.timezone="right/America/Edmonton",
646 		.time=9223372036854775807,
647 		.local_tm=		{
648 			.tm_year=0,
649 			.tm_mon=0,
650 			.tm_mday=0,
651 			.tm_hour=0,
652 			.tm_min=0,
653 			.tm_sec=0,
654 			.tm_wday=0,
655 			.tm_yday=0,
656 			.tm_isdst=0,
657 			.tm_gmtoff=0,
658 			.tm_zone="FAILURE"
659 		},
660 		.gmt_tm=		{
661 			.tm_year=0,
662 			.tm_mon=0,
663 			.tm_mday=0,
664 			.tm_hour=0,
665 			.tm_min=0,
666 			.tm_sec=0,
667 			.tm_wday=0,
668 			.tm_yday=0,
669 			.tm_isdst=0,
670 			.tm_gmtoff=0,
671 			.tm_zone="FAILURE"
672 		},
673 	},
674 	{
675 		.descr="max",
676 		.timezone="posix/America/Edmonton",
677 		.time=9223372036854775807,
678 		.local_tm=		{
679 			.tm_year=0,
680 			.tm_mon=0,
681 			.tm_mday=0,
682 			.tm_hour=0,
683 			.tm_min=0,
684 			.tm_sec=0,
685 			.tm_wday=0,
686 			.tm_yday=0,
687 			.tm_isdst=0,
688 			.tm_gmtoff=0,
689 			.tm_zone="FAILURE"
690 		},
691 		.gmt_tm=		{
692 			.tm_year=0,
693 			.tm_mon=0,
694 			.tm_mday=0,
695 			.tm_hour=0,
696 			.tm_min=0,
697 			.tm_sec=0,
698 			.tm_wday=0,
699 			.tm_yday=0,
700 			.tm_isdst=0,
701 			.tm_gmtoff=0,
702 			.tm_zone="FAILURE"
703 		},
704 	},
705 	{
706 		.descr="max",
707 		.timezone="right/UTC",
708 		.time=9223372036854775807,
709 		.local_tm=		{
710 			.tm_year=0,
711 			.tm_mon=0,
712 			.tm_mday=0,
713 			.tm_hour=0,
714 			.tm_min=0,
715 			.tm_sec=0,
716 			.tm_wday=0,
717 			.tm_yday=0,
718 			.tm_isdst=0,
719 			.tm_gmtoff=0,
720 			.tm_zone="FAILURE"
721 		},
722 		.gmt_tm=		{
723 			.tm_year=0,
724 			.tm_mon=0,
725 			.tm_mday=0,
726 			.tm_hour=0,
727 			.tm_min=0,
728 			.tm_sec=0,
729 			.tm_wday=0,
730 			.tm_yday=0,
731 			.tm_isdst=0,
732 			.tm_gmtoff=0,
733 			.tm_zone="FAILURE"
734 		},
735 	},
736 	{
737 		.descr="min",
738 		.timezone="right/America/Edmonton",
739 		.time=INT64_MIN,
740 		.local_tm=		{
741 			.tm_year=0,
742 			.tm_mon=0,
743 			.tm_mday=0,
744 			.tm_hour=0,
745 			.tm_min=0,
746 			.tm_sec=0,
747 			.tm_wday=0,
748 			.tm_yday=0,
749 			.tm_isdst=0,
750 			.tm_gmtoff=0,
751 			.tm_zone="FAILURE"
752 		},
753 		.gmt_tm=		{
754 			.tm_year=0,
755 			.tm_mon=0,
756 			.tm_mday=0,
757 			.tm_hour=0,
758 			.tm_min=0,
759 			.tm_sec=0,
760 			.tm_wday=0,
761 			.tm_yday=0,
762 			.tm_isdst=0,
763 			.tm_gmtoff=0,
764 			.tm_zone="FAILURE"
765 		},
766 	},
767 	{
768 		.descr="maxint struct tm",
769 		.timezone="right/America/Edmonton",
770 		.time=67767976204675199,
771 		.local_tm=		{
772                         .tm_year=2147481747,
773 			.tm_mon=0,
774 			.tm_mday=31,
775 			.tm_hour=16,
776 			.tm_min=59,
777 			.tm_sec=32,
778 			.tm_wday=4,
779 			.tm_yday=30,
780 			.tm_isdst=0,
781 			.tm_gmtoff=-25200,
782 			.tm_zone="MST"
783 		},
784 		.gmt_tm=		{
785                         .tm_year=2147481747,
786 			.tm_mon=0,
787 			.tm_mday=31,
788 			.tm_hour=23,
789 			.tm_min=59,
790 			.tm_sec=59,
791 			.tm_wday=4,
792 			.tm_yday=30,
793 			.tm_isdst=0,
794 			.tm_gmtoff=0,
795 			.tm_zone="GMT"
796 		},
797 	},
798 	{
799 		.descr="minint struct tm",
800 		.timezone="right/America/Edmonton",
801 		.time=-67768038398073601,
802 		.local_tm=		{
803                         .tm_year=-2147483578,
804 			.tm_mon=0,
805 			.tm_mday=31,
806 			.tm_hour=16,
807 			.tm_min=26,
808 			.tm_sec=7,
809 			.tm_wday=2,
810 			.tm_yday=30,
811 			.tm_isdst=0,
812 			.tm_gmtoff=-27232,
813 			.tm_zone="LMT"
814 		},
815 		.gmt_tm=		{
816                         .tm_year=-2147483578,
817 			.tm_mon=0,
818 			.tm_mday=31,
819 			.tm_hour=23,
820 			.tm_min=59,
821 			.tm_sec=59,
822 			.tm_wday=2,
823 			.tm_yday=30,
824 			.tm_isdst=0,
825 			.tm_gmtoff=0,
826 			.tm_zone="GMT"
827 		},
828 	},
829 	{
830 		.descr="maxint struct tm",
831 		.timezone="right/UTC",
832 		.time=67767976204675199,
833 		.local_tm=		{
834                         .tm_year=2147481747,
835 			.tm_mon=0,
836 			.tm_mday=31,
837 			.tm_hour=23,
838 			.tm_min=59,
839 			.tm_sec=32,
840 			.tm_wday=4,
841 			.tm_yday=30,
842 			.tm_isdst=0,
843 			.tm_gmtoff=0,
844 			.tm_zone="UTC"
845 		},
846 		.gmt_tm=		{
847                         .tm_year=2147481747,
848 			.tm_mon=0,
849 			.tm_mday=31,
850 			.tm_hour=23,
851 			.tm_min=59,
852 			.tm_sec=59,
853 			.tm_wday=4,
854 			.tm_yday=30,
855 			.tm_isdst=0,
856 			.tm_gmtoff=0,
857 			.tm_zone="GMT"
858 		},
859 	},
860 	{
861 		.descr="minint struct tm",
862 		.timezone="right/UTC",
863 		.time=-67768038398073601,
864 		.local_tm=		{
865                         .tm_year=-2147483578,
866 			.tm_mon=0,
867 			.tm_mday=31,
868 			.tm_hour=23,
869 			.tm_min=59,
870 			.tm_sec=59,
871 			.tm_wday=2,
872 			.tm_yday=30,
873 			.tm_isdst=0,
874 			.tm_gmtoff=0,
875 			.tm_zone="UTC"
876 		},
877 		.gmt_tm=		{
878                         .tm_year=-2147483578,
879 			.tm_mon=0,
880 			.tm_mday=31,
881 			.tm_hour=23,
882 			.tm_min=59,
883 			.tm_sec=59,
884 			.tm_wday=2,
885 			.tm_yday=30,
886 			.tm_isdst=0,
887 			.tm_gmtoff=0,
888 			.tm_zone="GMT"
889 		},
890 	},
891 	{
892 		.descr="0000",
893 		.timezone="posix/America/Edmonton",
894 		.time=-62167219200,
895 		.local_tm=		{
896 			.tm_year=-1901,
897 			.tm_mon=11,
898 			.tm_mday=31,
899 			.tm_hour=16,
900 			.tm_min=26,
901 			.tm_sec=8,
902 			.tm_wday=5,
903 			.tm_yday=364,
904 			.tm_isdst=0,
905 			.tm_gmtoff=-27232,
906 			.tm_zone="LMT"
907 		},
908 		.gmt_tm=		{
909 			.tm_year=-1900,
910 			.tm_mon=0,
911 			.tm_mday=1,
912 			.tm_hour=0,
913 			.tm_min=0,
914 			.tm_sec=0,
915 			.tm_wday=6,
916 			.tm_yday=0,
917 			.tm_isdst=0,
918 			.tm_gmtoff=0,
919 			.tm_zone="GMT"
920 		},
921 	},
922 	{
923 		.descr="0000",
924 		.timezone="right/UTC",
925 		.time=-62167219200,
926 		.local_tm=		{
927 			.tm_year=-1900,
928 			.tm_mon=0,
929 			.tm_mday=1,
930 			.tm_hour=0,
931 			.tm_min=0,
932 			.tm_sec=0,
933 			.tm_wday=6,
934 			.tm_yday=0,
935 			.tm_isdst=0,
936 			.tm_gmtoff=0,
937 			.tm_zone="UTC"
938 		},
939 		.gmt_tm=		{
940 			.tm_year=-1900,
941 			.tm_mon=0,
942 			.tm_mday=1,
943 			.tm_hour=0,
944 			.tm_min=0,
945 			.tm_sec=0,
946 			.tm_wday=6,
947 			.tm_yday=0,
948 			.tm_isdst=0,
949 			.tm_gmtoff=0,
950 			.tm_zone="GMT"
951 		},
952 	},
953 	{
954 		.descr="0000",
955 		.timezone="right/America/Edmonton",
956 		.time=-62167219200,
957 		.local_tm=		{
958 			.tm_year=-1901,
959 			.tm_mon=11,
960 			.tm_mday=31,
961 			.tm_hour=16,
962 			.tm_min=26,
963 			.tm_sec=8,
964 			.tm_wday=5,
965 			.tm_yday=364,
966 			.tm_isdst=0,
967 			.tm_gmtoff=-27232,
968 			.tm_zone="LMT"
969 		},
970 		.gmt_tm=		{
971 			.tm_year=-1900,
972 			.tm_mon=0,
973 			.tm_mday=1,
974 			.tm_hour=0,
975 			.tm_min=0,
976 			.tm_sec=0,
977 			.tm_wday=6,
978 			.tm_yday=0,
979 			.tm_isdst=0,
980 			.tm_gmtoff=0,
981 			.tm_zone="GMT"
982 		},
983 	},
984 	{
985 		.descr="9999",
986 		.timezone="posix/America/Edmonton",
987 		.time=253402300799,
988 		.local_tm=		{
989 			.tm_year=8099,
990 			.tm_mon=11,
991 			.tm_mday=31,
992 			.tm_hour=16,
993 			.tm_min=59,
994 			.tm_sec=59,
995 			.tm_wday=5,
996 			.tm_yday=364,
997 			.tm_isdst=0,
998 			.tm_gmtoff=-25200,
999 			.tm_zone="MST"
1000 		},
1001 		.gmt_tm=		{
1002 			.tm_year=8099,
1003 			.tm_mon=11,
1004 			.tm_mday=31,
1005 			.tm_hour=23,
1006 			.tm_min=59,
1007 			.tm_sec=59,
1008 			.tm_wday=5,
1009 			.tm_yday=364,
1010 			.tm_isdst=0,
1011 			.tm_gmtoff=0,
1012 			.tm_zone="GMT"
1013 		},
1014 	},
1015 	{
1016 		.descr="9999",
1017 		.timezone="right/UTC",
1018 		.time=253402300799,
1019 		.local_tm=		{
1020 			.tm_year=8099,
1021 			.tm_mon=11,
1022 			.tm_mday=31,
1023 			.tm_hour=23,
1024 			.tm_min=59,
1025 			.tm_sec=32,
1026 			.tm_wday=5,
1027 			.tm_yday=364,
1028 			.tm_isdst=0,
1029 			.tm_gmtoff=0,
1030 			.tm_zone="UTC"
1031 		},
1032 		.gmt_tm=		{
1033 			.tm_year=8099,
1034 			.tm_mon=11,
1035 			.tm_mday=31,
1036 			.tm_hour=23,
1037 			.tm_min=59,
1038 			.tm_sec=59,
1039 			.tm_wday=5,
1040 			.tm_yday=364,
1041 			.tm_isdst=0,
1042 			.tm_gmtoff=0,
1043 			.tm_zone="GMT"
1044 		},
1045 	},
1046 	{
1047 		.descr="9999",
1048 		.timezone="right/America/Edmonton",
1049 		.time=253402300799,
1050 		.local_tm=		{
1051 			.tm_year=8099,
1052 			.tm_mon=11,
1053 			.tm_mday=31,
1054 			.tm_hour=16,
1055 			.tm_min=59,
1056 			.tm_sec=32,
1057 			.tm_wday=5,
1058 			.tm_yday=364,
1059 			.tm_isdst=0,
1060 			.tm_gmtoff=-25200,
1061 			.tm_zone="MST"
1062 		},
1063 		.gmt_tm=		{
1064 			.tm_year=8099,
1065 			.tm_mon=11,
1066 			.tm_mday=31,
1067 			.tm_hour=23,
1068 			.tm_min=59,
1069 			.tm_sec=59,
1070 			.tm_wday=5,
1071 			.tm_yday=364,
1072 			.tm_isdst=0,
1073 			.tm_gmtoff=0,
1074 			.tm_zone="GMT"
1075 		},
1076 	},
1077 	{
1078 		.descr="leap second - 1",
1079 		.timezone="posix/America/Edmonton",
1080 		.time=1483228825,
1081 		.local_tm=		{
1082 			.tm_year=116,
1083 			.tm_mon=11,
1084 			.tm_mday=31,
1085 			.tm_hour=17,
1086 			.tm_min=0,
1087 			.tm_sec=25,
1088 			.tm_wday=6,
1089 			.tm_yday=365,
1090 			.tm_isdst=0,
1091 			.tm_gmtoff=-25200,
1092 			.tm_zone="MST"
1093 		},
1094 		.gmt_tm=		{
1095 			.tm_year=117,
1096 			.tm_mon=0,
1097 			.tm_mday=1,
1098 			.tm_hour=0,
1099 			.tm_min=0,
1100 			.tm_sec=25,
1101 			.tm_wday=0,
1102 			.tm_yday=0,
1103 			.tm_isdst=0,
1104 			.tm_gmtoff=0,
1105 			.tm_zone="GMT"
1106 		},
1107 	},
1108 	{
1109 		.descr="leap second",
1110 		.timezone="posix/America/Edmonton",
1111 		.time=1483228826,
1112 		.local_tm=		{
1113 			.tm_year=116,
1114 			.tm_mon=11,
1115 			.tm_mday=31,
1116 			.tm_hour=17,
1117 			.tm_min=0,
1118 			.tm_sec=26,
1119 			.tm_wday=6,
1120 			.tm_yday=365,
1121 			.tm_isdst=0,
1122 			.tm_gmtoff=-25200,
1123 			.tm_zone="MST"
1124 		},
1125 		.gmt_tm=		{
1126 			.tm_year=117,
1127 			.tm_mon=0,
1128 			.tm_mday=1,
1129 			.tm_hour=0,
1130 			.tm_min=0,
1131 			.tm_sec=26,
1132 			.tm_wday=0,
1133 			.tm_yday=0,
1134 			.tm_isdst=0,
1135 			.tm_gmtoff=0,
1136 			.tm_zone="GMT"
1137 		},
1138 	},
1139 	{
1140 		.descr="leap second + 1",
1141 		.timezone="posix/America/Edmonton",
1142 		.time=1483228827,
1143 		.local_tm=		{
1144 			.tm_year=116,
1145 			.tm_mon=11,
1146 			.tm_mday=31,
1147 			.tm_hour=17,
1148 			.tm_min=0,
1149 			.tm_sec=27,
1150 			.tm_wday=6,
1151 			.tm_yday=365,
1152 			.tm_isdst=0,
1153 			.tm_gmtoff=-25200,
1154 			.tm_zone="MST"
1155 		},
1156 		.gmt_tm=		{
1157 			.tm_year=117,
1158 			.tm_mon=0,
1159 			.tm_mday=1,
1160 			.tm_hour=0,
1161 			.tm_min=0,
1162 			.tm_sec=27,
1163 			.tm_wday=0,
1164 			.tm_yday=0,
1165 			.tm_isdst=0,
1166 			.tm_gmtoff=0,
1167 			.tm_zone="GMT"
1168 		},
1169 	},
1170 	{
1171 		.descr="leap second - 1",
1172 		.timezone="right/UTC",
1173 		.time=1483228825,
1174 		.local_tm=		{
1175 			.tm_year=116,
1176 			.tm_mon=11,
1177 			.tm_mday=31,
1178 			.tm_hour=23,
1179 			.tm_min=59,
1180 			.tm_sec=59,
1181 			.tm_wday=6,
1182 			.tm_yday=365,
1183 			.tm_isdst=0,
1184 			.tm_gmtoff=0,
1185 			.tm_zone="UTC"
1186 		},
1187 		.gmt_tm=		{
1188 			.tm_year=117,
1189 			.tm_mon=0,
1190 			.tm_mday=1,
1191 			.tm_hour=0,
1192 			.tm_min=0,
1193 			.tm_sec=25,
1194 			.tm_wday=0,
1195 			.tm_yday=0,
1196 			.tm_isdst=0,
1197 			.tm_gmtoff=0,
1198 			.tm_zone="GMT"
1199 		},
1200 	},
1201 	{
1202 		.descr="leap second",
1203 		.timezone="right/UTC",
1204 		.time=1483228826,
1205 		.local_tm=		{
1206 			.tm_year=116,
1207 			.tm_mon=11,
1208 			.tm_mday=31,
1209 			.tm_hour=23,
1210 			.tm_min=59,
1211 			.tm_sec=60,
1212 			.tm_wday=6,
1213 			.tm_yday=365,
1214 			.tm_isdst=0,
1215 			.tm_gmtoff=0,
1216 			.tm_zone="UTC"
1217 		},
1218 		.gmt_tm=		{
1219 			.tm_year=117,
1220 			.tm_mon=0,
1221 			.tm_mday=1,
1222 			.tm_hour=0,
1223 			.tm_min=0,
1224 			.tm_sec=26,
1225 			.tm_wday=0,
1226 			.tm_yday=0,
1227 			.tm_isdst=0,
1228 			.tm_gmtoff=0,
1229 			.tm_zone="GMT"
1230 		},
1231 	},
1232 	{
1233 		.descr="leap second + 1",
1234 		.timezone="right/UTC",
1235 		.time=1483228827,
1236 		.local_tm=		{
1237 			.tm_year=117,
1238 			.tm_mon=0,
1239 			.tm_mday=1,
1240 			.tm_hour=0,
1241 			.tm_min=0,
1242 			.tm_sec=0,
1243 			.tm_wday=0,
1244 			.tm_yday=0,
1245 			.tm_isdst=0,
1246 			.tm_gmtoff=0,
1247 			.tm_zone="UTC"
1248 		},
1249 		.gmt_tm=		{
1250 			.tm_year=117,
1251 			.tm_mon=0,
1252 			.tm_mday=1,
1253 			.tm_hour=0,
1254 			.tm_min=0,
1255 			.tm_sec=27,
1256 			.tm_wday=0,
1257 			.tm_yday=0,
1258 			.tm_isdst=0,
1259 			.tm_gmtoff=0,
1260 			.tm_zone="GMT"
1261 		},
1262 	},
1263 	{
1264 		.descr="leap second - 1",
1265 		.timezone="right/America/Edmonton",
1266 		.time=1483228825,
1267 		.local_tm=		{
1268 			.tm_year=116,
1269 			.tm_mon=11,
1270 			.tm_mday=31,
1271 			.tm_hour=16,
1272 			.tm_min=59,
1273 			.tm_sec=59,
1274 			.tm_wday=6,
1275 			.tm_yday=365,
1276 			.tm_isdst=0,
1277 			.tm_gmtoff=-25200,
1278 			.tm_zone="MST"
1279 		},
1280 		.gmt_tm=		{
1281 			.tm_year=117,
1282 			.tm_mon=0,
1283 			.tm_mday=1,
1284 			.tm_hour=0,
1285 			.tm_min=0,
1286 			.tm_sec=25,
1287 			.tm_wday=0,
1288 			.tm_yday=0,
1289 			.tm_isdst=0,
1290 			.tm_gmtoff=0,
1291 			.tm_zone="GMT"
1292 		},
1293 	},
1294 	{
1295 		.descr="leap second",
1296 		.timezone="right/America/Edmonton",
1297 		.time=1483228826,
1298 		.local_tm=		{
1299 			.tm_year=116,
1300 			.tm_mon=11,
1301 			.tm_mday=31,
1302 			.tm_hour=16,
1303 			.tm_min=59,
1304 			.tm_sec=60,
1305 			.tm_wday=6,
1306 			.tm_yday=365,
1307 			.tm_isdst=0,
1308 			.tm_gmtoff=-25200,
1309 			.tm_zone="MST"
1310 		},
1311 		.gmt_tm=		{
1312 			.tm_year=117,
1313 			.tm_mon=0,
1314 			.tm_mday=1,
1315 			.tm_hour=0,
1316 			.tm_min=0,
1317 			.tm_sec=26,
1318 			.tm_wday=0,
1319 			.tm_yday=0,
1320 			.tm_isdst=0,
1321 			.tm_gmtoff=0,
1322 			.tm_zone="GMT"
1323 		},
1324 	},
1325 	{
1326 		.descr="leap second + 1",
1327 		.timezone="right/America/Edmonton",
1328 		.time=1483228827,
1329 		.local_tm=		{
1330 			.tm_year=116,
1331 			.tm_mon=11,
1332 			.tm_mday=31,
1333 			.tm_hour=17,
1334 			.tm_min=0,
1335 			.tm_sec=0,
1336 			.tm_wday=6,
1337 			.tm_yday=365,
1338 			.tm_isdst=0,
1339 			.tm_gmtoff=-25200,
1340 			.tm_zone="MST"
1341 		},
1342 		.gmt_tm=		{
1343 			.tm_year=117,
1344 			.tm_mon=0,
1345 			.tm_mday=1,
1346 			.tm_hour=0,
1347 			.tm_min=0,
1348 			.tm_sec=27,
1349 			.tm_wday=0,
1350 			.tm_yday=0,
1351 			.tm_isdst=0,
1352 			.tm_gmtoff=0,
1353 			.tm_zone="GMT"
1354 		},
1355 	},
1356 	{
1357 		.descr="transition standard to daylight - 1",
1358 		.timezone="posix/America/Edmonton",
1359 		.time=1457859599,
1360 		.local_tm=		{
1361 			.tm_year=116,
1362 			.tm_mon=2,
1363 			.tm_mday=13,
1364 			.tm_hour=1,
1365 			.tm_min=59,
1366 			.tm_sec=59,
1367 			.tm_wday=0,
1368 			.tm_yday=72,
1369 			.tm_isdst=0,
1370 			.tm_gmtoff=-25200,
1371 			.tm_zone="MST"
1372 		},
1373 		.gmt_tm=		{
1374 			.tm_year=116,
1375 			.tm_mon=2,
1376 			.tm_mday=13,
1377 			.tm_hour=8,
1378 			.tm_min=59,
1379 			.tm_sec=59,
1380 			.tm_wday=0,
1381 			.tm_yday=72,
1382 			.tm_isdst=0,
1383 			.tm_gmtoff=0,
1384 			.tm_zone="GMT"
1385 		},
1386 	},
1387 	{
1388 		.descr="transition standard to daylight",
1389 		.timezone="posix/America/Edmonton",
1390 		.time=1457859600,
1391 		.local_tm=		{
1392 			.tm_year=116,
1393 			.tm_mon=2,
1394 			.tm_mday=13,
1395 			.tm_hour=3,
1396 			.tm_min=0,
1397 			.tm_sec=0,
1398 			.tm_wday=0,
1399 			.tm_yday=72,
1400 			.tm_isdst=1,
1401 			.tm_gmtoff=-21600,
1402 			.tm_zone="MDT"
1403 		},
1404 		.gmt_tm=		{
1405 			.tm_year=116,
1406 			.tm_mon=2,
1407 			.tm_mday=13,
1408 			.tm_hour=9,
1409 			.tm_min=0,
1410 			.tm_sec=0,
1411 			.tm_wday=0,
1412 			.tm_yday=72,
1413 			.tm_isdst=0,
1414 			.tm_gmtoff=0,
1415 			.tm_zone="GMT"
1416 		},
1417 	},
1418 	{
1419 		.descr="transition standard to daylight + 1",
1420 		.timezone="posix/America/Edmonton",
1421 		.time=1457859601,
1422 		.local_tm=		{
1423 			.tm_year=116,
1424 			.tm_mon=2,
1425 			.tm_mday=13,
1426 			.tm_hour=3,
1427 			.tm_min=0,
1428 			.tm_sec=1,
1429 			.tm_wday=0,
1430 			.tm_yday=72,
1431 			.tm_isdst=1,
1432 			.tm_gmtoff=-21600,
1433 			.tm_zone="MDT"
1434 		},
1435 		.gmt_tm=		{
1436 			.tm_year=116,
1437 			.tm_mon=2,
1438 			.tm_mday=13,
1439 			.tm_hour=9,
1440 			.tm_min=0,
1441 			.tm_sec=1,
1442 			.tm_wday=0,
1443 			.tm_yday=72,
1444 			.tm_isdst=0,
1445 			.tm_gmtoff=0,
1446 			.tm_zone="GMT"
1447 		},
1448 	},
1449 	{
1450 		.descr="transition standard to daylight - 1",
1451 		.timezone="right/America/Edmonton",
1452 		.time=1457859625,
1453 		.local_tm=		{
1454 			.tm_year=116,
1455 			.tm_mon=2,
1456 			.tm_mday=13,
1457 			.tm_hour=1,
1458 			.tm_min=59,
1459 			.tm_sec=59,
1460 			.tm_wday=0,
1461 			.tm_yday=72,
1462 			.tm_isdst=0,
1463 			.tm_gmtoff=-25200,
1464 			.tm_zone="MST"
1465 		},
1466 		.gmt_tm=		{
1467 			.tm_year=116,
1468 			.tm_mon=2,
1469 			.tm_mday=13,
1470 			.tm_hour=9,
1471 			.tm_min=0,
1472 			.tm_sec=25,
1473 			.tm_wday=0,
1474 			.tm_yday=72,
1475 			.tm_isdst=0,
1476 			.tm_gmtoff=0,
1477 			.tm_zone="GMT"
1478 		},
1479 	},
1480 	{
1481 		.descr="transition standard to daylight",
1482 		.timezone="right/America/Edmonton",
1483 		.time=1457859626,
1484 		.local_tm=		{
1485 			.tm_year=116,
1486 			.tm_mon=2,
1487 			.tm_mday=13,
1488 			.tm_hour=3,
1489 			.tm_min=0,
1490 			.tm_sec=0,
1491 			.tm_wday=0,
1492 			.tm_yday=72,
1493 			.tm_isdst=1,
1494 			.tm_gmtoff=-21600,
1495 			.tm_zone="MDT"
1496 		},
1497 		.gmt_tm=		{
1498 			.tm_year=116,
1499 			.tm_mon=2,
1500 			.tm_mday=13,
1501 			.tm_hour=9,
1502 			.tm_min=0,
1503 			.tm_sec=26,
1504 			.tm_wday=0,
1505 			.tm_yday=72,
1506 			.tm_isdst=0,
1507 			.tm_gmtoff=0,
1508 			.tm_zone="GMT"
1509 		},
1510 	},
1511 	{
1512 		.descr="transition standard to daylight + 1",
1513 		.timezone="right/America/Edmonton",
1514 		.time=1457859627,
1515 		.local_tm=		{
1516 			.tm_year=116,
1517 			.tm_mon=2,
1518 			.tm_mday=13,
1519 			.tm_hour=3,
1520 			.tm_min=0,
1521 			.tm_sec=1,
1522 			.tm_wday=0,
1523 			.tm_yday=72,
1524 			.tm_isdst=1,
1525 			.tm_gmtoff=-21600,
1526 			.tm_zone="MDT"
1527 		},
1528 		.gmt_tm=		{
1529 			.tm_year=116,
1530 			.tm_mon=2,
1531 			.tm_mday=13,
1532 			.tm_hour=9,
1533 			.tm_min=0,
1534 			.tm_sec=27,
1535 			.tm_wday=0,
1536 			.tm_yday=72,
1537 			.tm_isdst=0,
1538 			.tm_gmtoff=0,
1539 			.tm_zone="GMT"
1540 		},
1541 	},
1542 	{
1543 		.descr="transition daylight to standard - 1",
1544 		.timezone="posix/America/Edmonton",
1545 		.time=1478419199,
1546 		.local_tm=		{
1547 			.tm_year=116,
1548 			.tm_mon=10,
1549 			.tm_mday=6,
1550 			.tm_hour=1,
1551 			.tm_min=59,
1552 			.tm_sec=59,
1553 			.tm_wday=0,
1554 			.tm_yday=310,
1555 			.tm_isdst=1,
1556 			.tm_gmtoff=-21600,
1557 			.tm_zone="MDT"
1558 		},
1559 		.gmt_tm=		{
1560 			.tm_year=116,
1561 			.tm_mon=10,
1562 			.tm_mday=6,
1563 			.tm_hour=7,
1564 			.tm_min=59,
1565 			.tm_sec=59,
1566 			.tm_wday=0,
1567 			.tm_yday=310,
1568 			.tm_isdst=0,
1569 			.tm_gmtoff=0,
1570 			.tm_zone="GMT"
1571 		},
1572 	},
1573 	{
1574 		.descr="transition daylight to standard",
1575 		.timezone="posix/America/Edmonton",
1576 		.time=1478419200,
1577 		.local_tm=		{
1578 			.tm_year=116,
1579 			.tm_mon=10,
1580 			.tm_mday=6,
1581 			.tm_hour=1,
1582 			.tm_min=0,
1583 			.tm_sec=0,
1584 			.tm_wday=0,
1585 			.tm_yday=310,
1586 			.tm_isdst=0,
1587 			.tm_gmtoff=-25200,
1588 			.tm_zone="MST"
1589 		},
1590 		.gmt_tm=		{
1591 			.tm_year=116,
1592 			.tm_mon=10,
1593 			.tm_mday=6,
1594 			.tm_hour=8,
1595 			.tm_min=0,
1596 			.tm_sec=0,
1597 			.tm_wday=0,
1598 			.tm_yday=310,
1599 			.tm_isdst=0,
1600 			.tm_gmtoff=0,
1601 			.tm_zone="GMT"
1602 		},
1603 	},
1604 	{
1605 		.descr="transition daylight to standard + 1",
1606 		.timezone="posix/America/Edmonton",
1607 		.time=1478419201,
1608 		.local_tm=		{
1609 			.tm_year=116,
1610 			.tm_mon=10,
1611 			.tm_mday=6,
1612 			.tm_hour=1,
1613 			.tm_min=0,
1614 			.tm_sec=1,
1615 			.tm_wday=0,
1616 			.tm_yday=310,
1617 			.tm_isdst=0,
1618 			.tm_gmtoff=-25200,
1619 			.tm_zone="MST"
1620 		},
1621 		.gmt_tm=		{
1622 			.tm_year=116,
1623 			.tm_mon=10,
1624 			.tm_mday=6,
1625 			.tm_hour=8,
1626 			.tm_min=0,
1627 			.tm_sec=1,
1628 			.tm_wday=0,
1629 			.tm_yday=310,
1630 			.tm_isdst=0,
1631 			.tm_gmtoff=0,
1632 			.tm_zone="GMT"
1633 		},
1634 	},
1635 	{
1636 		.descr="transition daylight to standard - 1",
1637 		.timezone="right/America/Edmonton",
1638 		.time=1478419225,
1639 		.local_tm=		{
1640 			.tm_year=116,
1641 			.tm_mon=10,
1642 			.tm_mday=6,
1643 			.tm_hour=1,
1644 			.tm_min=59,
1645 			.tm_sec=59,
1646 			.tm_wday=0,
1647 			.tm_yday=310,
1648 			.tm_isdst=1,
1649 			.tm_gmtoff=-21600,
1650 			.tm_zone="MDT"
1651 		},
1652 		.gmt_tm=		{
1653 			.tm_year=116,
1654 			.tm_mon=10,
1655 			.tm_mday=6,
1656 			.tm_hour=8,
1657 			.tm_min=0,
1658 			.tm_sec=25,
1659 			.tm_wday=0,
1660 			.tm_yday=310,
1661 			.tm_isdst=0,
1662 			.tm_gmtoff=0,
1663 			.tm_zone="GMT"
1664 		},
1665 	},
1666 	{
1667 		.descr="transition daylight to standard",
1668 		.timezone="right/America/Edmonton",
1669 		.time=1478419226,
1670 		.local_tm=		{
1671 			.tm_year=116,
1672 			.tm_mon=10,
1673 			.tm_mday=6,
1674 			.tm_hour=1,
1675 			.tm_min=0,
1676 			.tm_sec=0,
1677 			.tm_wday=0,
1678 			.tm_yday=310,
1679 			.tm_isdst=0,
1680 			.tm_gmtoff=-25200,
1681 			.tm_zone="MST"
1682 		},
1683 		.gmt_tm=		{
1684 			.tm_year=116,
1685 			.tm_mon=10,
1686 			.tm_mday=6,
1687 			.tm_hour=8,
1688 			.tm_min=0,
1689 			.tm_sec=26,
1690 			.tm_wday=0,
1691 			.tm_yday=310,
1692 			.tm_isdst=0,
1693 			.tm_gmtoff=0,
1694 			.tm_zone="GMT"
1695 		},
1696 	},
1697 	{
1698 		.descr="transition daylight to standard + 1",
1699 		.timezone="right/America/Edmonton",
1700 		.time=1478419227,
1701 		.local_tm=		{
1702 			.tm_year=116,
1703 			.tm_mon=10,
1704 			.tm_mday=6,
1705 			.tm_hour=1,
1706 			.tm_min=0,
1707 			.tm_sec=1,
1708 			.tm_wday=0,
1709 			.tm_yday=310,
1710 			.tm_isdst=0,
1711 			.tm_gmtoff=-25200,
1712 			.tm_zone="MST"
1713 		},
1714 		.gmt_tm=		{
1715 			.tm_year=116,
1716 			.tm_mon=10,
1717 			.tm_mday=6,
1718 			.tm_hour=8,
1719 			.tm_min=0,
1720 			.tm_sec=27,
1721 			.tm_wday=0,
1722 			.tm_yday=310,
1723 			.tm_isdst=0,
1724 			.tm_gmtoff=0,
1725 			.tm_zone="GMT"
1726 		},
1727 	},
1728         {
1729 		.descr = NULL,
1730 	},
1731 };
1732 
printtm(FILE * f,struct tm * tm)1733 void printtm(FILE *f, struct tm *tm)
1734 {
1735 	fprintf(f, "\t\t{\n\t\t\t.tm_year=%d,\n\t\t\t.tm_mon=%d,\n\t\t\t"
1736 	    ".tm_mday=%d,\n\t\t\t.tm_hour=%d,\n\t\t\t.tm_min=%d,\n\t\t\t"
1737 	    ".tm_sec=%d,\n\t\t\t.tm_wday=%d,\n\t\t\t.tm_yday=%d,\n\t\t\t"
1738 	    ".tm_isdst=%d,\n\t\t\t.tm_gmtoff=%ld,\n\t\t\t.tm_zone=\"%s\""
1739 	    "\n\t\t},\n",
1740 	    tm->tm_year,
1741 	    tm->tm_mon,
1742 	    tm->tm_mday,
1743 	    tm->tm_hour,
1744 	    tm->tm_min,
1745 	    tm->tm_sec,
1746 	    tm->tm_wday,
1747 	    tm->tm_yday,
1748 	    tm->tm_isdst,
1749 	    tm->tm_gmtoff,
1750 	    tm->tm_zone);
1751 }
1752 
dotimetest(struct timetest * test,int print)1753 int dotimetest(struct timetest *test, int print)
1754 {
1755 	int failures = 0;
1756 	struct tm local = {}, gmt = {};
1757 	time_t converted;
1758 	if (gmtime_r(&test->time, &gmt) == NULL) {
1759 		memset(&gmt, 0, sizeof(gmt));
1760 		gmt.tm_zone="FAILURE";
1761 	} else {
1762 		converted = timegm(&gmt);
1763 		if (converted != test->time) {
1764 			fprintf(stderr, "FAIL: test \"%s\", tz \"%s\" timegm "
1765 			    "does not match expected value\n", test->descr,
1766 			    test->timezone);
1767 			fprintf(stderr, "expected: %lld\n", test->time);
1768 			fprintf(stderr, "actual: %lld\n", converted);
1769 			failures++;
1770 		}
1771 	}
1772 	if (!tm_match(&test->gmt_tm, &gmt)) {
1773 		fprintf(stderr, "FAIL: test \"%s\", tz \"%s\" gmtime_r does not"
1774 		    " match expected value\n", test->descr, test->timezone);
1775 		fprintf(stderr, "expected: ");
1776 		printtm(stderr, &test->gmt_tm);
1777 		fprintf(stderr, "actual: ");
1778 		printtm(stderr, &gmt);
1779 		failures++;
1780 	}
1781 	setenv("TZ", test->timezone, 1);
1782 	if (localtime_r(&test->time, &local) == NULL) {
1783 		memset(&local, 0, sizeof(local));
1784 		local.tm_zone="FAILURE";
1785 	} else {
1786 		converted = mktime(&local);
1787 		if (converted != test->time) {
1788 			fprintf(stderr, "FAIL: test \"%s\", tz \"%s\" mktime "
1789 			    "does not match expected value\n", test->descr,
1790 			    test->timezone);
1791 			fprintf(stderr, "expected: %lld\n", test->time);
1792 			fprintf(stderr, "actual: %lld\n", converted);
1793 			failures++;
1794 		}
1795 	}
1796 	if (!tm_match(&test->local_tm, &local)) {
1797 		fprintf(stderr, "FAIL: test \"%s\", tz \"%s\" localtime_r does "
1798 		    "not match expected value\n", test->descr, test->timezone);
1799 		fprintf(stderr, "expected: ");
1800 		printtm(stderr, &test->local_tm);
1801 		fprintf(stderr, "actual: ");
1802 		printtm(stderr, &local);
1803 		failures++;
1804 	}
1805 	if (print) {
1806 		printf("\t{\n\t\t.descr=\"%s\",\n\t\t.timezone=\"%s\",\n\t\t"
1807 		    ".time=%lld,\n", test->descr, test->timezone, test->time);
1808 		printf("\t\t.local_tm=");
1809 		printtm(stdout, &local);
1810 		printf("\t\t.gmt_tm=");
1811 		printtm(stdout, &gmt);
1812 		printf("\t},\n");
1813 	}
1814 	return failures;
1815 }
1816 
1817 
printtmdescr(FILE * f,struct tm * tm,char * descr)1818 void printtmdescr(FILE *f, struct tm *tm, char * descr)
1819 {
1820 	fprintf(f, "%s: ", descr);
1821 	printtm(f, tm);
1822 }
1823 
main()1824 int main() {
1825 	int failures = 0;
1826 	int verbose = 0;
1827 	struct stat sb;
1828 	size_t i;
1829 
1830 	if (stat("/usr/share/zoneinfo/posix", &sb) == -1 ||
1831 	    stat("/usr/share/zoneinfo/right", &sb) == -1) {
1832 		fprintf(stderr, "POSIX time zones missing, run the following command:\n\n"
1833 		    "\tmake -C ../../../../../share/zoneinfo other_two\n\n"
1834 		    "SKIPPED\n");
1835 		exit(0);
1836 	}
1837 
1838 	for (i = 0; timetests[i].descr != NULL; i++) {
1839 		failures += dotimetest(&timetests[i], verbose);
1840 	}
1841 	if (failures)
1842 		fprintf(stderr, "FAIL:  %d time test failures\n", failures);
1843 	else
1844 		printf("SUCCESS: no time test failures\n");
1845 	exit(failures);
1846 }
1847 
1848