apply UTC offset during timestamp conversion
[libi2ncommon] / test / test_timefunc.cpp
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 /** @file
21  * @brief unit test for time related functions.
22  *
23  * @copyright Copyright © 2001-2008 by Intra2net AG
24  *
25  */
26
27 #define BOOST_TEST_DYN_LINK
28 #include <boost/test/unit_test.hpp>
29
30 #include <timefunc.hxx>
31 #include <filefunc.hxx>
32
33 #include <unistd.h>
34 #include <set>
35 #include <iostream>
36
37 using namespace std;
38 using namespace I2n;
39 using namespace I2n::Time;
40
41 class TestTimeFuncFixture
42 {
43 protected:
44    typedef std::list< std::string > StringList;
45    std::set<std::string>  used_check_files;
46    std::string tz; /* save and restore TZ from envp */
47
48    std::string get_check_file_path(std::string tag)
49    {
50       std::string result;
51       result= "__unittest__" + tag + ".dat";
52       used_check_files.insert(result);
53       return result;
54    } // eo get_check_file_path
55
56    void remove_check_files()
57    {
58       for (std::set<std::string>::iterator it= used_check_files.begin();
59             it != used_check_files.end();
60             ++it)
61       {
62          std::string filepath(*it);
63          if (path_exists(filepath))
64          {
65             unlink(filepath);
66          }
67          //TODO
68       }
69       used_check_files.clear();
70    } // eo remove_check_files
71
72    void set_tz (const std::string &tzname)
73    {
74         errno = 0;
75         if (setenv ("TZ", tzname.c_str (), 1) == -1)
76         {
77             std::cerr
78                 << "error setting environment 'TZ': [" << tzname << "]"
79                 << std::endl
80                 ;
81             return;
82         }
83
84         tzset ();
85    }
86
87    inline void set_utc (void)
88    {
89        this->set_tz ("UTC");
90    }
91
92 public:
93     TestTimeFuncFixture()
94         : tz (secure_getenv ("TZ") ?: "")
95     {
96     }
97
98     ~TestTimeFuncFixture()
99     {
100         remove_check_files();
101
102         errno = 0;
103         if (setenv ("TZ", this->tz.c_str (), 1) == -1)
104         {
105             std::cerr
106                 << "error cleaning up environment 'TZ': [" << this->tz << "]"
107                 << std::endl
108                 ;
109         }
110         else
111         {
112             tzset();
113         }
114     }
115 };
116
117 BOOST_FIXTURE_TEST_SUITE(TestTimeFunc, TestTimeFuncFixture)
118
119 BOOST_AUTO_TEST_CASE(AddIntervalsDisjoint)
120 {
121     Intervals intervals;
122
123     intervals.add( Interval( 10, 100 ) );
124     intervals.add( Interval( 600, 620 ) );
125
126     BOOST_CHECK_EQUAL( false, intervals.empty() );
127     BOOST_CHECK_EQUAL( 2u, intervals.size() );
128
129     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
130     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
131
132     BOOST_CHECK_EQUAL( 600u, intervals.back().lower_bound() );
133     BOOST_CHECK_EQUAL( 620u, intervals.back().upper_bound() );
134 } // eo AddIntervalsDisjoint()
135
136
137
138 BOOST_AUTO_TEST_CASE(AddIntervalsInclude)
139 {
140     Intervals intervals;
141
142     intervals.add( Interval( 10, 100 ) );
143     intervals.add( Interval( 10, 80 ) );
144
145     BOOST_CHECK_EQUAL( false, intervals.empty() );
146     BOOST_CHECK_EQUAL( 1u, intervals.size() );
147
148     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
149     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
150     BOOST_CHECK_EQUAL( false, intervals.front().changed() );
151 } // eo AddIntervalsInclude()
152
153
154
155 BOOST_AUTO_TEST_CASE(AddIntervalsEmbrace)
156 {
157     Intervals intervals;
158
159     intervals.add( Interval( 10, 100 ) );
160     intervals.add( Interval( 5, 120 ) );
161
162     BOOST_CHECK_EQUAL( false, intervals.empty() );
163     BOOST_CHECK_EQUAL( 1u, intervals.size() );
164
165     BOOST_CHECK_EQUAL( 5u, intervals.front().lower_bound() );
166     BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() );
167     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
168 } // eo AddIntervalsEmbrace()
169
170
171
172 BOOST_AUTO_TEST_CASE(AddIntervalsJoin1)
173 {
174     Intervals intervals;
175
176     intervals.add( Interval( 10, 100 ) );
177     intervals.add( Interval( 60, 120 ) );
178
179     BOOST_CHECK_EQUAL( false, intervals.empty() );
180     BOOST_CHECK_EQUAL( 1u, intervals.size() );
181
182     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
183     BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() );
184     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
185 } // eo AddIntervalsJoin1()
186
187
188
189 BOOST_AUTO_TEST_CASE(AddIntervalsJoin1b)
190 {
191     Intervals intervals;
192
193     intervals.add( Interval( 10, 100 ) );
194     intervals.add( Interval( 100, 120 ) );
195
196     BOOST_CHECK_EQUAL( false, intervals.empty() );
197     BOOST_CHECK_EQUAL( 1u, intervals.size() );
198
199     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
200     BOOST_CHECK_EQUAL( 120u, intervals.front().upper_bound() );
201     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
202 } // eo AddIntervalsJoin1b()
203
204
205
206 BOOST_AUTO_TEST_CASE(AddIntervalsJoin2)
207 {
208     Intervals intervals;
209
210     intervals.add( Interval( 10, 100 ) );
211     intervals.add( Interval( 200, 250 ) );
212
213     BOOST_CHECK_EQUAL( false, intervals.empty() );
214     BOOST_CHECK_EQUAL( 2u, intervals.size() );
215
216     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
217     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
218     BOOST_CHECK_EQUAL( 200u, intervals.back().lower_bound() );
219     BOOST_CHECK_EQUAL( 250u, intervals.back().upper_bound() );
220
221     // now add the gap; the intervals should collapse to one covering all:
222     intervals.add( Interval(100, 200) );
223
224     BOOST_CHECK_EQUAL( false, intervals.empty() );
225     BOOST_CHECK_EQUAL( 1u, intervals.size() );
226
227     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
228     BOOST_CHECK_EQUAL( 250u, intervals.front().upper_bound() );
229     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
230 } // eo AddIntervalsJoin2()
231
232
233
234 BOOST_AUTO_TEST_CASE(SubIntervalsDisjoint)
235 {
236     Intervals intervals;
237
238     intervals.add( Interval(10, 100) );
239     intervals.sub( Interval(0, 10) );
240
241     BOOST_CHECK_EQUAL( false, intervals.empty() );
242     BOOST_CHECK_EQUAL( 1u, intervals.size() );
243
244     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
245     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
246     BOOST_CHECK_EQUAL( false, intervals.front().changed() );
247 } // eo SubIntervalsDisjoint()
248
249
250
251 BOOST_AUTO_TEST_CASE(SubIntervalsExact)
252 {
253     Intervals intervals;
254
255     intervals.add( Interval(10, 100) );
256     intervals.sub( Interval(10, 100) );
257
258     BOOST_CHECK_EQUAL( true, intervals.empty() );
259     BOOST_CHECK_EQUAL( 0u, intervals.size() );
260 } // eo SubIntervalsExact()
261
262
263
264 BOOST_AUTO_TEST_CASE(SubIntervalsSplit1)
265 {
266     Intervals intervals;
267
268     intervals.add( Interval(10, 100) );
269     intervals.sub( Interval(20, 40) );
270
271     BOOST_CHECK_EQUAL( false, intervals.empty() );
272     BOOST_CHECK_EQUAL( 2u, intervals.size() );
273
274     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
275     BOOST_CHECK_EQUAL( 20u, intervals.front().upper_bound() );
276
277     BOOST_CHECK_EQUAL( 40u, intervals.back().lower_bound() );
278     BOOST_CHECK_EQUAL( 100u, intervals.back().upper_bound() );
279     BOOST_CHECK_EQUAL( false, intervals.front().changed() );
280     BOOST_CHECK_EQUAL( true, intervals.back().changed() );
281 } // eo SubIntervalsSplit1()
282
283
284 BOOST_AUTO_TEST_CASE(SubIntervalsCutFront)
285 {
286     Intervals intervals;
287
288     intervals.add( Interval(10, 100) );
289     intervals.sub( Interval(10, 20) );
290
291     BOOST_CHECK_EQUAL( false, intervals.empty() );
292     BOOST_CHECK_EQUAL( 1u, intervals.size() );
293
294     BOOST_CHECK_EQUAL( 20u, intervals.front().lower_bound() );
295     BOOST_CHECK_EQUAL( 100u, intervals.front().upper_bound() );
296     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
297 } // eo SubIntervalsCutFront()
298
299
300 BOOST_AUTO_TEST_CASE(SubIntervalsCutBack)
301 {
302     Intervals intervals;
303
304     intervals.add( Interval(10, 100) );
305     intervals.sub( Interval(87, 100) );
306
307     BOOST_CHECK_EQUAL( false, intervals.empty() );
308     BOOST_CHECK_EQUAL( 1u, intervals.size() );
309
310     BOOST_CHECK_EQUAL( 10u, intervals.front().lower_bound() );
311     BOOST_CHECK_EQUAL( 87u, intervals.front().upper_bound() );
312     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
313 } // eo SubIntervalsCutBack()
314
315
316
317 BOOST_AUTO_TEST_CASE(SubIntervalsCutMore)
318 {
319     Intervals intervals;
320
321     intervals.add( Interval( 10, 100) );
322     intervals.add( Interval(110, 200) );
323     intervals.add( Interval(210, 300) );
324
325     // this should remove the first 2 intervals and cut the third:
326     intervals.sub( Interval(8, 220) );
327
328     BOOST_CHECK_EQUAL( false, intervals.empty() );
329     BOOST_CHECK_EQUAL( 1u, intervals.size() );
330
331     BOOST_CHECK_EQUAL( 220u, intervals.front().lower_bound() );
332     BOOST_CHECK_EQUAL( 300u, intervals.front().upper_bound() );
333     BOOST_CHECK_EQUAL( true, intervals.front().changed() );
334 } // eo SubIntervalsCutMore()
335
336
337 BOOST_AUTO_TEST_CASE(IntervalComparisons)
338 {
339     Intervals intervals1;
340     Intervals intervals2;
341
342     intervals1.add( Interval( 10, 120) );
343
344     intervals2.add( Interval( 10, 110 ) );
345     intervals2.add( Interval( 100, 120 ) );
346
347     BOOST_CHECK_EQUAL( 1u, intervals2.size() );
348
349     BOOST_CHECK( intervals1 == intervals2 );
350     BOOST_CHECK_EQUAL( true, intervals1.contains( intervals2 ));
351     BOOST_CHECK_EQUAL( true, intervals2.contains( intervals1 ));
352
353     intervals2.sub( Interval( 40, 50) );
354
355     BOOST_CHECK( intervals1 != intervals2 );
356     BOOST_CHECK_EQUAL( true, intervals1.contains( intervals2 ));
357     BOOST_CHECK_EQUAL( false, intervals2.contains( intervals1 ));
358 } // eo IntervalComparisons()
359
360
361
362 BOOST_AUTO_TEST_CASE(MonotonicClock)
363 {
364     long sec0, nsec0;
365     long sec1, nsec1;
366
367     bool res = monotonic_clock_gettime(sec0,nsec0);
368     BOOST_CHECK_EQUAL( true, res );
369
370     usleep(250000);
371     res= monotonic_clock_gettime(sec1,nsec1);
372     BOOST_CHECK_EQUAL( true, res);
373
374     long delta_sec = sec1 - sec0;
375     long delta_nsec= nsec1 - nsec0;
376
377     long delta_millisec= ( delta_nsec / 1000000L) + delta_sec * 1000L;
378
379     BOOST_CHECK( delta_millisec >= 250 - /*fuzz*/ 1);
380     BOOST_CHECK( delta_millisec < 300 );
381 } // eo MonotonicClock()
382
383 BOOST_AUTO_TEST_CASE(WeekInvalid)
384 {
385     Week week("99999999");
386     BOOST_CHECK_EQUAL(false, week.is_valid());
387     BOOST_CHECK_EQUAL(string(""), week.get_displaystring());
388 }
389
390 BOOST_AUTO_TEST_CASE(WeekDisplayString1)
391 {
392     Week week("");
393     BOOST_CHECK_EQUAL(true, week.is_valid());
394     BOOST_CHECK_EQUAL(string(""), week.get_displaystring());
395 }
396
397 BOOST_AUTO_TEST_CASE(WeekDisplayString2)
398 {
399     Week week("0123456");
400     BOOST_CHECK_EQUAL(true, week.is_valid());
401     BOOST_CHECK_EQUAL(string("Mon-Sun"), week.get_displaystring());
402 }
403
404 BOOST_AUTO_TEST_CASE(WeekDisplayString3)
405 {
406     Week week("123456");
407     BOOST_CHECK_EQUAL(true, week.is_valid());
408     BOOST_CHECK_EQUAL(string("Mon-Sat"), week.get_displaystring());
409 }
410
411 BOOST_AUTO_TEST_CASE(WeekDisplayString4)
412 {
413     Week week("012345");
414     BOOST_CHECK_EQUAL(true, week.is_valid());
415     BOOST_CHECK_EQUAL(string("Mon-Fri, Sun"), week.get_displaystring());
416 }
417
418 BOOST_AUTO_TEST_CASE(WeekDisplayString5)
419 {
420     Week week("1256");
421     BOOST_CHECK_EQUAL(true, week.is_valid());
422     BOOST_CHECK_EQUAL(string("Mon, Tue, Fri, Sat"), week.get_displaystring());
423 }
424
425 BOOST_AUTO_TEST_CASE(WeekDisplayString6)
426 {
427     Week week("0246");
428     BOOST_CHECK_EQUAL(true, week.is_valid());
429     BOOST_CHECK_EQUAL(string("Tue, Thu, Sat, Sun"), week.get_displaystring());
430 }
431
432 BOOST_AUTO_TEST_CASE(WeekDisplayString7)
433 {
434     Week week("135");
435     BOOST_CHECK_EQUAL(true, week.is_valid());
436     BOOST_CHECK_EQUAL(string("Mon, Wed, Fri"), week.get_displaystring());
437 }
438
439 BOOST_AUTO_TEST_CASE(WeekDisplayString8)
440 {
441     Week week("15");
442     BOOST_CHECK_EQUAL(true, week.is_valid());
443     BOOST_CHECK_EQUAL(string("Mon, Fri"), week.get_displaystring());
444 }
445
446 BOOST_AUTO_TEST_CASE(WeekDisplayString9)
447 {
448     Week week("06");
449     BOOST_CHECK_EQUAL(true, week.is_valid());
450     BOOST_CHECK_EQUAL(string("Sat, Sun"), week.get_displaystring());
451 }
452
453 BOOST_AUTO_TEST_CASE(WeekDisplayString10)
454 {
455     Week week("056");
456     BOOST_CHECK_EQUAL(true, week.is_valid());
457     BOOST_CHECK_EQUAL(string("Fri-Sun"), week.get_displaystring());
458 }
459
460 BOOST_AUTO_TEST_CASE(WeekDisplayString11)
461 {
462     Week week("0");
463     BOOST_CHECK_EQUAL(true, week.is_valid());
464     BOOST_CHECK_EQUAL(string("Sun"), week.get_displaystring());
465 }
466
467 BOOST_AUTO_TEST_CASE(WeekDisplayString12)
468 {
469     Week week("6");
470     BOOST_CHECK_EQUAL(true, week.is_valid());
471     BOOST_CHECK_EQUAL(string("Sat"), week.get_displaystring());
472 }
473
474 BOOST_AUTO_TEST_CASE(WeekDisplayString13)
475 {
476     Week week("123");
477     BOOST_CHECK_EQUAL(true, week.is_valid());
478     BOOST_CHECK_EQUAL(string("Mon-Wed"), week.get_displaystring());
479 }
480
481 BOOST_AUTO_TEST_CASE(FormatFullTime)
482 {
483     this->set_tz ("CET");
484     time_t seconds = 1318844005;
485
486     BOOST_CHECK_EQUAL("17.10.2011 11:33", format_full_time(seconds));
487 }
488
489 BOOST_AUTO_TEST_CASE(DateToSeconds1)
490 {
491     this->set_tz ("CET");
492     // no DST
493     BOOST_CHECK_EQUAL(1325372400, date_to_seconds("2012-01-01"));
494 }
495
496 BOOST_AUTO_TEST_CASE(DateToSeconds2)
497 {
498     this->set_tz ("CET");
499     // DST
500     BOOST_CHECK_EQUAL(1341093600, date_to_seconds("2012-07-01"));
501 }
502
503 BOOST_AUTO_TEST_CASE(FormatISO8601_T)
504 {
505     const time_t moment = 1515492684;
506     BOOST_CHECK_EQUAL("10:11:24",
507                       format_iso8601 (moment, true, false, true, false));
508 }
509
510 BOOST_AUTO_TEST_CASE(FormatISO8601_TZ_local)
511 {
512     this->set_tz ("CET");
513     const time_t moment = 1515492684;
514     BOOST_CHECK_EQUAL("11:11:24+0100",
515                       format_iso8601 (moment, false, false, true, true));
516 }
517
518 BOOST_AUTO_TEST_CASE(FormatISO8601_TZ)
519 {
520     const time_t moment = 1515492684;
521     BOOST_CHECK_EQUAL("10:11:24+0000",
522                       format_iso8601 (moment, true, false, true, true));
523 }
524
525 BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_local)
526 {
527     this->set_tz ("CET");
528     const time_t moment = 1515492684;
529     BOOST_CHECK_EQUAL("2018-01-09T11:11:24+0100",
530                       format_iso8601 (moment, false, true, true, true));
531 }
532
533 BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ)
534 {
535     const time_t moment = 1515492684;
536     BOOST_CHECK_EQUAL("2018-01-09T10:11:24+0000",
537                       format_iso8601 (moment, true, true, true, true));
538 }
539
540 BOOST_AUTO_TEST_CASE(FormatISO8601_DT)
541 {
542     const time_t moment = 1515492684;
543     BOOST_CHECK_EQUAL("2018-01-09T10:11:24",
544                       format_iso8601 (moment, true, true, true, false));
545 }
546
547 BOOST_AUTO_TEST_CASE(FormatISO8601_D)
548 {
549     const time_t moment = 1515492684;
550     BOOST_CHECK_EQUAL("2018-01-09",
551                       format_iso8601 (moment, true, true, false, false));
552 }
553
554 BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_struct_tm)
555 {
556     struct tm helau;
557     helau.tm_sec    = 11;
558     helau.tm_min    = 11;
559     helau.tm_hour   = 11;
560     helau.tm_mday   = 11;
561     helau.tm_mon    = 10;
562     helau.tm_year   = 2018 - 1900;
563     helau.tm_wday   = 0;
564     helau.tm_yday   = 315;
565     helau.tm_isdst  = 0;
566     helau.tm_gmtoff = 0;
567     helau.tm_zone   = NULL;
568
569     BOOST_CHECK_EQUAL("2018-11-11T11:11:11+0000",
570                       format_iso8601 (helau, true, true, true));
571 }
572
573 BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ_struct_timespec)
574 {
575     struct timespec ts = { 1541934671, 11 };
576
577     BOOST_CHECK_EQUAL("2018-11-11T11:11:11+0000",
578                       format_iso8601 (ts, true, true, true, true));
579 }
580
581 BOOST_AUTO_TEST_SUITE(Clock)
582
583     BOOST_AUTO_TEST_CASE(ctor_simple)
584     {
585         I2n::clock::Time t;
586
587         BOOST_CHECK_EQUAL(t.get_sec  (), 0);
588         BOOST_CHECK_EQUAL(t.get_nsec (), 0);
589     }
590
591     BOOST_AUTO_TEST_CASE(ctor_type)
592     {
593         I2n::clock::Time t1 (I2n::clock::type::real);
594         I2n::clock::Time t2 (I2n::clock::type::mono);
595         I2n::clock::Time t3 (I2n::clock::type::boot);
596         I2n::clock::Time t4 (I2n::clock::type::cpu);
597
598         BOOST_CHECK_EQUAL(t1.get_sec  (), 0);
599         BOOST_CHECK_EQUAL(t1.get_nsec (), 0);
600
601         BOOST_CHECK_EQUAL(t2.get_sec  (), 0);
602         BOOST_CHECK_EQUAL(t2.get_nsec (), 0);
603
604         BOOST_CHECK_EQUAL(t3.get_sec  (), 0);
605         BOOST_CHECK_EQUAL(t3.get_nsec (), 0);
606
607         BOOST_CHECK_EQUAL(t4.get_sec  (), 0);
608         BOOST_CHECK_EQUAL(t4.get_nsec (), 0);
609     }
610
611     BOOST_AUTO_TEST_CASE(ctor_variant)
612     {
613         I2n::clock::Time tmc (I2n::clock::type::mono);
614         I2n::clock::Time tmr (I2n::clock::type::mono, I2n::clock::type::raw);
615         I2n::clock::Time tme (I2n::clock::type::mono, I2n::clock::type::exact);
616
617         I2n::clock::Time trc (I2n::clock::type::real);
618         I2n::clock::Time tre (I2n::clock::type::real, I2n::clock::type::exact);
619
620         I2n::clock::Time tb (I2n::clock::type::boot);
621
622         I2n::clock::Time tcp (I2n::clock::type::cpu);
623         I2n::clock::Time tct (I2n::clock::type::cpu, I2n::clock::type::thread);
624
625         BOOST_CHECK_EQUAL(tmc.get_sec  (), 0); /* MONO */
626         BOOST_CHECK_EQUAL(tmc.get_nsec (), 0);
627
628         BOOST_CHECK_EQUAL(tmr.get_sec  (), 0);
629         BOOST_CHECK_EQUAL(tmr.get_nsec (), 0);
630
631         BOOST_CHECK_EQUAL(tme.get_sec  (), 0);
632         BOOST_CHECK_EQUAL(tme.get_nsec (), 0);
633
634         BOOST_CHECK_EQUAL(trc.get_sec  (), 0); /* REAL */
635         BOOST_CHECK_EQUAL(trc.get_nsec (), 0);
636
637         BOOST_CHECK_EQUAL(tre.get_sec  (), 0);
638         BOOST_CHECK_EQUAL(tre.get_nsec (), 0);
639
640         BOOST_CHECK_EQUAL(tb.get_sec  (), 0); /* BOOT */
641         BOOST_CHECK_EQUAL(tb.get_nsec (), 0);
642
643         BOOST_CHECK_EQUAL(tcp.get_sec  (), 0); /* CPU */
644         BOOST_CHECK_EQUAL(tcp.get_nsec (), 0);
645
646         BOOST_CHECK_EQUAL(tct.get_sec  (), 0);
647         BOOST_CHECK_EQUAL(tct.get_nsec (), 0);
648     }
649
650     BOOST_AUTO_TEST_CASE(initializer_now)
651     {
652         boost::optional<I2n::clock::Time> t = I2n::clock::now ();
653
654         BOOST_CHECK(t);
655         BOOST_CHECK_GT(t->get_sec (), 0);
656         BOOST_CHECK_EQUAL(t->err, 0);
657     }
658
659     BOOST_AUTO_TEST_CASE(initializer_zero)
660     {
661         I2n::clock::Time stundenull = I2n::clock::zero ();
662
663         BOOST_CHECK_EQUAL(stundenull.get_sec  (), 0);
664         BOOST_CHECK_EQUAL(stundenull.get_nsec (), 0);
665         BOOST_CHECK_EQUAL(stundenull.err, 0);
666     }
667
668     BOOST_AUTO_TEST_CASE(member_set_now)
669     {
670         I2n::clock::Time t;
671
672         BOOST_CHECK(t.set ());
673
674         BOOST_CHECK_NE(t.get_sec (), 0);
675     }
676
677     BOOST_AUTO_TEST_CASE(member_set_value)
678     {
679         I2n::clock::Time t;
680
681         t.set (42, 42);
682
683         BOOST_CHECK_EQUAL(t.get_sec  (), 42);
684         BOOST_CHECK_EQUAL(t.get_nsec (), 42);
685     }
686
687     BOOST_AUTO_TEST_CASE(member_set_value_type)
688     {
689         I2n::clock::Time t;
690
691         t.set (42, 42, I2n::clock::type::real, I2n::clock::type::exact);
692
693         BOOST_CHECK_EQUAL(t.get_sec  (), 42);
694         BOOST_CHECK_EQUAL(t.get_nsec (), 42);
695     }
696
697     BOOST_AUTO_TEST_CASE(member_add_parts)
698     {
699         I2n::clock::Time t;
700
701         t.set (42, 42);
702         t.add (2187, 2187);
703
704         BOOST_CHECK_EQUAL(t.get_sec  (), 2229);
705         BOOST_CHECK_EQUAL(t.get_nsec (), 2229);
706     }
707
708     BOOST_AUTO_TEST_CASE(member_sub_parts)
709     {
710         I2n::clock::Time t;
711
712         t.set (2, 0L);
713         t.subtract (1, 1L);
714
715         BOOST_CHECK_EQUAL(t.get_sec  (), 0);
716         BOOST_CHECK_EQUAL(t.get_nsec (), 999999999);
717     }
718
719     BOOST_AUTO_TEST_CASE(member_sub_Time)
720     {
721         I2n::clock::Time t1;
722         I2n::clock::Time t2;
723
724         t1.set (42, 42L);
725         t2.set (42,  0L);
726
727         t1.subtract (t2);
728
729         BOOST_CHECK_EQUAL(t1.get_sec  (),  0);
730         BOOST_CHECK_EQUAL(t1.get_nsec (), 42L);
731     }
732
733     BOOST_AUTO_TEST_CASE(member_diff)
734     {
735         static const time_t five = 5 * 365 * 24 * 3600;
736
737         I2n::clock::Time t1 (42, 1337);
738         I2n::clock::Time t2 = t1 + five;;
739         I2n::clock::Time t3 = t1 - five;;
740
741         BOOST_CHECK_EQUAL(t2, I2n::clock::Time ((time_t)42 + five, 1337));
742         BOOST_CHECK_EQUAL(t3, I2n::clock::Time ((time_t)42 - five, 1337));
743         BOOST_CHECK_EQUAL(t1.difference (t3), t3.difference (t1));
744         BOOST_CHECK_EQUAL(t3.difference (t3), t3.difference (t3));
745     }
746
747     BOOST_AUTO_TEST_CASE(op_copyassign)
748     {
749         I2n::clock::Time t1;
750         I2n::clock::Time t2;
751
752         BOOST_CHECK(t1.set ());
753
754         t2 = t1;
755
756         BOOST_CHECK_EQUAL(t1.get_sec  (), t2.get_sec  ());
757         BOOST_CHECK_EQUAL(t1.get_nsec (), t2.get_nsec ());
758     }
759
760     BOOST_AUTO_TEST_CASE(op_equal)
761     {
762         I2n::clock::Time t1;
763         I2n::clock::Time t2;
764
765         BOOST_CHECK(t1.set ());
766         t2 = t1;
767
768         BOOST_CHECK_EQUAL(t1, t2);
769     }
770
771     BOOST_AUTO_TEST_CASE(op_add_Time)
772     {
773         I2n::clock::Time t1;
774         I2n::clock::Time t2;
775         I2n::clock::Time tsum;
776
777         t1.set (2187, 2187);
778         t2.set (1337, 1337);
779         tsum = t1 + t2;
780
781         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3524);
782         BOOST_CHECK_EQUAL(tsum.get_nsec (), 3524);
783     }
784
785     BOOST_AUTO_TEST_CASE(op_add_Time_carry)
786     {
787         I2n::clock::Time t1;
788         I2n::clock::Time t2;
789         I2n::clock::Time tsum;
790
791         t1.set (2187, 2187);
792 # if LONG_BIT == 32
793         t2.set (1300,  2L * 1000 * 1000 * 1000 + 1337);
794 # else
795         t2.set (1300, 37L * 1000 * 1000 * 1000 + 1337);
796 # endif
797
798         tsum = t1 + t2;
799
800 # if LONG_BIT == 32
801         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3489);
802         BOOST_CHECK_EQUAL(tsum.get_nsec (), 3524);
803 # else
804         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3524);
805         BOOST_CHECK_EQUAL(tsum.get_nsec (), 3524);
806 # endif
807     }
808
809     BOOST_AUTO_TEST_CASE(op_add_time_t)
810     {
811         I2n::clock::Time t1 (2187, 2187);
812         time_t           t2 = 1337;
813         I2n::clock::Time tsum;
814
815         tsum = t1 + t2;
816
817         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3524);
818         BOOST_CHECK_EQUAL(tsum.get_nsec (), 2187);
819     }
820
821     BOOST_AUTO_TEST_CASE(op_add_time_t_external)
822     {
823         time_t           t1 = 1337;
824         I2n::clock::Time t2 (2187, 2187);
825         I2n::clock::Time tsum;
826
827         tsum = t1 + t2;
828
829         BOOST_CHECK_EQUAL(tsum.get_sec  (), 3524);
830         BOOST_CHECK_EQUAL(tsum.get_nsec (), 2187);
831     }
832
833     BOOST_AUTO_TEST_CASE(op_incr_Time)
834     {
835         I2n::clock::Time t1 (2187, 2187);
836         I2n::clock::Time t2 (1337, 1337);
837
838         t1 += t2;
839
840         BOOST_CHECK_EQUAL(t1.get_sec  (), 3524);
841         BOOST_CHECK_EQUAL(t1.get_nsec (), 3524);
842     }
843
844     BOOST_AUTO_TEST_CASE(op_incr_time_t)
845     {
846         I2n::clock::Time t1 (2187, 2187);
847         time_t           t2 = 1337;
848
849         t1 += t2;
850
851         BOOST_CHECK_EQUAL(t1.get_sec  (), 3524);
852         BOOST_CHECK_EQUAL(t1.get_nsec (), 2187);
853     }
854
855     BOOST_AUTO_TEST_CASE(op_subtract_Time)
856     {
857         I2n::clock::Time t1;
858         I2n::clock::Time t2;
859         I2n::clock::Time tdiff;
860
861         t1.set (2187, 2187);
862         t2.set (1337, 1337);
863         tdiff = t1 - t2;
864
865         BOOST_CHECK_EQUAL(tdiff.get_sec  (), 850);
866         BOOST_CHECK_EQUAL(tdiff.get_nsec (), 850);
867     }
868
869     BOOST_AUTO_TEST_CASE(op_subtract_time_t)
870     {
871         I2n::clock::Time t1 (2187, 2187);
872         time_t           t2 = 1337;
873         I2n::clock::Time tdiff;
874
875         tdiff = t1 - t2;
876
877         BOOST_CHECK_EQUAL(tdiff.get_sec  (), 850);
878         BOOST_CHECK_EQUAL(tdiff.get_nsec (), 2187);
879     }
880
881     BOOST_AUTO_TEST_CASE(op_subtract_time_t_external)
882     {
883         time_t           t1 = 1337;
884         I2n::clock::Time t2 (2187, 2187);
885         I2n::clock::Time tdiff;
886
887         tdiff = t1 - t2;
888
889         BOOST_CHECK_EQUAL(tdiff.get_sec  (), -851);
890         BOOST_CHECK_EQUAL(tdiff.get_nsec (), 999997813);
891     }
892
893     BOOST_AUTO_TEST_CASE(op_decr_Time)
894     {
895         I2n::clock::Time t1 (2187, 2187);
896         I2n::clock::Time t2 (1337, 1337);
897
898         t1 -= t2;
899
900         BOOST_CHECK_EQUAL(t1.get_sec  (), 850);
901         BOOST_CHECK_EQUAL(t1.get_nsec (), 850);
902     }
903
904     BOOST_AUTO_TEST_CASE(op_decr_time_t)
905     {
906         I2n::clock::Time t1 (2187, 2187);
907         time_t           t2 = 1337;
908
909         t1 -= t2;
910
911         BOOST_CHECK_EQUAL(t1.get_sec  (), 850);
912         BOOST_CHECK_EQUAL(t1.get_nsec (), 2187);
913     }
914
915     BOOST_AUTO_TEST_CASE(op_mult_scale)
916     {
917         I2n::clock::Time t1;
918         I2n::clock::Time t2;
919
920         t1.set (1, 1);
921         t2 = t1 * 42;
922
923         BOOST_CHECK_EQUAL(t2.get_sec  (), 42);
924         BOOST_CHECK_EQUAL(t2.get_nsec (), 42);
925     }
926
927     BOOST_AUTO_TEST_CASE(op_mult_mutate)
928     {
929         I2n::clock::Time t1 (  42, 42);
930         I2n::clock::Time t2 (1337,  0);
931
932         t1 *=   2;
933         t2 *= -10;
934
935         BOOST_CHECK_EQUAL(t1.get_sec  (),     84);
936         BOOST_CHECK_EQUAL(t1.get_nsec (),     84);
937         BOOST_CHECK_EQUAL(t2.get_sec  (), -13370);
938     }
939
940     BOOST_AUTO_TEST_CASE(op_mult_scale_carry)
941     {
942         I2n::clock::Time t1;
943         I2n::clock::Time t2;
944
945         t1.set (1, 500 * 1000 * 1000);
946         t2 = t1 * 3;
947
948         BOOST_CHECK_EQUAL(t2.get_sec  (),  4);
949         BOOST_CHECK_EQUAL(t2.get_nsec (),  500 * 1000 * 1000);
950     }
951
952     BOOST_AUTO_TEST_CASE(op_equals)
953     {
954         I2n::clock::Time t1;
955         I2n::clock::Time t2;
956
957         t1.set (50, 50);
958         t2.set (50, 50);
959
960         BOOST_CHECK_EQUAL(t1, t2);
961     }
962
963     BOOST_AUTO_TEST_CASE(compare_equal)
964     {
965         I2n::clock::Time t1;
966         I2n::clock::Time t2;
967
968         t1.set (42, 42);
969         t2.set (42, 42);
970
971         BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), 0);
972     }
973
974     BOOST_AUTO_TEST_CASE(compare_equal_type)
975     {
976         I2n::clock::Time t1 (42, 42, I2n::clock::type::real);
977         I2n::clock::Time t2 (42, 42, I2n::clock::type::cpu);
978         I2n::clock::Time t3 (42,  0, I2n::clock::type::real);
979         I2n::clock::Time t4 (42, 42, I2n::clock::type::real);
980
981         BOOST_CHECK_NE(t1, t2);
982         BOOST_CHECK_NE(t1, t3);
983         BOOST_CHECK_EQUAL(t1, t4);
984     }
985
986     BOOST_AUTO_TEST_CASE(compare_ne_sec)
987     {
988         I2n::clock::Time t1;
989         I2n::clock::Time t2;
990
991         t1.set (  42, 42);
992         t2.set (1337, 42);
993
994         BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), -1);
995         BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1),  1);
996     }
997
998     BOOST_AUTO_TEST_CASE(compare_ne_nsec)
999     {
1000         I2n::clock::Time t1;
1001         I2n::clock::Time t2;
1002
1003         t1.set (42,   42);
1004         t2.set (42, 1337);
1005
1006         BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2), -1);
1007         BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1),  1);
1008     }
1009
1010     BOOST_AUTO_TEST_CASE(compare_ne_both)
1011     {
1012         I2n::clock::Time t1;
1013         I2n::clock::Time t2;
1014
1015         t1.set (42, 2187);
1016         t2.set (23, 1337);
1017
1018         BOOST_CHECK_EQUAL(I2n::clock::compare (t1, t2),  1);
1019         BOOST_CHECK_EQUAL(I2n::clock::compare (t2, t1), -1);
1020     }
1021
1022     BOOST_AUTO_TEST_CASE(op_ineq_sec)
1023     {
1024         I2n::clock::Time t1 (1337);
1025         I2n::clock::Time t2 (2187);
1026
1027         BOOST_CHECK_LT(t1, t2);
1028         BOOST_CHECK_GT(t2, t1);
1029     }
1030
1031     BOOST_AUTO_TEST_CASE(op_ineq_nsec)
1032     {
1033         I2n::clock::Time t1 (1337, 23);
1034         I2n::clock::Time t2 (1337, 42);
1035
1036         BOOST_CHECK_LT(t1, t2);
1037         BOOST_CHECK_GT(t2, t1);
1038     }
1039
1040     BOOST_AUTO_TEST_CASE(op_ineq_both)
1041     {
1042         I2n::clock::Time t1 (2187, 23);
1043         I2n::clock::Time t2 (1337, 42);
1044
1045         BOOST_CHECK_LT(t2, t1);
1046         BOOST_CHECK_GT(t1, t2);
1047     }
1048
1049     BOOST_AUTO_TEST_CASE(op_eq_time_t)
1050     {
1051         boost::optional<I2n::clock::Time> t1  = I2n::clock::now ();
1052         const time_t                      t2  = time (NULL); /* race here */
1053
1054         *t1 -= (time_t)42;
1055
1056         BOOST_CHECK_NE(*t1,  t2);
1057         BOOST_CHECK_LT(*t1,  t2);
1058         BOOST_CHECK_GT( t2, *t1);
1059     }
1060
1061     BOOST_AUTO_TEST_CASE(Format_sec_msec)
1062     {
1063         I2n::clock::Time t1 (42, 42);
1064         I2n::clock::Time t2 ( 4, 242424242);
1065         I2n::clock::Time t3 ( 0, 133713371);
1066         I2n::clock::Time t4 ( 0, 0);
1067
1068         std::string s1 = t1.format_sec_msec ();
1069         std::string s2 = t2.format_sec_msec ();
1070         std::string s3 = t3.format_sec_msec ();
1071         std::string s4 = t4.format_sec_msec ();
1072
1073         BOOST_CHECK_EQUAL("42s 0ms"  , s1);
1074         BOOST_CHECK_EQUAL( "4s 242ms", s2);
1075         BOOST_CHECK_EQUAL( "0s 133ms", s3);
1076         BOOST_CHECK_EQUAL( "0s 0ms"  , s4);
1077     }
1078
1079     BOOST_AUTO_TEST_CASE(Format_min_sec_msec)
1080     {
1081         I2n::clock::Time t1 (42*60 + 42, 42);
1082         I2n::clock::Time t2 ( 4*60 + 42, 242424242);
1083         I2n::clock::Time t3 ( 0*60 + 42, 133713371);
1084         I2n::clock::Time t4 (    0 +  0,  0);
1085
1086         std::string s1 = *t1.format_min_sec_msec ();
1087         std::string s2 = *t2.format_min_sec_msec ();
1088         std::string s3 = *t3.format_min_sec_msec ();
1089         std::string s4 = *t4.format_min_sec_msec ();
1090
1091         BOOST_CHECK_EQUAL("42m42.000s", s1);
1092         BOOST_CHECK_EQUAL( "4m42.242s", s2);
1093         BOOST_CHECK_EQUAL( "0m42.133s", s3);
1094         BOOST_CHECK_EQUAL(  "0m0.000s", s4);
1095     }
1096
1097     BOOST_AUTO_TEST_CASE(FormatISO8601_T)
1098     {
1099         I2n::clock::Time t (42, 42);
1100         boost::optional<std::string> s = t.format_iso8601 (true, false, true, false);
1101
1102         BOOST_CHECK_EQUAL("00:00:42", *s);
1103     }
1104
1105     BOOST_AUTO_TEST_CASE(FormatISO8601_DT)
1106     {
1107         I2n::clock::Time t (1541934671, 0);
1108         boost::optional<std::string> s = t.format_iso8601 (true, true, true, false);
1109
1110         BOOST_CHECK_EQUAL("2018-11-11T11:11:11", *s);
1111     }
1112
1113     BOOST_AUTO_TEST_CASE(FormatISO8601_DTZ)
1114     {
1115         I2n::clock::Time t (1541934671, 0);
1116         boost::optional<std::string> s = t.format_iso8601 (true, true, true, true);
1117
1118         BOOST_CHECK_EQUAL("2018-11-11T11:11:11+0000", *s);
1119     }
1120
1121     BOOST_AUTO_TEST_CASE(Format_make_nice_time)
1122     {
1123         I2n::clock::Time t (111111, 0);
1124         boost::optional<std::string> s = t.make_nice_time ();
1125
1126         BOOST_CHECK_EQUAL("1 day, 06:51:51", *s);
1127     }
1128
1129     BOOST_AUTO_TEST_CASE(Format_format_full_time)
1130     {
1131         I2n::clock::Time t (1541934671, 0);
1132         /*
1133          * brr, the old formatters use localtime without a way to opt out of
1134          * it!
1135          */
1136         this->set_utc ();
1137         boost::optional<std::string> s = t.format_full_time ();
1138
1139         BOOST_CHECK_EQUAL("11.11.2018 11:11", *s);
1140     }
1141
1142     BOOST_AUTO_TEST_CASE(Format_format_date)
1143     {
1144         I2n::clock::Time t (1541934671, 0);
1145         boost::optional<std::string> s = t.format_date ();
1146
1147         BOOST_CHECK_EQUAL("11.11.2018", *s);
1148     }
1149
1150     BOOST_AUTO_TEST_CASE(FromString_iso8601_full)
1151     {
1152         const std::string in1 ("0001-01-01T00:00:00+0000");
1153         const std::string in2 ("2018-11-11T11:11:11+0000");
1154
1155         this->set_utc ();
1156
1157         boost::optional<I2n::clock::Time> t1 = I2n::clock::time_of_iso8601 (in1);
1158         boost::optional<I2n::clock::Time> t2 = I2n::clock::time_of_iso8601 (in2);
1159
1160 # if LONG_BIT == 32
1161         BOOST_CHECK(!t1);
1162 # else
1163         BOOST_CHECK(t1);
1164         BOOST_CHECK_EQUAL(*t1->format_iso8601 (), in1);
1165 # endif
1166
1167         BOOST_CHECK(t2);
1168         BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in2);
1169     }
1170
1171     BOOST_AUTO_TEST_CASE(FromString_iso8601_full_negyear)
1172     {
1173         const std::string in1 ("-0001-01-01T00:00:00+0000");
1174         const std::string in2 ("-2018-11-11T11:11:11+0000");
1175
1176         this->set_utc ();
1177
1178         boost::optional<I2n::clock::Time> t1 = I2n::clock::time_of_iso8601 (in1);
1179         boost::optional<I2n::clock::Time> t2 = I2n::clock::time_of_iso8601 (in2);
1180
1181 # if LONG_BIT == 32
1182         BOOST_CHECK(!t1);
1183         BOOST_CHECK(!t2);
1184 # else
1185         BOOST_CHECK(t1);
1186         BOOST_CHECK(t2);
1187         BOOST_CHECK_EQUAL(*t1->format_iso8601 (), in1);
1188         BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in2);
1189 # endif
1190     }
1191
1192     BOOST_AUTO_TEST_CASE(FromString_iso8601_Z)
1193     {
1194         const std::string in1 ("2019-04-25T13:41:47+0000");
1195         const std::string in2 ("2019-04-25T13:41:47Z");
1196
1197         this->set_utc ();
1198         boost::optional<I2n::clock::Time> t1 = I2n::clock::time_of_iso8601 (in1, true, true, true);
1199         boost::optional<I2n::clock::Time> t2 = I2n::clock::time_of_iso8601 (in2, true, true, true);
1200
1201         BOOST_CHECK(t1);
1202         BOOST_CHECK(t2);
1203
1204         BOOST_CHECK_EQUAL(*t1, *t2);
1205         BOOST_CHECK_EQUAL(*t1->format_iso8601 (), *t2->format_iso8601 ());
1206         BOOST_CHECK_EQUAL(*t2->format_iso8601 (), in1);
1207     }
1208
1209     BOOST_AUTO_TEST_CASE(FromString_iso8601_partial)
1210     {
1211         const std::string in1 ("2018-11-11T11:11:11");
1212         const std::string in2 ("2018-11-11");
1213
1214         this->set_utc ();
1215
1216         boost::optional<I2n::clock::Time> t1 =
1217             I2n::clock::time_of_iso8601 (in1, true, true, false);
1218         boost::optional<I2n::clock::Time> t2 =
1219             I2n::clock::time_of_iso8601 (in2, true, false, false);
1220
1221         BOOST_CHECK(t1);
1222         BOOST_CHECK(t2);
1223         /*
1224          * We test for the difference here which is zero if the number is
1225          * correct but causes the difference from the expected value to be
1226          * printed in case the test fails.
1227          */
1228         BOOST_CHECK_EQUAL(*t1->format_iso8601 (true,  true,  true, false), in1);
1229         BOOST_CHECK_EQUAL(*t2->format_iso8601 (true,  true, false, false), in2);
1230     }
1231
1232     BOOST_AUTO_TEST_CASE(FromString_iso8601_offset)
1233     {
1234         const std::string in1 ("2019-04-25T13:41:47Z");
1235         const std::string in2 ("2019-04-25T13:41:47+0200"); /* = UTC(in1 + 2h) */
1236         const std::string in3 ("2019-04-25T15:41:47+0000"); /* = UTC(in2) */
1237
1238         this->set_utc ();
1239         boost::optional<I2n::clock::Time> t1 = I2n::clock::time_of_iso8601 (in1, true, true, true);
1240         boost::optional<I2n::clock::Time> t2 = I2n::clock::time_of_iso8601 (in2, true, true, true);
1241         boost::optional<I2n::clock::Time> t3 = I2n::clock::time_of_iso8601 (in3, true, true, true);
1242
1243         BOOST_CHECK(t1);
1244         BOOST_CHECK(t2);
1245         BOOST_CHECK(t3);
1246
1247         BOOST_CHECK_EQUAL(*t1->format_iso8601 (), "2019-04-25T13:41:47+0000");
1248         BOOST_CHECK_EQUAL(t1->get_sec (), 1556199707);
1249         BOOST_CHECK_EQUAL(*t2->format_iso8601 (), "2019-04-25T15:41:47+0000");
1250         BOOST_CHECK_EQUAL(t2->get_sec (), t1->get_sec () + 2 * 60 * 60);
1251         BOOST_CHECK_EQUAL(*t2, *t3);
1252         BOOST_CHECK_EQUAL(*t3->format_iso8601 (), "2019-04-25T15:41:47+0000");
1253     }
1254
1255     BOOST_AUTO_TEST_CASE(FromString_iso8601_tzdiff)
1256     {
1257         const std::string in ("2019-04-26T13:45:02+0000");
1258
1259         this->set_tz ("UTC");
1260         boost::optional<I2n::clock::Time> t1 = I2n::clock::time_of_iso8601 (in, true, true, false);
1261
1262         this->set_tz ("CET");
1263         boost::optional<I2n::clock::Time> t2 = I2n::clock::time_of_iso8601 (in, true, true, false);
1264
1265         BOOST_CHECK_EQUAL(*t1->format_iso8601 (true, true, true, true), in);
1266         BOOST_CHECK_EQUAL(*t2->format_iso8601 (true, true, true, true), "2019-04-26T13:45:02+0000");
1267     }
1268
1269     BOOST_AUTO_TEST_CASE(FromString_iso8601_32bit_time_t_err)
1270     {
1271         const std::string timeless ("11:11:11");
1272         boost::optional<I2n::clock::Time> untimely = boost::none;
1273
1274         this->set_utc ();
1275
1276         untimely = I2n::clock::time_of_iso8601 (timeless, false, true, false);
1277
1278 # if LONG_BIT == 32
1279         BOOST_CHECK(!untimely);
1280 # else
1281         BOOST_CHECK(untimely);
1282         BOOST_CHECK_EQUAL(*untimely->format_iso8601 (true, false,  true, false),
1283                           timeless);
1284 # endif
1285     }
1286
1287     BOOST_AUTO_TEST_CASE(Ctor_32bit_time_t_err)
1288     {
1289         boost::optional<std::string> threw = boost::none;
1290
1291         struct tm tm;
1292         memset (&tm, 0, sizeof (tm));
1293
1294         tm.tm_sec    = 11;
1295         tm.tm_min    = 11;
1296         tm.tm_hour   = 11;
1297         tm.tm_mday   = 11;
1298         tm.tm_mon    = 10;
1299         tm.tm_year   = -789;
1300         tm.tm_gmtoff = 0;
1301
1302         try {
1303             I2n::clock::Time untimely (tm);
1304         } catch (I2n::clock::conversion_error &exn) {
1305             threw = std::string (exn);
1306         }
1307
1308
1309 # if LONG_BIT == 32
1310         BOOST_CHECK_EQUAL(*threw,
1311                           "errno=0 [mktime: from struct tm {Sun Nov 11 11:11:11 1111}]");
1312 # else
1313         BOOST_CHECK(!threw);
1314 # endif
1315     }
1316
1317     BOOST_AUTO_TEST_CASE(containers_list)
1318     {
1319         std::list<I2n::clock::Time> ts;
1320
1321         ts.push_back (I2n::clock::zero ());
1322         ts.push_back (I2n::clock::zero ());
1323
1324         BOOST_CHECK_EQUAL(ts.size (), 2);
1325     }
1326
1327     BOOST_AUTO_TEST_CASE(containers_vec)
1328     {
1329         std::vector<I2n::clock::Time> ts;
1330
1331         ts.push_back (I2n::clock::zero ());
1332         ts.push_back (I2n::clock::zero ());
1333
1334         BOOST_CHECK_EQUAL(ts.size (), 2);
1335     }
1336
1337     BOOST_AUTO_TEST_CASE(containers_set)
1338     {
1339         std::set<I2n::clock::Time> ts;
1340
1341         ts.insert (I2n::clock::zero ());
1342         ts.insert (I2n::clock::Time (42, 2187));
1343         ts.insert (I2n::clock::zero ());
1344
1345         BOOST_CHECK_EQUAL(ts.size (), 2);
1346     }
1347
1348     BOOST_AUTO_TEST_CASE(containers_list_mean)
1349     {
1350         std::list<I2n::clock::Time> ts;
1351
1352         ts.push_back (I2n::clock::Time (42, 42));
1353         ts.push_back (I2n::clock::Time (1337, 1337));
1354
1355         BOOST_CHECK_EQUAL(I2n::clock::mean (ts),
1356                           I2n::clock::Time (689, 500000689));
1357     }
1358
1359     BOOST_AUTO_TEST_CASE(containers_list_mean_zero)
1360     {
1361         std::list<I2n::clock::Time> ts;
1362
1363         ts.push_back (I2n::clock::Time (0, 0));
1364         ts.push_back (I2n::clock::Time (0, 0));
1365         ts.push_back (I2n::clock::Time (0, 0));
1366         ts.push_back (I2n::clock::Time (0, 0));
1367
1368         BOOST_CHECK_EQUAL(I2n::clock::mean (ts),
1369                           I2n::clock::zero ());
1370     }
1371
1372     BOOST_AUTO_TEST_CASE(containers_list_mean_empty)
1373     {
1374         std::list<I2n::clock::Time> ts;
1375
1376         BOOST_CHECK_EQUAL(I2n::clock::mean (ts), I2n::clock::Time (0, 0));
1377     }
1378
1379     BOOST_AUTO_TEST_CASE(containers_set_mean)
1380     {
1381         std::set<I2n::clock::Time> ts;
1382
1383         ts.insert (I2n::clock::Time (42));
1384         ts.insert (I2n::clock::Time (1337));
1385         ts.insert (I2n::clock::Time (2187));
1386
1387         BOOST_CHECK_EQUAL(I2n::clock::mean (ts),
1388                           I2n::clock::Time (1188, 666666666));
1389     }
1390
1391     BOOST_AUTO_TEST_CASE(containers_set_median_empty)
1392     {
1393         std::set<I2n::clock::Time> ts;
1394
1395         BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (0, 0));
1396     }
1397
1398     BOOST_AUTO_TEST_CASE(containers_set_median_one)
1399     {
1400         std::set<I2n::clock::Time> ts;
1401
1402         ts.insert (I2n::clock::Time (42, 0));
1403
1404         BOOST_CHECK_EQUAL(I2n::clock::median (ts),
1405                           I2n::clock::Time (42, 0));
1406     }
1407
1408     BOOST_AUTO_TEST_CASE(containers_set_median_multi)
1409     {
1410         std::set<I2n::clock::Time> ts;
1411
1412         ts.insert (I2n::clock::Time (42));
1413         ts.insert (I2n::clock::Time (1337));
1414         ts.insert (I2n::clock::Time (2187));
1415
1416         BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (1337));
1417     }
1418
1419     BOOST_AUTO_TEST_CASE(containers_vec_median_multi)
1420     {
1421         std::vector<I2n::clock::Time> ts;
1422
1423         ts.push_back (I2n::clock::Time (42));
1424         ts.push_back (I2n::clock::Time (1337));
1425         ts.push_back (I2n::clock::Time (2187));
1426
1427         BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (1337));
1428     }
1429
1430     BOOST_AUTO_TEST_CASE(containers_list_median_multi)
1431     {
1432         std::list<I2n::clock::Time> ts;
1433
1434         ts.push_back (I2n::clock::Time (42));
1435         ts.push_back (I2n::clock::Time (1337));
1436         ts.push_back (I2n::clock::Time (2187));
1437         ts.push_back (I2n::clock::Time (0xdead));
1438         ts.push_back (I2n::clock::Time (0xbeef));
1439
1440         BOOST_CHECK_EQUAL(I2n::clock::median (ts),
1441                           I2n::clock::Time (2187));
1442     }
1443
1444     BOOST_AUTO_TEST_CASE(containers_list_median_multi_evensize)
1445     {
1446         std::list<I2n::clock::Time> ts;
1447
1448         ts.push_back (I2n::clock::Time (42));
1449         ts.push_back (I2n::clock::Time (1337));
1450         ts.push_back (I2n::clock::Time (2187));
1451         ts.push_back (I2n::clock::Time (0xf00d));
1452         ts.push_back (I2n::clock::Time (0xfeed));
1453         ts.push_back (I2n::clock::Time (0xdeadf0e));
1454
1455         BOOST_CHECK_EQUAL(I2n::clock::median (ts), I2n::clock::Time (0xf00d));
1456     }
1457
1458 BOOST_AUTO_TEST_SUITE_END() /* [Clock] */
1459
1460 BOOST_AUTO_TEST_SUITE_END()