1 /*  $Id: test_ncbitime.cpp 621326 2020-12-09 19:22:45Z ivanov $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors:  Anton Butanayev, Denis Vakatov, Vladimir Ivanov
27  *
28  * File Description:
29  *   Test for CTime - the standard Date/Time class.
30  *
31  * NOTE:
32  *   The time change dates for Daylight Saving Time in the U.S. and
33  *   Europe are different. Because this test have hardcoded dates, it works
34  *   only on the machines with the same DST standards as in the U.S.
35  *
36  */
37 
38 #include <ncbi_pch.hpp>
39 #include <corelib/ncbitime.hpp>
40 #include <corelib/ncbi_system.hpp>
41 #include <corelib/ncbisys.hpp>
42 #include <stdio.h>
43 #include <stdlib.h>
44 
45 #include <common/test_assert.h>  /* This header must go last */
46 
47 USING_NCBI_SCOPE;
48 
49 
50 // Macro to enable/disable speed tests
51 #define ENABLE_SPEED_TESTS  0
52 
53 // String printout
54 #define STR(t) string("[" + (t).AsString() + "]")
55 
56 #if defined(NCBI_OS_DARWIN)  ||  defined(NCBI_OS_BSD)
57 #  define TIMEZONE_IS_UNDEFINED  1
58 #endif
59 
60 
61 //============================================================================
62 //
63 // TestMisc
64 //
65 //============================================================================
66 
s_TestMisc(void)67 static void s_TestMisc(void)
68 {
69     // Get current time
70     {{
71         CTime t0(CTime::eCurrent);
72         CCurrentTime t1;
73         assert(CTimeSpan(t1-t0).GetAsDouble() <= 1);
74     }}
75 
76     // Month and Day name<->num conversion
77     {{
78         assert(CTime::MonthNameToNum("Jan")              == CTime::eJanuary);
79         assert(CTime::MonthNameToNum("January")          == 1);
80         assert(CTime::MonthNameToNum("JAN")              == CTime::eJanuary);
81         assert(CTime::MonthNameToNum("JANUARY")          == 1);
82         assert(CTime::MonthNameToNum("Dec")              == CTime::eDecember);
83         assert(CTime::MonthNameToNum("December")         == 12);
84         assert(CTime::MonthNumToName(CTime::eJanuary)    == "January");
85         assert(CTime::MonthNumToName(1, CTime::eAbbr)    == "Jan");
86         assert(CTime::MonthNumToName(CTime::eDecember,
87                                      CTime::eFull)       == "December");
88         assert(CTime::MonthNumToName(12,CTime::eAbbr)    == "Dec");
89 
90         assert(CTime::DayOfWeekNameToNum("Sun")          == CTime::eSunday);
91         assert(CTime::DayOfWeekNameToNum("Sunday")       == 0);
92         assert(CTime::DayOfWeekNameToNum("SUN")          == CTime::eSunday);
93         assert(CTime::DayOfWeekNameToNum("SUNDAY")       == 0);
94         assert(CTime::DayOfWeekNameToNum("Sat")          == CTime::eSaturday);
95         assert(CTime::DayOfWeekNameToNum("Saturday")     == 6);
96         assert(CTime::DayOfWeekNumToName(CTime::eSunday) == "Sunday");
97         assert(CTime::DayOfWeekNumToName(0,CTime::eAbbr) == "Sun");
98         assert(CTime::DayOfWeekNumToName(CTime::eSaturday,
99                                        CTime::eFull)     == "Saturday");
100         assert(CTime::DayOfWeekNumToName(6,CTime::eAbbr) == "Sat");
101         try {
102             CTime::MonthNameToNum("Month");
103             _TROUBLE;
104         }
105         catch (CTimeException&) {}
106     }}
107 
108     // String <-> CTime conversion
109     {{
110         {{
111             CTime t;
112             assert(t.AsString() == "");
113         }}
114         {{
115             CTime t(2000, 365 / 2);
116             CTime::SetFormat("M/D/Y h:m:s");
117             assert(t.AsString() == "06/30/2000 00:00:00");
118         }}
119         {{
120             // Year 2000 problem:
121             CTime::SetFormat("M/D/Y");
122             CTime t(1999, 12, 30);
123             t.AddDay();
124             assert(t.AsString() == "12/31/1999");
125             t.AddDay();
126             assert(t.AsString() == "01/01/2000");
127             t.AddDay();
128             assert(t.AsString() == "01/02/2000");
129             t="02/27/2000";
130             t.AddDay();
131             assert(t.AsString() == "02/28/2000");
132             t.AddDay();
133             assert(t.AsString() == "02/29/2000");
134             t.AddDay();
135             assert(t.AsString() == "03/01/2000");
136             t.AddDay();
137             assert(t.AsString() == "03/02/2000");
138         }}
139         {{
140             // String assignment:
141             CTime::SetFormat("M/D/Y h:m:s");
142             try {
143                 CTime t("02/15/2000 01:12:33");
144                 assert(t.AsString() == "02/15/2000 01:12:33");
145                 t = "6/16/2001 02:13:34";
146                 assert(t.AsString() == "06/16/2001 02:13:34");
147             }
148             catch (CTimeException&) {}
149         }}
150     }}
151 
152     // Comparison
153     {{
154         CTime empty;
155         CTime cl(CTime::eCurrent, CTime::eLocal);
156         CTime cg(cl);
157         cg.ToGmtTime();
158 
159         assert( !(empty > empty) );
160         assert( !(empty < empty) );
161         assert(  (empty == empty) );
162         assert( !(empty > cl) );
163         assert(  (empty < cl) );
164         assert( !(empty == cl) );
165         assert( !(empty > cg) );
166         assert(  (empty < cg) );
167         assert( !(empty == cg) );
168         assert(  (cl > empty) );
169         assert( !(cl < empty) );
170         assert( !(cl == empty) );
171         assert(  (cg > empty) );
172         assert( !(cg < empty) );
173         assert( !(cg == empty) );
174         assert( !(cg > cl) );
175         assert( !(cg < cl) );
176         assert(  (cg == cl) );
177         assert( !(cl > cg) );
178         assert( !(cl < cg) );
179         assert(  (cl == cg) );
180     }}
181 
182     // Addition
183     {{
184         CTime::SetFormat("M/D/Y h:m:s.S");
185         {{
186             // Adding Nanoseconds
187             CTime t;
188             for (CTime tmp(1999, 12, 31, 23, 59, 59, 999999995);
189                  tmp <= CTime(2000, 1, 1, 0, 0, 0, 000000003);
190                  t = tmp, tmp.AddNanoSecond(2)) {
191             }
192             assert(t.AsString() == "01/01/2000 00:00:00.000000003");
193         }}
194         {{
195             // Current time with nanoseconds (10 cycles)
196             CTime t;
197             for (int i = 0; i < 10; i++) {
198                  t.SetCurrent();
199             }
200         }}
201 
202         CTime::SetFormat("M/D/Y h:m:s");
203         {{
204             // nAdding seconds
205             CTime t;
206             for (CTime tmp(1999, 12, 31, 23, 59, 5);
207                  tmp <= CTime(2000, 1, 1, 0, 1, 20);
208                  t = tmp, tmp.AddSecond(11)) {
209             }
210             assert(t.AsString() == "01/01/2000 00:01:17");
211         }}
212         {{
213             // Adding minutes
214             for (CTime t(1999, 12, 31, 23, 45);
215                  t <= CTime(2000, 1, 1, 0, 15);
216                  t.AddMinute(11)) {
217             }
218         }}
219         {{
220             // Adding hours
221             for (CTime t(1999, 12, 31);
222                  t <= CTime(2000, 1, 1, 15);
223                  t.AddHour(11)) {
224             }
225         }}
226         {{
227             // Adding months
228             for (CTime t(1998, 12, 29);
229                  t <= CTime(1999, 4, 1);
230                  t.AddMonth()) {
231             }
232         }}
233         {{
234             // Adding time span
235             CTime t0(1999, 12, 31, 23, 59, 5);
236             CTimeSpan ts(1, 2, 3, 4, 555555555);
237 
238             for (int i=0; i<10; i++) {
239                  t0.AddTimeSpan(ts);
240             }
241             assert(t0.AsString() == "01/11/2000 20:29:50");
242 
243             CTime t1;
244             t1 = t0 + ts;
245             assert(t0.AsString() == "01/11/2000 20:29:50");
246             assert(t1.AsString() == "01/12/2000 22:32:55");
247             t1 = ts + t0;
248             assert(t0.AsString() == "01/11/2000 20:29:50");
249             assert(t1.AsString() == "01/12/2000 22:32:55");
250             t1 = t0; t1 += ts;
251             assert(t0.AsString() == "01/11/2000 20:29:50");
252             assert(t1.AsString() == "01/12/2000 22:32:55");
253             t1 = t0 - ts;
254             assert(t0.AsString() == "01/11/2000 20:29:50");
255             assert(t1.AsString() == "01/10/2000 18:26:45");
256             t1 = t0; t1 -= ts;
257             assert(t0.AsString() == "01/11/2000 20:29:50");
258             assert(t1.AsString() == "01/10/2000 18:26:45");
259             ts = t0 - t1;
260             assert(ts.AsString() == "93784.555555555");
261             ts = t1 - t0;
262             assert(ts.AsString() == "-93784.555555555");
263         }}
264     }}
265 
266     // Difference
267     {{
268         CTime t1(2000, 10, 1, 12, 3, 45,1);
269         CTime t2(2000, 10, 2, 14, 55, 1,2);
270         CTimeSpan ts(1,2,51,16,1);
271 
272         assert((t2.DiffDay(t1) - 1.12) < 0.01);
273         assert((t2.DiffHour(t1) - 26.85) < 0.01);
274         assert((t2.DiffMinute(t1) - 1611.27) < 0.01);
275         assert( t2.DiffSecond(t1) ==  96676);
276         assert( t1.DiffSecond(t2) == -96676);
277         assert(NStr::DoubleToString(t2.DiffNanoSecond(t1),0) == "96676000000001");
278         assert(t2.DiffTimeSpan(t1) ==  ts);
279         assert(t1.DiffTimeSpan(t2) == -ts);
280 
281         t1 = t2; // both local times
282         t1.SetTimeZone(CTime::eUTC);
283         ts = CTimeSpan(long(t1.DiffSecond(t2)));
284         assert(ts.GetAsDouble() == double(t2.TimeZoneOffset()));
285     }}
286 
287     // CXX-195
288     {{
289         CTime time1("12/31/2007 20:00", "M/D/Y h:m");
290         CTime time2("1/1/2008 20:00", "M/D/Y h:m");
291         CTime time3("12/31/2007", "M/D/Y");
292         CTime time4("1/1/2008", "M/D/Y");
293         ERR_POST(Note << "time1=" << time1.AsString("M/D/Y h:m:s")
294                       << "  time_t=" << time1.GetTimeT()
295                       << "  time-zone: " << time1.TimeZoneOffset());
296         ERR_POST(Note << "time2=" << time2.AsString("M/D/Y h:m:s")
297                       << "  time_t=" << time2.GetTimeT()
298                       << "  time-zone: " << time2.TimeZoneOffset());
299         assert(time1.TimeZoneOffset() == time2.TimeZoneOffset());
300         ERR_POST(Note << "time3=" << time3.AsString("M/D/Y h:m:s")
301                       << "  time_t=" << time3.GetTimeT()
302                       << "  time-zone: " << time3.TimeZoneOffset());
303         assert(time2.TimeZoneOffset() == time3.TimeZoneOffset());
304         ERR_POST(Note << "time4=" << time4.AsString("M/D/Y h:m:s")
305                       << "  time_t=" << time4.GetTimeT()
306                       << "  time-zone: " << time4.TimeZoneOffset());
307         assert(time3.TimeZoneOffset() == time4.TimeZoneOffset());
308     }}
309 
310     // Database formats conversion
311     {{
312         CTime t1(2000, 1, 1, 1, 1, 1, 10000000);
313         CTime::SetFormat("M/D/Y h:m:s.S");
314 
315         TDBTimeU dbu = t1.GetTimeDBU();
316         assert(dbu.days == 36524);
317         assert(dbu.time == 61);
318         TDBTimeI dbi = t1.GetTimeDBI();
319         assert(dbi.days == 36524);
320         assert(dbi.time == 1098303);
321 
322         CTime t2;
323         t2.SetTimeDBU(dbu);
324         assert(t2.AsString() == "01/01/2000 01:01:00.000000000");
325         t2.SetTimeDBI(dbi);
326         assert(t2.AsString() == "01/01/2000 01:01:01.010000000");
327         CTime::SetFormat("M/D/Y h:m:s");
328         dbi.days = 37093;
329         dbi.time = 12301381;
330         t2.SetTimeDBI(dbi);
331         assert(t2.AsString() == "07/23/2001 11:23:24");
332     }}
333 
334     // Set* functions
335     {{
336         CTime::SetFormat("M/D/Y h:m:s");
337         CTime t(2000, 1, 31);
338 
339         t.SetMonth(2);
340         assert(t.AsString() == "02/29/2000 00:00:00");
341         t.SetYear(2001);
342         assert(t.AsString() == "02/28/2001 00:00:00");
343         t.SetMonth(4);
344         assert(t.AsString() == "04/28/2001 00:00:00");
345         t.SetDay(31);
346         assert(t.AsString() == "04/30/2001 00:00:00");
347         t.SetHour(6);
348         assert(t.AsString() == "04/30/2001 06:00:00");
349         t.SetMinute(37);
350         assert(t.AsString() == "04/30/2001 06:37:00");
351         t.SetSecond(59);
352         assert(t.AsString() == "04/30/2001 06:37:59");
353     }}
354 
355     // Day of week
356     {{
357         CTime t(1900, 1, 1);
358         int i;
359         for (i = 1; t <= CTime(2030, 12, 31); t.AddDay(),i++) {
360             assert(t.DayOfWeek() == (i%7));
361         }
362     }}
363 
364     // Number of days in the month
365     {{
366         CTime t(2000, 1, 31);
367         assert(t.DaysInMonth() == 31);
368         t.SetMonth(2);
369         assert(t.DaysInMonth() == 29);
370         t.SetYear(2001);
371         assert(t.DaysInMonth() == 28);
372         t.SetMonth(4);
373         assert(t.DaysInMonth() == 30);
374     }}
375 
376     // Week number in the year/month
377     {{
378         CTime t(1970, 1, 1);
379         int i;
380         char buf[3];
381 
382         time_t gt = t.GetTimeT();
383 
384         for (i = 1; t <= CTime(2030, 12, 31); i++, t.AddDay(), gt += 24*3600) {
385             struct tm *today = gmtime(&gt);
386             assert(today != 0);
387             int week_num_rtl, week_num, month_week_num;
388 
389             // Sunday-based weeks
390             strftime(buf, sizeof(buf), "%U", today);
391             week_num_rtl   = NStr::StringToInt(buf) + 1;
392             week_num       = t.YearWeekNumber(/*CTime::eSunday*/);
393             assert(week_num_rtl == week_num);
394             month_week_num = t.MonthWeekNumber(/*CTime::eSunday*/);
395             assert(month_week_num >= 1  &&  month_week_num <= 6);
396 
397             // Monday-based weeks
398             strftime(buf, sizeof(buf), "%W", today);
399             week_num_rtl   = NStr::StringToInt(buf) + 1;
400             week_num       = t.YearWeekNumber(CTime::eMonday);
401             assert(week_num_rtl == week_num);
402             month_week_num = t.MonthWeekNumber(CTime::eMonday);
403             assert(month_week_num >= 1  &&  month_week_num <= 6);
404         }
405     }}
406 
407     // Rounding time
408     {{
409         CTime::SetFormat("M/D/Y h:m:s.S");
410 
411         // Round
412         CTime t(2000, 1, 2, 20, 40, 29, 998933833);
413         t.Round(CTime::eRound_Microsecond);
414         assert(t.AsString() == "01/02/2000 20:40:29.998934000");
415         t.Round(CTime::eRound_Millisecond);
416         assert(t.AsString() == "01/02/2000 20:40:29.999000000");
417         t.Round(CTime::eRound_Second);
418         assert(t.AsString() == "01/02/2000 20:40:30.000000000");
419         t.Round(CTime::eRound_Minute);
420         assert(t.AsString() == "01/02/2000 20:41:00.000000000");
421         t.Round(CTime::eRound_Hour);
422         assert(t.AsString() == "01/02/2000 21:00:00.000000000");
423         t.Round(CTime::eRound_Day);
424         assert(t.AsString() == "01/03/2000 00:00:00.000000000");
425 
426         // Round - special case
427         CTime t1(2000, 1, 2, 20, 40, 29, 999999991);
428         t1.Round(CTime::eRound_Microsecond);
429         assert(t1.AsString() == "01/02/2000 20:40:30.000000000");
430 
431         // Truncate
432         CTime t2(2000, 1, 2, 20, 40, 29, 998933833);
433         t2.Truncate(CTime::eRound_Microsecond);
434         assert(t2.AsString() == "01/02/2000 20:40:29.998933000");
435         t2.Truncate(CTime::eRound_Millisecond);
436         assert(t2.AsString() == "01/02/2000 20:40:29.998000000");
437         t2.Truncate(CTime::eRound_Second);
438         assert(t2.AsString() == "01/02/2000 20:40:29.000000000");
439         t2.Truncate(CTime::eRound_Minute);
440         assert(t2.AsString() == "01/02/2000 20:40:00.000000000");
441         t2.Truncate(CTime::eRound_Hour);
442         assert(t2.AsString() == "01/02/2000 20:00:00.000000000");
443         t2.Truncate(CTime::eRound_Day);
444         assert(t2.AsString() == "01/02/2000 00:00:00.000000000");
445     }}
446 }
447 
448 
449 //============================================================================
450 //
451 // TestFormats
452 //
453 //============================================================================
454 
s_TestFormats(void)455 static void s_TestFormats(void)
456 {
457     struct SFormatTest {
458         const char* format;
459         int         truncated;
460     };
461 
462     static const SFormatTest s_Fmt[] = {
463         {"b D Y h:m:s:r",           1},
464         {"b D Y h:m:s:lp",          1},
465         {"b D Y H:m:s P",           1},
466         {"M/D/Y h:m:s",             1},
467         {"M/D/Y h:m:s.S",           0},
468         {"M/D/y h:m:s",             1},
469         {"M/DY  h:m:s",             1},
470         {"M/Dy  h:m:s",             1},
471         {"M/D/Y hm:s",              1},
472         {"M/D/Y h:ms",              1},
473         {"M/D/Y hms",               1},
474         {"MD/y  h:m:s",             1},
475         {"MD/Y  h:m:s",             1},
476         {"MYD   m:h:s",             1},
477         {"M/D/Y smh",               1},
478         {"YMD   h:sm",              1},
479         {"yDM   h:ms",              1},
480         {"yMD   h:ms",              1},
481         {"D B Y h:m:s",             1},
482         {"B d, Y h:m:s",            1},
483         {"D b Y h:m:s",             1},
484 #if !defined(TIMEZONE_IS_UNDEFINED)
485         {"M/D/Y h:m:s z",           1},
486 #endif
487         {"M/D/Y Z h:m:s",           1},
488         {"M/D/Y h:m:G",             0},
489         {"M/D/Y h:m g",             0},
490         {"smhyMD",                  1},
491         {"y||||M++++D   h===ms",    1},
492         {"   yM[][D   h:,.,.,ms  ", 1},
493         {"\tkkkMy++D   h:ms\n",     1},
494         {0,0}
495     };
496 
497     for ( int hour = 0; hour < 24; ++hour ) {
498         for (int i = 0;  s_Fmt[i].format;  i++) {
499             const char* fmt = s_Fmt[i].format;
500 
501             bool is_UTC = (strchr(fmt, 'Z') ||  strchr(fmt, 'z'));
502             CTime t1(2001, 4, 2, hour, 4, 5, 88888888,
503                      is_UTC ? CTime::eUTC : CTime::eLocal);
504 
505             CTime::SetFormat(fmt);
506             string t1_str = t1.AsString();
507             CTime::SetFormat("MDY__s");
508             CTime t2(t1_str, fmt);
509             if ( s_Fmt[i].truncated ) {
510                 string test_str = t2.AsString("M/D/Y h:m:s");
511                 CNcbiOstrstream s;
512                 s << "04/02/2001 " << hour/10 << hour%10 << ":04:05";
513                 string need_str = CNcbiOstrstreamToString(s);
514                 assert(test_str == need_str);
515             } else {
516                 assert(t1 == t2);
517             }
518             CTime::SetFormat(fmt);
519             string t2_str = t2;
520             assert(t1_str.compare(t2_str) == 0);
521             assert(CTime::ValidateString(t1_str, fmt));
522         }
523     }
524 
525     // Check against well-known dates
526     {{
527         const char fmtstr[] = "M/D/Y h:m:s Z W";
528         {{
529             CTime t(2003, 2, 10, 20, 40, 30, 0, CTime::eUTC);
530             t.SetFormat(fmtstr);
531             string s = t.AsString();
532             assert(s.compare("02/10/2003 20:40:30 GMT Monday") == 0);
533         }}
534         {{
535             CTime t(1998, 2, 10, 20, 40, 30, 0, CTime::eUTC);
536             t.SetFormat(fmtstr);
537             string s = t.AsString();
538             assert(s.compare("02/10/1998 20:40:30 GMT Tuesday") == 0);
539         }}
540         {{
541             CTime t(2003, 3, 13, 15, 49, 30, 0, CTime::eUTC);
542             t.SetFormat(fmtstr);
543             string s = t.AsString();
544             assert(s.compare("03/13/2003 15:49:30 GMT Thursday") == 0);
545         }}
546         {{
547             CTime t(2001, 3, 13, 15, 49, 30, 0, CTime::eUTC);
548             t.SetFormat(fmtstr);
549             string s = t.AsString();
550             assert(s.compare("03/13/2001 15:49:30 GMT Tuesday") == 0);
551         }}
552         {{
553             CTime t(2002, 12, 31, 23, 59, 59, 0, CTime::eUTC);
554             t.SetFormat(fmtstr);
555             string s = t.AsString();
556             assert(s.compare("12/31/2002 23:59:59 GMT Tuesday") == 0);
557         }}
558         {{
559             CTime t(2003, 1, 1, 0, 0, 0, 0, CTime::eUTC);
560             t.SetFormat(fmtstr);
561             string s = t.AsString();
562             assert(s.compare("01/01/2003 00:00:00 GMT Wednesday") == 0);
563         }}
564         {{
565             CTime t(2002, 12, 13, 12, 34, 56, 0, CTime::eUTC);
566             t.SetFormat(fmtstr);
567             string s = t.AsString();
568             assert(s.compare("12/13/2002 12:34:56 GMT Friday") == 0);
569         }}
570         {{
571             CTime t(2003, 2, 10, 20, 40, 30, 0, CTime::eUTC);
572             t.SetFormat(CTimeFormat(fmtstr, CTimeFormat::fConf_UTC));
573             string s = t.AsString();
574             assert(s.compare("02/10/2003 20:40:30 UTC Monday") == 0);
575         }}
576     }}
577     {{
578         const char fmtstr[] = "M/D/Y H:m:s P Z W";
579         {{
580             CTime t(2003, 2, 10, 20, 40, 30, 0, CTime::eUTC);
581             t.SetFormat(fmtstr);
582             string s = t.AsString();
583             assert(s.compare("02/10/2003 08:40:30 PM GMT Monday") == 0);
584         }}
585         {{
586             CTime t(1998, 2, 10, 20, 40, 30, 0, CTime::eUTC);
587             t.SetFormat(fmtstr);
588             string s = t.AsString();
589             assert(s.compare("02/10/1998 08:40:30 PM GMT Tuesday") == 0);
590         }}
591         {{
592             CTime t(2003, 3, 13, 15, 49, 30, 0, CTime::eUTC);
593             t.SetFormat(fmtstr);
594             string s = t.AsString();
595             assert(s.compare("03/13/2003 03:49:30 PM GMT Thursday") == 0);
596         }}
597         {{
598             CTime t(2001, 3, 13, 15, 49, 30, 0, CTime::eUTC);
599             t.SetFormat(fmtstr);
600             string s = t.AsString();
601             assert(s.compare("03/13/2001 03:49:30 PM GMT Tuesday") == 0);
602         }}
603         {{
604             CTime t(2002, 12, 31, 23, 59, 59, 0, CTime::eUTC);
605             t.SetFormat(fmtstr);
606             string s = t.AsString();
607             assert(s.compare("12/31/2002 11:59:59 PM GMT Tuesday") == 0);
608         }}
609         {{
610             CTime t(2003, 1, 1, 0, 0, 0, 0, CTime::eUTC);
611             t.SetFormat(fmtstr);
612             string s = t.AsString();
613             assert(s.compare("01/01/2003 12:00:00 AM GMT Wednesday") == 0);
614         }}
615         {{
616             CTime t(2002, 12, 13, 12, 34, 56, 0, CTime::eUTC);
617             t.SetFormat(fmtstr);
618             string s = t.AsString();
619             assert(s.compare("12/13/2002 12:34:56 PM GMT Friday") == 0);
620         }}
621     }}
622     {{
623         const char fmtstr[] = "b d, Y H:m P";
624         {{
625             CTime t(2003, 2, 10, 20, 40, 30, 0, CTime::eUTC);
626             t.SetFormat(fmtstr);
627             string s = t.AsString();
628             assert(s.compare("Feb 10, 2003 08:40 PM") == 0);
629         }}
630         {{
631             CTime t(1998, 2, 10, 20, 40, 30, 0, CTime::eUTC);
632             t.SetFormat(fmtstr);
633             string s = t.AsString();
634             assert(s.compare("Feb 10, 1998 08:40 PM") == 0);
635         }}
636         {{
637             CTime t(2003, 3, 13, 15, 49, 30, 0, CTime::eUTC);
638             t.SetFormat(fmtstr);
639             string s = t.AsString();
640             assert(s.compare("Mar 13, 2003 03:49 PM") == 0);
641         }}
642         {{
643             CTime t(2001, 3, 13, 15, 49, 30, 0, CTime::eUTC);
644             t.SetFormat(fmtstr);
645             string s = t.AsString();
646             assert(s.compare("Mar 13, 2001 03:49 PM") == 0);
647         }}
648         {{
649             CTime t(2002, 12, 31, 23, 59, 59, 0, CTime::eUTC);
650             t.SetFormat(fmtstr);
651             string s = t.AsString();
652             assert(s.compare("Dec 31, 2002 11:59 PM") == 0);
653         }}
654         {{
655             CTime t(2003, 1, 1, 0, 0, 0, 0, CTime::eUTC);
656             t.SetFormat(fmtstr);
657             string s = t.AsString();
658             assert(s.compare("Jan 1, 2003 12:00 AM") == 0);
659         }}
660         {{
661             CTime t(2002, 12, 13, 12, 34, 56, 0, CTime::eUTC);
662             t.SetFormat(fmtstr);
663             string s = t.AsString();
664             assert(s.compare("Dec 13, 2002 12:34 PM") == 0);
665         }}
666     }}
667 
668     // Partially defined time
669     {{
670         string s;
671         {{  // Y
672             CTime t("2001", "Y");
673             s = t.AsString("M/D/Y h:m:s");
674             assert(s.compare("01/01/2001 00:00:00") == 0);
675         }}
676         {{  // Y/M
677             CTime t("2001/2", "Y/M");
678             s = t.AsString("M/D/Y h:m:s");
679             assert(s.compare("02/01/2001 00:00:00") == 0);
680         }}
681         {{  // M/D
682             CTime current(CTime::eCurrent);
683             current.Truncate();
684             CTime t("01/02", "M/D");
685             current.SetMonth(1);
686             current.SetDay(2);
687             assert(t == current);
688         }}
689         {{  // M
690             CTime current(CTime::eCurrent);
691             current.Truncate();
692             CTime t("2", "M");
693             current.SetMonth(2);
694             current.SetDay(1);
695             assert(t == current);
696         }}
697         {{  // D time
698             CTime current(CTime::eCurrent);
699             current.Truncate();
700             CTime t("2 11:22", "D h:m");
701             current.SetDay(2);
702             current.SetHour(11);
703             current.SetMinute(22);
704             assert(t == current);
705         }}
706         {{  // D
707             CTime current(CTime::eCurrent);
708             current.Truncate();
709             CTime t("2", "D");
710             current.SetDay(2);
711             assert(t == current);
712         }}
713         {{  // time
714             CTime current(CTime::eCurrent);
715             CTime t("11:22", "h:m");
716             current.SetHour(11);
717             current.SetMinute(22);
718             current.SetSecond(0);
719             current.SetNanoSecond(0);
720             assert(t == current);
721         }}
722 
723         try {
724             CTime t("2001/2 00:00", "Y/M h:m");
725             _TROUBLE; // day is not defined
726             t.Clear();
727         }
728         catch (CTimeException&) {}
729 
730         try {
731             CTime t("2001/2 00:00", "Y/D h:m");
732             _TROUBLE; // month is not defined
733             t.Clear();
734         }
735         catch (CTimeException&) {}
736 
737         try {
738             CTime t("2001/2", "Y/D");
739             _TROUBLE; // month is not defined
740             t.Clear();
741         }
742         catch (CTimeException&) {}
743 
744         try {
745             CTime t("2001 00:00", "Y h:m");
746             _TROUBLE; // month and day are not defined
747             t.Clear();
748         }
749         catch (CTimeException&) {}
750 
751         try {
752             CTime t("2 00:00", "M h:m");
753             _TROUBLE; // year and day are not defined
754             t.Clear();
755         }
756         catch (CTimeException&) {}
757     }}
758 
759     // Strict/weak time assignment from a string
760     {{
761         string s;
762         {{
763             CTime t("2001", CTimeFormat("Y/M/D", CTimeFormat::fMatch_ShortTime));
764             s = t.AsString("M/D/Y h:m:s");
765             assert(s.compare("01/01/2001 00:00:00") == 0);
766         }}
767         {{
768             // Note that day and month changed
769             CTime t("2001/01/02", CTimeFormat("Y", CTimeFormat::fMatch_ShortFormat));
770             s = t.AsString("M/D/Y h:m:s");
771             assert(s.compare("01/01/2001 00:00:00") == 0);
772         }}
773         {{
774             CTime t("2001", CTimeFormat("Y/M/D", CTimeFormat::fMatch_Weak));
775             s = t.AsString("M/D/Y h:m:s");
776             assert(s.compare("01/01/2001 00:00:00") == 0);
777         }}
778         {{
779             try {
780                 CTime t("2001...", CTimeFormat("Y/M/D", CTimeFormat::fMatch_Weak));
781                 s = t.AsString("M/D/Y h:m:s");
782                 assert(s.compare("01/01/2001 00:00:00") == 0);
783             }
784             catch (CTimeException&) {}
785         }}
786         {{
787             try {
788                 CTime t("2001/01/02", CTimeFormat("Y...", CTimeFormat::fMatch_Weak));
789                 s = t.AsString("M/D/Y h:m:s");
790                 assert(s.compare("01/01/2001 00:00:00") == 0);
791             }
792             catch (CTimeException&) {}
793         }}
794         // Check that strict matching is by default.
795         {{
796             try {
797                 CTime t("2001", "Y/M/D");
798                 _TROUBLE;  // by default used strict format matching
799                 t.Clear();
800             }
801             catch (CTimeException&) {}
802             try {
803                 CTime t("2001/01/02", "Y");
804                 _TROUBLE;  // by default used strict format matching
805                 t.Clear();
806             }
807             catch (CTimeException&) {}
808         }}
809     }}
810 
811     // Observing spaces by default. Make sure that:
812     //  - if fields in the format string are separated by one or more
813     //    white spaces, then the fields in the parsed string also must
814     //    be separated by one or more spaces;
815     //  - if fields in the format string are adjacent, then the fields
816     //    in the parsed string also must be adjacent.
817     //
818     // fMatch_IgnoreSpaces changes default behavior to backward-compatible.
819     //
820     // JIRA: CXX-5422
821     {{
822         CTimeFormat::EFlags ign = (CTimeFormat::EFlags)(CTimeFormat::fDefault |
823                                                         CTimeFormat::fMatch_IgnoreSpaces);
824 
825         // default flags
826         assert(  CTime::ValidateString("01/01/2001",     CTimeFormat("M/D/Y")   ));
827         assert(! CTime::ValidateString("01/01/2001   ",  CTimeFormat("M/D/Y")   ));
828         assert(  CTime::ValidateString("01/01/2001   ",  CTimeFormat("M/D/Y ")  ));
829         assert(  CTime::ValidateString("01012001",       CTimeFormat("MDY")     ));
830         assert( !CTime::ValidateString("01 01 2001",     CTimeFormat("MDY")     ));
831         assert(  CTime::ValidateString("01 01 2001",     CTimeFormat("M D Y")   ));
832         assert( !CTime::ValidateString(" 01 01 2001",    CTimeFormat("M D Y")   ));
833         assert( !CTime::ValidateString("01 01 2001 ",    CTimeFormat("M D Y")   ));
834         assert(  CTime::ValidateString("01  01  2001",   CTimeFormat("M D Y")   ));
835         assert( !CTime::ValidateString("01  01  2001  ", CTimeFormat("M D Y")   ));
836         assert(  CTime::ValidateString("01\n01\t2001",   CTimeFormat("M D Y")   ));
837         assert(  CTime::ValidateString("01\n  01\t2001", CTimeFormat("M D Y")   ));
838         assert(  CTime::ValidateString("01  01  2001  ", CTimeFormat("M D Y ")  ));
839         assert(  CTime::ValidateString("01  01  2001  ", CTimeFormat("M D Y  ") ));
840         assert(  CTime::ValidateString(" 0101 2001",     CTimeFormat(" MD Y")   ));
841         assert(  CTime::ValidateString("   0101 2001",   CTimeFormat(" MD Y")   ));
842         assert( !CTime::ValidateString("   0101 2001  ", CTimeFormat("MDY")     ));
843         assert( !CTime::ValidateString("01/01/2001\n\n", CTimeFormat("M/D/Y")   ));
844         assert(  CTime::ValidateString("01/01/2001\n\n", CTimeFormat("M/D/Y ")  ));
845 
846         // "short" flags
847         assert(  CTime::ValidateString("01/01/2001\n\n", CTimeFormat("M/D/Y",
848                                                          CTimeFormat::fMatch_ShortFormat)));
849         assert(  CTime::ValidateString("01/01/2001",     CTimeFormat("M/D/Y ",
850                                                          CTimeFormat::fMatch_ShortTime)));
851         // fMatch_IgnoreSpaces -- all valid
852         assert(  CTime::ValidateString("01/01/2001",     CTimeFormat("M/D/Y",  ign) ));
853         assert(  CTime::ValidateString("01/01/2001   ",  CTimeFormat("M/D/Y",  ign) ));
854         assert(  CTime::ValidateString("01/01/2001   ",  CTimeFormat("M/D/Y ", ign) ));
855         assert(  CTime::ValidateString("01012001",       CTimeFormat("MDY",    ign) ));
856         assert(  CTime::ValidateString("01 01 2001",     CTimeFormat("MDY",    ign) ));
857         assert(  CTime::ValidateString("01 01 2001",     CTimeFormat("M D Y",  ign) ));
858         assert(  CTime::ValidateString(" 01 01 2001",    CTimeFormat("M D Y",  ign) ));
859         assert(  CTime::ValidateString("01 01 2001 ",    CTimeFormat("M D Y",  ign) ));
860         assert(  CTime::ValidateString("01  01  2001",   CTimeFormat("M D Y",  ign) ));
861         assert(  CTime::ValidateString("01  01  2001  ", CTimeFormat("M D Y",  ign) ));
862         assert(  CTime::ValidateString("01\n01\t2001",   CTimeFormat("M D Y",  ign) ));
863         assert(  CTime::ValidateString("01\n  01\t2001", CTimeFormat("M D Y",  ign) ));
864         assert(  CTime::ValidateString("01  01  2001  ", CTimeFormat("M D Y ", ign) ));
865         assert(  CTime::ValidateString("01  01  2001  ", CTimeFormat("M D Y  ",ign) ));
866         assert(  CTime::ValidateString(" 0101 2001",     CTimeFormat(" MD Y",  ign) ));
867         assert(  CTime::ValidateString("   0101 2001",   CTimeFormat(" MD Y",  ign) ));
868         assert(  CTime::ValidateString("   0101 2001  ", CTimeFormat("MDY",    ign) ));
869         assert(  CTime::ValidateString("01/01/2001\n\n", CTimeFormat("M/D/Y",  ign) ));
870         assert(  CTime::ValidateString("01/01/2001\n\n", CTimeFormat("M/D/Y ", ign) ));
871     }}
872 
873     // SetFormat/AsString with flag parameter test
874     {{
875         CTime t(2003, 2, 10, 20, 40, 30, 0, CTime::eUTC);
876         string s;
877         s = t.AsString("M/D/Y h:m:s");
878         assert(s.compare("02/10/2003 20:40:30") == 0);
879         s = t.AsString("MDY $M/$D/$Y $h:$m:$s hms");
880         assert(s.compare("02102003 $02/$10/$2003 $20:$40:$30 204030") == 0);
881         s = t.AsString(CTimeFormat("MDY $M/$D/$Y $h:$m:$s hms", CTimeFormat::eNcbi));
882         assert(s.compare("MDY 02/10/2003 20:40:30 hms") == 0);
883         s = t.AsString(CTimeFormat("$YY $MM $dd $hh $mm $ss", CTimeFormat::eNcbi));
884         assert(s.compare("2003Y 02M 10d 20h 40m 30s") == 0);
885     }}
886 
887     // CTimeFormat::GetPredefined() test
888     {{
889         CTime t(2003, 2, 10, 20, 40, 30, 123, CTime::eUTC);
890         string s;
891         s = t.AsString(CTimeFormat::GetPredefined(CTimeFormat::eISO8601_Year));
892         assert(s.compare("2003") == 0);
893         s = t.AsString(CTimeFormat::GetPredefined(CTimeFormat::eISO8601_YearMonth));
894         assert(s.compare("2003-02") == 0);
895         s = t.AsString(CTimeFormat::GetPredefined(CTimeFormat::eISO8601_Date));
896         assert(s.compare("2003-02-10") == 0);
897         s = t.AsString(CTimeFormat::GetPredefined(CTimeFormat::eISO8601_DateTimeMin));
898         assert(s.compare("2003-02-10T20:40") == 0);
899         s = t.AsString(CTimeFormat::GetPredefined(CTimeFormat::eISO8601_DateTimeSec));
900         assert(s.compare("2003-02-10T20:40:30") == 0);
901         s = t.AsString(CTimeFormat::GetPredefined(CTimeFormat::eISO8601_DateTimeFrac));
902         assert(s.compare("2003-02-10T20:40:30.000000123") == 0);
903     }}
904     // CTimeFormat::GetPredefined( eISO8601_DateTimeFrac ) test
905     {{
906         CTime t(2003, 2, 10, 20, 40, 3, 0, CTime::eLocal);
907         CTimeFormat fmt = CTimeFormat::GetPredefined(CTimeFormat::eISO8601_DateTimeFrac);
908         t.SetNanoSecond(0);
909         assert(t.AsString(fmt) == "2003-02-10T20:40:03.0");
910         t.SetNanoSecond(2);
911         assert(t.AsString(fmt) == "2003-02-10T20:40:03.000000002");
912         t.SetNanoSecond(1234);
913         assert(t.AsString(fmt) == "2003-02-10T20:40:03.000001234");
914         t.SetNanoSecond(123456789);
915         assert(t.AsString(fmt) == "2003-02-10T20:40:03.123456789");
916         t.SetNanoSecond(123000);
917         assert(t.AsString(fmt) == "2003-02-10T20:40:03.000123");
918         t.SetNanoSecond(123000000);
919         assert(t.AsString(fmt) == "2003-02-10T20:40:03.123");
920     }}
921 
922     // Test assignment operator in different (from default) time format
923     {{
924         CTime t0(2003, 2, 10, 20, 40, 30, 0, CTime::eLocal);
925         CTime::SetFormat(CTimeFormat::GetPredefined(
926                                 CTimeFormat::eISO8601_DateTimeMin,
927                                 CTimeFormat::eNcbi));
928         assert(t0.AsString() == "2003-02-10T20:40");
929         CTime t("2003-02-10T20:40");
930         t.SetSecond(30);
931         assert(t == t0);
932     }}
933 
934     // Formats with floating numbers of seconds ("g", "G")
935     {{
936         CTime t;
937         {{
938             t.SetFormat("g");
939             t = "3";
940             assert(t.AsString()      == "3.0");
941             assert(t.AsString("s.S") == "03.000000000");
942             t = "3.45";
943             assert(t.AsString()      == "3.45");
944             assert(t.AsString("s.S") == "03.450000000");
945             // long string with ignored symbols after 9th digit.
946             t = "3.123456789123456";
947             assert(t.AsString()      == "3.123456789");
948             assert(t.AsString("s.S") == "03.123456789");
949         }}
950         {{
951             t.SetFormat("G");
952             t = "3";
953             assert(t.AsString()      == "03.0");
954             assert(t.AsString("s.S") == "03.000000000");
955             t = "3.45";
956             assert(t.AsString()      == "03.45");
957             assert(t.AsString("s.S") == "03.450000000");
958             // long string with ignored symbols after 9th digit.
959             t = "3.123456789123456";
960             assert(t.AsString()      == "03.123456789");
961             assert(t.AsString("s.S") == "03.123456789");
962         }}
963     }}
964 
965     // AM/PM time parsing
966     {{
967         CTime t;
968         t.SetFormat("Y-M-D H:m P");
969         string fmtout = "Y-M-D h:m";
970         t = "2001-01-01 12:00 AM";  assert(t.AsString(fmtout) == "2001-01-01 00:00");
971         t = "2001-01-01 12:01 AM";  assert(t.AsString(fmtout) == "2001-01-01 00:01");
972         t = "2001-01-01 01:00 AM";  assert(t.AsString(fmtout) == "2001-01-01 01:00");
973         t = "2001-01-01 11:00 AM";  assert(t.AsString(fmtout) == "2001-01-01 11:00");
974         t = "2001-01-01 11:59 AM";  assert(t.AsString(fmtout) == "2001-01-01 11:59");
975         t = "2001-01-01 12:00 PM";  assert(t.AsString(fmtout) == "2001-01-01 12:00");
976         t = "2001-01-01 12:01 PM";  assert(t.AsString(fmtout) == "2001-01-01 12:01");
977         t = "2001-01-01 01:00 PM";  assert(t.AsString(fmtout) == "2001-01-01 13:00");
978         t = "2001-01-01 11:00 PM";  assert(t.AsString(fmtout) == "2001-01-01 23:00");
979         t = "2001-01-01 11:59 PM";  assert(t.AsString(fmtout) == "2001-01-01 23:59");
980     }}
981 }
982 
983 
984 //============================================================================
985 //
986 // Test UTC/GMT
987 //
988 //============================================================================
989 
s_TestUTC(void)990 static void s_TestUTC(void)
991 {
992     //------------------------------------------------------------------------
993     // Local/universal times
994     {{
995         CTime::SetFormat("M/D/Y h:m:s Z");
996         CTime t1(2001, 3, 12, 11, 22, 33, 999, CTime::eUTC);
997         assert(t1.AsString() == "03/12/2001 11:22:33 GMT");
998         CTime t2(2001, 3, 12, 11, 22, 33, 999, CTime::eLocal);
999         assert(t2.AsString() == "03/12/2001 11:22:33 ");
1000 
1001         CTime::SetFormat(CTimeFormat("M/D/Y h:m:s Z", CTimeFormat::fConf_UTC));
1002         CTime t3(2001, 3, 12, 11, 22, 33, 999, CTime::eUTC);
1003         assert(t1.AsString() == "03/12/2001 11:22:33 UTC");
1004 
1005         // Current time
1006         CTime        tl(CTime::eCurrent, CTime::eLocal);
1007         CTime        tu(CTime::eCurrent, CTime::eUTC);
1008         CCurrentTime cl(CTime::eLocal);
1009         CCurrentTime cu(CTime::eUTC);
1010     }}
1011     //------------------------------------------------------------------------
1012     // Process timezone string
1013     {{
1014         CTime t;
1015         t.SetFormat("M/D/Y h:m:s Z");
1016         t = "03/12/2001 11:22:33 UTC";
1017         assert(t.AsString() == "03/12/2001 11:22:33 GMT");
1018         t = "03/12/2001 11:22:33 GMT";
1019         assert(t.AsString() == "03/12/2001 11:22:33 GMT");
1020         t = "03/12/2001 11:22:33 Z";
1021         assert(t.AsString() == "03/12/2001 11:22:33 GMT");
1022         t = "03/12/2001 11:22:33 ";
1023         assert(t.AsString() == "03/12/2001 11:22:33 ");
1024     }}
1025     //------------------------------------------------------------------------
1026     // Day of week
1027     {{
1028         CTime t(2001, 4, 1);
1029         t.SetFormat("M/D/Y h:m:s w");
1030         int i;
1031         for (i = 0; t <= CTime(2001, 4, 10); t.AddDay(),i++) {
1032             assert(t.DayOfWeek() == (i%7));
1033         }
1034     }}
1035     //------------------------------------------------------------------------
1036     // Test GetTimeT
1037     {{
1038 
1039         time_t timer = time(0);
1040         CTime tgmt(CTime::eCurrent, CTime::eUTC,   CTime::eTZPrecisionDefault);
1041         CTime tloc(CTime::eCurrent, CTime::eLocal, CTime::eTZPrecisionDefault);
1042         CTime t(timer);
1043         // Set the same time to all time objects
1044         tgmt.SetTimeT(timer);
1045         tloc.SetTimeT(timer);
1046 
1047         time_t g_ = tgmt.GetTimeT();
1048         time_t l_ = tloc.GetTimeT();
1049         time_t t_ = t.GetTimeT();
1050 
1051         ERR_POST(Note << STR(t));
1052         ERR_POST(Note << NStr::Int8ToString(g_/3600) + " - " +
1053                          NStr::Int8ToString(l_/3600) + " - " +
1054                          NStr::Int8ToString(t_/3600) + " - " +
1055                          NStr::Int8ToString(timer/3600) + "\n");
1056 
1057         assert(timer == t_);
1058         assert(timer == g_);
1059         // On the day of changing to summer/winter time, the local time
1060         // converted to UTC may differ from the value returned by time(0),
1061         // because in the common case API don't know is DST in effect for
1062         // specified local time or not (see mktime()).
1063         if (timer != l_) {
1064             if ( abs((int)(timer - l_)) > 3600 )
1065                 assert(timer == l_);
1066         }
1067 
1068         CTime t11(2013, 3, 10, 1, 59, 0, 0, CTime::eLocal, CTime::eHour);
1069         CTime t12(2013, 3, 10, 3,  0, 0, 0, CTime::eLocal, CTime::eHour);
1070         assert(t12.GetTimeT()/3600 - t11.GetTimeT()/3600 == 1);
1071 
1072         CTime t21(2013, 11, 3, 0, 59, 0, 0, CTime::eLocal, CTime::eHour);
1073         CTime t22(2013, 11, 3, 2,  0, 0, 0, CTime::eLocal, CTime::eHour);
1074         assert(t22.GetTimeT()/3600 - t21.GetTimeT()/3600 == 3);
1075 
1076         // Check for underlying implementations not based on time_t (Win/Unix).
1077         // Results should be close, but not necessary equal,
1078         // and even 'timer' can be greater than 'now'.
1079         // On Linux this behavior is due to the implementation of timekeeping
1080         // in the kernel. Note: time() is called after gettimeofday()
1081         // (GetCurrentTimeT()) on Unix.
1082         t.GetCurrentTimeT(&timer);
1083         time_t now = time(0);
1084         if (timer < now) {
1085             assert(now - timer < 3);
1086         } else {
1087             assert(timer - now < 3);
1088         }
1089     }}
1090 
1091     //------------------------------------------------------------------------
1092     // Test GetTimeTM
1093     {{
1094         CTime tloc(CTime::eCurrent, CTime::eLocal, CTime::eTZPrecisionDefault);
1095         struct tm l_ = tloc.GetTimeTM();
1096         CTime tmp(CTime::eCurrent, CTime::eUTC, CTime::eTZPrecisionDefault);
1097         assert(tmp.GetTimeZone() == CTime::eUTC);
1098         tmp.SetTimeTM(l_);
1099         assert(tmp.GetTimeZone() == CTime::eLocal);
1100         assert(tloc.AsString() == tmp.AsString());
1101 
1102         CTime tgmt(tloc.GetTimeT());
1103         struct tm g_ = tgmt.GetTimeTM();
1104         tmp.SetTimeTM(g_);
1105         assert(tmp.GetTimeZone() == CTime::eLocal);
1106         assert(tgmt.AsString() != tloc.AsString());
1107     }}
1108     //------------------------------------------------------------------------
1109     // Test TimeZoneOffset (1) -- EST timezone only
1110     {{
1111         CTime tw(2001, 1, 1, 12);
1112         CTime ts(2001, 6, 1, 12);
1113         assert(tw.TimeZoneOffset() / 3600 == -5);
1114         assert(ts.TimeZoneOffset() / 3600 == -4);
1115         tw.SetFormat("M/D/Y");
1116         for (; tw < ts; tw.AddDay()) {
1117             if ((tw.TimeZoneOffset() / 3600) == -4) {
1118                 ERR_POST(Note << "First daylight saving day = " + STR(tw));
1119                 break;
1120             }
1121         }
1122     }}
1123     //------------------------------------------------------------------------
1124     // Test TimeZoneOffset (2) -- EST timezone only
1125     {{
1126         CTime tw(2001, 6, 1, 12);
1127         CTime ts(2002, 1, 1, 12);
1128         assert(tw.TimeZoneOffset() / 3600 == -4);
1129         assert(ts.TimeZoneOffset() / 3600 == -5);
1130         tw.SetFormat("M/D/Y");
1131         for (; tw < ts; tw.AddDay()) {
1132             if ((tw.TimeZoneOffset() / 3600) == -5) {
1133                 ERR_POST(Note << "First non daylight saving day = " + STR(tw));
1134                 break;
1135 
1136             }
1137         }
1138     }}
1139     //------------------------------------------------------------------------
1140     // Test AdjusyTime -- EST timezone only
1141     {{
1142         CTime::SetFormat("M/D/Y h:m:s");
1143         CTime t("03/11/2007 01:01:00");
1144         CTime tn;
1145         t.SetTimeZonePrecision(CTime::eTZPrecisionDefault);
1146 
1147         t.SetTimeZone(CTime::eUTC);
1148         tn = t;
1149         tn.AddDay(5);
1150         assert(tn.AsString() == "03/16/2007 01:01:00");
1151         tn = t;
1152         tn.AddDay(40);
1153         assert(tn.AsString() == "04/20/2007 01:01:00");
1154 
1155         t.SetTimeZone(CTime::eLocal);
1156         t.SetTimeZonePrecision(CTime::eNone);
1157         tn = t;
1158         tn.AddDay(5);
1159         assert(tn.AsString() == "03/16/2007 01:01:00");
1160         tn = t;
1161         tn.AddDay(40);
1162         assert(tn.AsString() == "04/20/2007 01:01:00");
1163 
1164         t.SetTimeZonePrecision(CTime::eMonth);
1165         tn = t;
1166         tn.AddDay(5);
1167         tn = t;
1168         tn.AddMonth(-1);
1169         assert(tn.AsString() == "02/11/2007 01:01:00");
1170         tn = t;
1171         tn.AddMonth(+1);
1172         assert(tn.AsString() == "04/11/2007 02:01:00");
1173 
1174         t.SetTimeZonePrecision(CTime::eDay);
1175         tn = t;
1176         tn.AddDay(-1);
1177         assert(tn.AsString() == "03/10/2007 01:01:00");
1178         tn.AddDay();
1179         assert(tn.AsString() == "03/11/2007 01:01:00");
1180         tn = t;
1181         tn.AddDay();
1182         assert(tn.AsString() == "03/12/2007 02:01:00");
1183 
1184         t.SetTimeZonePrecision(CTime::eHour);
1185         tn = t;
1186         tn.AddHour(-3);
1187         CTime te = t;
1188         te.AddHour(3);
1189         assert(tn.AsString() == "03/10/2007 22:01:00");
1190         assert(te.AsString() == "03/11/2007 05:01:00");
1191         CTime th = tn;
1192         th.AddHour(49);
1193         assert(th.AsString() == "03/13/2007 00:01:00");
1194 
1195         tn = "11/04/2007 00:01:00";
1196         tn.SetTimeZonePrecision(CTime::eHour);
1197         te = tn;
1198         tn.AddHour(-3);
1199         te.AddHour(9);
1200         assert(tn.AsString() == "11/03/2007 21:01:00");
1201         assert(te.AsString() == "11/04/2007 08:01:00");
1202         th = tn;
1203         th.AddHour(49);
1204         assert(th.AsString() == "11/05/2007 21:01:00");
1205 
1206         tn = "11/04/2007 09:01:00";
1207         tn.SetTimeZonePrecision(CTime::eHour);
1208         te = tn;
1209         tn.AddHour(-10);
1210         te.AddHour(+10);
1211         assert(tn.AsString() == "11/04/2007 00:01:00");
1212         assert(te.AsString() == "11/04/2007 19:01:00");
1213     }}
1214 }
1215 
1216 
1217 //============================================================================
1218 //
1219 // TestUTCSpeed
1220 //
1221 //============================================================================
1222 
1223 #if ENABLE_SPEED_TESTS
1224 
s_TestUTCSpeedRun(string comment,CTime::ETimeZone tz,CTime::ETimeZonePrecision tzp)1225 static void s_TestUTCSpeedRun(string comment, CTime::ETimeZone tz,
1226                               CTime::ETimeZonePrecision tzp)
1227 {
1228     CTime t(CTime::eCurrent, tz, tzp);
1229     CStopWatch timer;
1230 
1231 #if defined    NCBI_OS_MSWIN
1232     const long kCount=100000L;
1233 #elif defined  NCBI_OS_UNIX
1234     const long kCount=10000L;
1235 #else
1236     const long kCount=100000L;
1237 #endif
1238 
1239     t.SetFormat("M/D/Y h:m:s");
1240     t = "03/31/2001 00:00:00";
1241 
1242     timer.Start();
1243     for (long i = 0; i < kCount; i++) {
1244         t.AddMinute();
1245     }
1246     ERR_POST(Note << comment + ", duration = " + NStr::DoubleToString(timer.Elapsed()) + " sec.");
1247 }
1248 
s_TestUTCSpeed(void)1249 static void s_TestUTCSpeed(void)
1250 {
1251     s_TestUTCSpeedRun("eLocal - eMinute", CTime::eLocal, CTime::eMinute);
1252     s_TestUTCSpeedRun("eLocal - eHour  ", CTime::eLocal, CTime::eHour);
1253     s_TestUTCSpeedRun("eLocal - eMonth ", CTime::eLocal, CTime::eMonth);
1254     s_TestUTCSpeedRun("eLocal - eNone  ", CTime::eLocal, CTime::eNone);
1255     s_TestUTCSpeedRun("eUTC   - eNone  ", CTime::eUTC,   CTime::eNone);
1256 }
1257 
1258 #endif
1259 
1260 //============================================================================
1261 //
1262 // TestTimeSpan
1263 //
1264 //============================================================================
1265 
s_TestTimeSpan(void)1266 static void s_TestTimeSpan(void)
1267 {
1268     // Common constructors
1269     {{
1270         CTimeSpan t1(0,0,0,1,-2);
1271         assert(t1.AsString() == "0.999999998");
1272         CTimeSpan t2(0,0,0,-1,2);
1273         assert(t2.AsString() == "-0.999999998");
1274         CTimeSpan t3(0,0,0,0,-2);
1275         assert(t3.AsString() == "-0.000000002");
1276         CTimeSpan t4(0,0,0,0,2);
1277         assert(t4.AsString() == "0.000000002");
1278     }}
1279     {{
1280         CTimeSpan t1(2,3,4,5,6);
1281         assert(t1.GetCompleteHours()   == 51);
1282         assert(t1.GetCompleteMinutes() == (51*60+4));
1283         assert(t1.GetCompleteSeconds() == ((51*60+4)*60+5));
1284         assert(t1.GetNanoSecondsAfterSecond() == 6);
1285         assert(t1.AsString() == "183845.000000006");
1286 
1287         CTimeSpan t2(-2,-3,-4,-5,-6);
1288         assert(t2.GetCompleteHours()   == -51);
1289         assert(t2.GetCompleteMinutes() == -(51*60+4));
1290         assert(t2.GetCompleteSeconds() == -((51*60+4)*60+5));
1291         assert(t2.GetNanoSecondsAfterSecond() == -6);
1292         assert(t2.AsString() == "-183845.000000006");
1293 
1294         CTimeSpan t3(-2,+3,-4,-5,+6);
1295         assert(t3.GetCompleteHours()   == -45);
1296         assert(t3.GetCompleteMinutes() == -(45*60+4));
1297         assert(t3.GetCompleteSeconds() == -((45*60+4)*60+4));
1298         assert(t3.GetNanoSecondsAfterSecond() == -999999994);
1299         assert(t3.AsString() == "-162244.999999994");
1300     }}
1301 
1302     // Comparison
1303     {{
1304         CTimeSpan t0;
1305         CTimeSpan t1(123.4);
1306         CTimeSpan t2(123.45);
1307         CTimeSpan t3(123.4);
1308 
1309         assert(t0.GetSign() == eZero);
1310         assert(t1.GetSign() == ePositive);
1311         assert(t0 == CTimeSpan(0,0,0,0,0));
1312         assert(t1 != t2);
1313         assert(t1 == t3);
1314         assert(t1 <  t2);
1315         assert(t2 >  t1);
1316         assert(t1 <= t2);
1317         assert(t2 >= t2);
1318     }}
1319 
1320     // Assignment
1321     {{
1322         CTimeSpan t1(-123.4);
1323         CTimeSpan t2(123.45);
1324 
1325         t1 = t2;
1326         assert(t1 == t2);
1327         t1 = "-123.450000000";
1328         assert(t1 == -t2);
1329     }}
1330 
1331     // Arithmetics
1332     {{
1333         // This case test defaut behavior -- SetFormat() never used before!
1334         // and "-G" is format by default to init from strings in this case.
1335         {{
1336             CTimeSpan t;
1337             t = CTimeSpan("100.3") - CTimeSpan("123.4");
1338             assert(t == CTimeSpan("-23.1"));
1339             t = CTimeSpan("63.7")  + CTimeSpan("2.3");
1340             assert(t == CTimeSpan("66"));
1341             t = CTimeSpan("63.7")  - CTimeSpan("72.6");
1342             assert(t == CTimeSpan("-8.9"));
1343 
1344             t = "-123.4";
1345             t += CTimeSpan("1.0");
1346             assert(t == CTimeSpan("-122.4"));
1347             t += CTimeSpan("222.4");
1348             assert(t == CTimeSpan("100.0") );
1349             t -= CTimeSpan("50.1");
1350             assert(t == CTimeSpan("49.9"));
1351             t += CTimeSpan("0.1");
1352             assert(t == CTimeSpan("50.0"));
1353             t += CTimeSpan("3.7");
1354             assert(t == CTimeSpan("53.7"));
1355             t -= CTimeSpan("3.8");
1356             assert(t == CTimeSpan("49.9"));
1357         }}
1358         // And now the same with another format "-S.n".
1359         {{
1360             CTimeSpan::SetFormat("-S.n");
1361             CTimeSpan t;
1362             t = CTimeSpan("100.3") - CTimeSpan("123.4");
1363             assert(t == CTimeSpan("-23.1"));
1364             t = CTimeSpan("63.7")  + CTimeSpan("2.3");
1365             assert(t == CTimeSpan("65.10"));
1366             t = CTimeSpan("63.7")  - CTimeSpan("72.6");
1367             assert(t == CTimeSpan("-8.999999999"));
1368 
1369             t = "-123.4";
1370             t += CTimeSpan("1.0");
1371             assert(t == CTimeSpan("-122.4"));
1372             t += CTimeSpan("222.4");
1373             assert(t == CTimeSpan("100.0") );
1374             t -= CTimeSpan("50.1");
1375             assert(t == CTimeSpan("49.999999999"));
1376             t += CTimeSpan("0.1");
1377             assert(t == CTimeSpan("50.0"));
1378             t += CTimeSpan("3.7");
1379             assert(t == CTimeSpan("53.7"));
1380             t -= CTimeSpan("3.8");
1381             assert(t == CTimeSpan("49.999999999"));
1382         }}
1383     }}
1384 
1385     // Formats with floating numbers of seconds ("g", "G")
1386     {{
1387         CTimeSpan t;
1388         {{
1389             t.SetFormat("g");
1390             t = "123";
1391             assert(t.AsString()      == "3.0");
1392             assert(t.AsString("s.n") == "03.000000000");
1393             t = "123.45";
1394             assert(t.AsString()      == "3.45");
1395             assert(t.AsString("s.n") == "03.450000000");
1396             // long string with ignored symbols after 9th digit.
1397             t = "123.123456789123456";
1398             assert(t.AsString()      == "3.123456789");
1399             assert(t.AsString("s.n") == "03.123456789");
1400         }}
1401         {{
1402             t.SetFormat("G");
1403             t = "123";
1404             assert(t.AsString()      == "123.0");
1405             assert(t.AsString("S.n") == "123.000000000");
1406             t = "123.45";
1407             assert(t.AsString()      == "123.45");
1408             assert(t.AsString("S.n") == "123.450000000");
1409             // long string with ignored symbols after 9th digit.
1410             t = "123.123456789123456";
1411             assert(t.AsString()      == "123.123456789");
1412             assert(t.AsString("S.n") == "123.123456789");
1413         }}
1414     }}
1415 
1416     // Formats
1417     {{
1418         static const char* s_Fmt[] = {
1419             "d h:m:s.n",
1420             "H m:s",
1421             "S",
1422             "H",
1423             "M",
1424             "d",
1425             "G",
1426             "g",
1427             "-d h:m:s.n",
1428             "-H m:s",
1429             "-S",
1430             "-H",
1431             "-M",
1432             "-d",
1433             "-G",
1434             "-g",
1435             0
1436         };
1437 
1438         for (const char** fmt = s_Fmt;  *fmt;  fmt++) {
1439             CTimeSpan t1(-123456789.987654321);
1440             CTimeSpan::SetFormat(*fmt);
1441             string t1_str = t1.AsString();
1442             CTimeSpan::SetFormat("_s_");
1443             CTimeSpan t2(t1_str, *fmt);
1444             CTimeSpan::SetFormat(*fmt);
1445             string t2_str = t2;
1446             assert(t1_str.compare(t2_str) == 0);
1447         }
1448     }}
1449 
1450     // SetFormat/AsString with flag parameter test
1451     {{
1452         CTimeSpan t(123.456);
1453         string s;
1454         s = t.AsString("S.n");
1455         assert(s.compare("123.456000000") == 0);
1456         s = t.AsString("$S.$n");
1457         assert(s.compare("$123.$456000000") == 0);
1458         s = t.AsString(CTimeFormat("$S.$n", CTimeFormat::eNcbi));
1459         assert(s.compare("123.456000000") == 0);
1460         s = t.AsString(CTimeFormat("$mm $ss", CTimeFormat::eNcbi));
1461         assert(s.compare("02m 03s") == 0);
1462     }}
1463 }
1464 
1465 
1466 
1467 //============================================================================
1468 //
1469 // TestTimeSpan -- AssignFromSmartString()
1470 // Cases not covered by converting strings produced by AsSmartString().
1471 //
1472 //============================================================================
1473 
s_TestTimeSpan_AssignFromSmartString(void)1474 static void s_TestTimeSpan_AssignFromSmartString(void)
1475 {
1476     struct STest {
1477         const char* str;
1478         CTimeSpan   result;
1479     };
1480 
1481     static const STest s_Test[] = {
1482         { "",                CTimeSpan()              },
1483         { " ",               CTimeSpan()              },
1484         { "\t",              CTimeSpan()              },
1485         { "\t ",             CTimeSpan()              },
1486         { "1s",              CTimeSpan(0,  0,  0,  1) },
1487         { "44s",             CTimeSpan(0,  0,  0, 44) },
1488         { "35m",             CTimeSpan(0,  0, 35,  0) },
1489         { "1d 13h 35m 44s",  CTimeSpan(1, 13, 35, 44) },
1490         { "1d13h35m44s",     CTimeSpan(1, 13, 35, 44) },
1491         { "13h 35m 44s",     CTimeSpan(0, 13, 35, 44) },
1492         { "35m 44s",         CTimeSpan(0,  0, 35, 44) },
1493         { "1d 13h 35m",      CTimeSpan(1, 13, 35,  0) },
1494         { "13h 35m",         CTimeSpan(0, 13, 35,  0) },
1495         { "1d 44s",          CTimeSpan(1,  0,  0, 44) },
1496         { "1d 13h",          CTimeSpan(1, 13,  0,  0) },
1497         { "1d 35m 44s",      CTimeSpan(1,  0, 35, 44) },
1498         { "1 day 35m 3.4s",  CTimeSpan(1,  0, 35,  3, 400000000) },
1499         { "1d 35m 44s 3ms",  CTimeSpan(1,  0, 35, 44,   3000000) },
1500         { "2mo 13h",         CTimeSpan(2*(long)kAverageSecondsPerMonth + 13*3600L, 0) },
1501         { "2y 1 nanosecond", CTimeSpan(2*(long)kAverageSecondsPerYear, 1) },
1502 
1503         // fractional values
1504         { "0.2ns",           CTimeSpan(0,  0,  0,  0,         0) },   // fraction of ns - rounding
1505         { "1.2ns",           CTimeSpan(0,  0,  0,  0,         1) },   // fraction of ns - rounding
1506         { "1.6ns",           CTimeSpan(0,  0,  0,  0,         2) },   // fraction of ns - rounding
1507         { "1.2ms",           CTimeSpan(0,  0,  0,  0,   1200000) },
1508         { "1.2us",           CTimeSpan(0,  0,  0,  0,      1200) },
1509         { "1.2s",            CTimeSpan(0,  0,  0,  1, 200000000) },
1510         { "1.003s",          CTimeSpan(0,  0,  0,  1,   3000000) },
1511         { "1.000004s",       CTimeSpan(0,  0,  0,  1,      4000) },
1512         { "1.000000005s",    CTimeSpan(0,  0,  0,  1,         5) },
1513         { "0.000000001s",    CTimeSpan(0,  0,  0,  0,         1) },
1514         { "1.s",             CTimeSpan(0,  0,  0,  1) },
1515         { "1.5m",            CTimeSpan(0,  0,  0, 90) },
1516         { "1.2h",            CTimeSpan(0,  1, 12,  0) },
1517         { "1.25h",           CTimeSpan(0,  1, 15,  0) },
1518         { "2.3d",            CTimeSpan(  2,  7, 12, 0) },  // 24*2 + 7.2 hours
1519         { "1.2mo",           CTimeSpan((long)kAverageSecondsPerMonth*12/10) },
1520         { "1.5mo 1.8d",      CTimeSpan((long)kAverageSecondsPerMonth*15/10 + 43*3600L + 12*60L) },  // 1.8d = 1d + 19.2h = 43h 12m
1521         { "1.2y",            CTimeSpan((long)kAverageSecondsPerYear*12/10) },
1522         { "2.3y",            CTimeSpan((long)kAverageSecondsPerYear*23/10) },
1523         { "1y 3.2s",         CTimeSpan((long)kAverageSecondsPerYear + 3, 200000000) },
1524         { " 1y3.2s ",        CTimeSpan((long)kAverageSecondsPerYear + 3, 200000000) },
1525 
1526         // stopper
1527         { NULL, CTimeSpan() }
1528     };
1529 
1530     CTimeSpan ts;
1531 
1532     for (int i = 0; s_Test[i].str;  i++) {
1533         ts.AssignFromSmartString(s_Test[i].str);
1534 #if 1
1535         assert(ts == s_Test[i].result);
1536 #else
1537         if (ts != s_Test[i].result) {
1538             cout << i << ".  " << s_Test[i].str << " != " << s_Test[i].result.AsString() << endl;
1539         }
1540 #endif
1541     }
1542 
1543     // Tests that throw exceptions
1544     static const STest s_Test_Ex[] = {
1545         { "1",        CTimeSpan() },   // no time specifier
1546         { "s",        CTimeSpan() },   // no value
1547         { "2k",       CTimeSpan() },   // unknown specifier
1548         { "1d 2d",    CTimeSpan() },   // repetitions not allowed
1549         { "1day 2d",  CTimeSpan() },   // repetitions not allowed
1550         { "1.2s 3ns", CTimeSpan() },   // implicit repetitions not allowed
1551         { "1..2s",    CTimeSpan() },   // double ..
1552         // stopper
1553         { NULL,       CTimeSpan() }
1554     };
1555     for (int i = 0; s_Test_Ex[i].str; i++) {
1556         try {
1557             ts.AssignFromSmartString(s_Test_Ex[i].str);
1558             _TROUBLE;
1559         }
1560         catch (CTimeException&) {}
1561     }
1562 }
1563 
1564 
1565 
1566 //============================================================================
1567 //
1568 // TestTimeSpan -- AsSmartString()
1569 //
1570 //============================================================================
1571 
s_TestTimeSpan_AsSmartString(void)1572 static void s_TestTimeSpan_AsSmartString(void)
1573 {
1574     typedef CTimeSpan TS;
1575     struct STest {
1576         TS                    timespan;
1577         TS::TSmartStringFlags flags;
1578         const char*           res_full;
1579         const char*           res_short;
1580     };
1581 
1582     //  Shorten some common flags combinations
1583     TS::TSmartStringFlags fTN = TS::fSS_Trunc | TS::fSS_NoSkipZero;
1584     TS::TSmartStringFlags fTS = TS::fSS_Trunc | TS::fSS_SkipZero;
1585     TS::TSmartStringFlags fRN = TS::fSS_Round | TS::fSS_NoSkipZero;
1586     TS::TSmartStringFlags fRS = TS::fSS_Round | TS::fSS_SkipZero;
1587 
1588     static const STest s_Test[] = {
1589 
1590         // Smart mode for timespans < 1 min (CXX-4101)
1591         { TS( 0,          0), fTS, "0 seconds",         "0s"     },
1592         { TS( 1,          0), fTS, "1 second",          "1s"     },
1593         { TS( 1,    1000000), fTS, "1 second",          "1s"     },
1594         { TS( 0,        999), fTS, "999 nanoseconds",   "999ns"  },
1595         { TS( 0,       1000), fTS, "1 microsecond",     "1us"    },
1596         { TS( 0,    1000000), fTS, "1 millisecond",     "1ms"    },
1597         { TS( 0,  100000000), fTS, "100 milliseconds",  "100ms"  },
1598         { TS( 0, 1000000001), fTS, "1 second",          "1s"     },
1599         { TS(59,  900000000), fTS, "59.9 seconds",      "59.9s"  },
1600         { TS(12,   41000000), fTS, "12 seconds",        "12s"    },
1601         { TS(12,  341000000), fTS, "12.3 seconds",      "12.3s"  },
1602         { TS( 1,  234100000), fTS, "1.23 seconds",      "1.23s"  },
1603         { TS( 0,  123410000), fTS, "123 milliseconds",  "123ms"  },
1604         { TS( 0,   12341000), fTS, "12.3 milliseconds", "12.3ms" },
1605         { TS( 0,    1234100), fTS, "1.23 milliseconds", "1.23ms" },
1606         { TS( 0,     123410), fTS, "123 microseconds",  "123us"  },
1607         { TS( 0,      12341), fTS, "12.3 microseconds", "12.3us" },
1608         { TS( 0,       1234), fTS, "1.23 microseconds", "1.23us" },
1609         { TS( 0,        123), fTS, "123 nanoseconds",   "123ns"  },
1610         { TS( 0,         12), fTS, "12 nanoseconds",    "12ns"   },
1611         { TS( 0,  999000000), fTS, "999 milliseconds",  "999ms"  },
1612         { TS( 0,  999500000), fTS, "999 milliseconds",  "999ms"  },
1613         { TS( 0,     999000), fTS, "999 microseconds",  "999us"  },
1614         { TS( 0,     999500), fTS, "999 microseconds",  "999us"  },
1615 
1616         { TS( 0,          0), fRS, "0 seconds",         "0s"     },
1617         { TS( 1,          0), fRS, "1 second",          "1s"     },
1618         { TS( 1,    1000000), fRS, "1 second",          "1s"     },
1619         { TS( 0,        999), fRS, "999 nanoseconds",   "999ns"  },
1620         { TS( 0,       1000), fRS, "1 microsecond",     "1us"    },
1621         { TS( 0,    1000000), fRS, "1 millisecond",     "1ms"    },
1622         { TS( 0,  100000000), fRS, "100 milliseconds",  "100ms"  },
1623         { TS( 0, 1000000001), fRS, "1 second",          "1s"     },
1624         { TS(59,  940000000), fRS, "59.9 seconds",      "59.9s"  },
1625         { TS(59,  950000000), fRS, "1 minute",          "1m"     },
1626         { TS(12,   50000000), fRS, "12.1 seconds",      "12.1s"  },
1627         { TS(12,  341000000), fRS, "12.3 seconds",      "12.3s"  },
1628         { TS(12,  351000000), fRS, "12.4 seconds",      "12.4s"  },
1629         { TS( 1,  234100000), fRS, "1.23 seconds",      "1.23s"  },
1630         { TS( 1,  235100000), fRS, "1.24 seconds",      "1.24s"  },
1631         { TS( 0,  123410000), fRS, "123 milliseconds",  "123ms"  },
1632         { TS( 0,  123510000), fRS, "124 milliseconds",  "124ms"  },
1633         { TS( 0,   12341000), fRS, "12.3 milliseconds", "12.3ms" },
1634         { TS( 0,    1234100), fRS, "1.23 milliseconds", "1.23ms" },
1635         { TS( 0,     123410), fRS, "123 microseconds",  "123us"  },
1636         { TS( 0,      12341), fRS, "12.3 microseconds", "12.3us" },
1637         { TS( 0,       1234), fRS, "1.23 microseconds", "1.23us" },
1638         { TS( 0,        123), fRS, "123 nanoseconds",   "123ns"  },
1639         { TS( 0,         12), fRS, "12 nanoseconds",    "12ns"   },
1640         { TS( 0,  999000000), fRS, "999 milliseconds",  "999ms"  },
1641         { TS( 0,  999500000), fRS, "1 second",          "1s"     },
1642         { TS( 0,     999000), fRS, "999 microseconds",  "999us"  },
1643         { TS( 0,     999500), fRS, "1 millisecond",     "1ms"    },
1644 
1645         // Smart mode for timespans >= 1 min
1646         { TS(   60,         0), fTS, "1 minute",              "1m"      },
1647         { TS(   61,         0), fTS, "1 minute 1 second",     "1m 1s"   },
1648         { TS(  119, 900000000), fTS, "1 minute 59 seconds",   "1m 59s"  },
1649         { TS(  600,         0), fTS, "10 minutes",            "10m"     },
1650         { TS(  629,         0), fTS, "10 minutes 29 seconds", "10m 29s" },
1651         { TS( 3599, 900000000), fTS, "59 minutes 59 seconds", "59m 59s" },
1652         { TS( 3600,         0), fTS, "1 hour",                "1h"      },
1653         { TS(36000,         0), fTS, "10 hours",              "10h"     },
1654         { TS(36059,         0), fTS, "10 hours",              "10h"     },
1655         { TS(86400,         0), fTS, "1 day",                 "1d"      },
1656 
1657         { TS(   60,         0), fRS, "1 minute",              "1m"      },
1658         { TS(   61,         0), fRS, "1 minute 1 second",     "1m 1s"   },
1659         { TS(  119, 900000000), fRS, "2 minutes",             "2m"      },
1660         { TS(  600,         0), fRS, "10 minutes",            "10m"     },
1661         { TS(  629,         0), fRS, "10 minutes 29 seconds", "10m 29s" },
1662         { TS( 3599, 900000000), fRS, "1 hour",                "1h"      },
1663         { TS( 3600,         0), fRS, "1 hour",                "1h"      },
1664         { TS(36000,         0), fRS, "10 hours",              "10h"     },
1665         { TS(36059,         0), fRS, "10 hours 1 minute",     "10h 1m"  },
1666         { TS(86400,         0), fRS, "1 day",                 "1d"      },
1667 
1668         { TS(29,23,59,1,0),                    fTS,  "29 days 23 hours", "29d 23h" },
1669         { TS(29,23,59,1,0),                    fRS,  "30 days",          "30d"     },
1670         { TS((long)kAverageSecondsPerMonth-1), fTS,  "30 days 10 hours", "30d 10h" },
1671         { TS((long)kAverageSecondsPerMonth-1), fRS,  "1 month",          "1mo"     },
1672         { TS((long)kAverageSecondsPerMonth),   fTS,  "1 month",          "1mo"     },
1673         { TS((long)kAverageSecondsPerMonth),   fRS,  "1 month",          "1mo"     },
1674         { TS((long)kAverageSecondsPerMonth+1), fTS,  "1 month",          "1mo" },
1675         { TS((long)kAverageSecondsPerMonth+1), fRS,  "1 month",          "1mo" },
1676         { TS(559,0,59,41,900500),              fTS,  "1 year 6 months",  "1y 6mo"  },
1677         { TS(559,0,59,41,900500),              fRS,  "1 year 6 months",  "1y 6mo"  },
1678 
1679 
1680         // zero time span
1681         { TS(0,0), fTN | TS::fSS_Year,        "0 years",   "0y"  },
1682         { TS(0,0), fTN | TS::fSS_Month,       "0 months",  "0mo" },
1683         { TS(0,0), fTN | TS::fSS_Day,         "0 days",    "0d"  },
1684         { TS(0,0), fTN | TS::fSS_Minute,      "0 minutes", "0m"  },
1685         { TS(0,0), fTN | TS::fSS_Second,      "0 seconds", "0s"  },
1686         { TS(0,0), fTN | TS::fSS_Millisecond, "0 seconds", "0s"  },
1687         { TS(0,0), fTN | TS::fSS_Microsecond, "0 seconds", "0s"  },
1688         { TS(0,0), fTN | TS::fSS_Nanosecond,  "0 seconds", "0s"  },
1689         { TS(0,0), fTN | TS::fSS_Precision1,  "0 seconds", "0s"  },
1690         { TS(0,0), fTN | TS::fSS_Precision2,  "0 seconds", "0s"  },
1691         { TS(0,0), fTN | TS::fSS_Precision3,  "0 seconds", "0s"  },
1692         { TS(0,0), fTN | TS::fSS_Precision4,  "0 seconds", "0s"  },
1693         { TS(0,0), fTN | TS::fSS_Precision5,  "0 seconds", "0s"  },
1694         { TS(0,0), fTN | TS::fSS_Precision6,  "0 seconds", "0s"  },
1695         { TS(0,0), fTN | TS::fSS_Precision7,  "0 seconds", "0s"  },
1696         { TS(0,0), fTS | TS::fSS_Year,        "0 years",   "0y"  },
1697         { TS(0,0), fTS | TS::fSS_Month,       "0 months",  "0mo" },
1698         { TS(0,0), fTS | TS::fSS_Day,         "0 days",    "0d"  },
1699         { TS(0,0), fTS | TS::fSS_Minute,      "0 minutes", "0m"  },
1700         { TS(0,0), fTS | TS::fSS_Second,      "0 seconds", "0s"  },
1701         { TS(0,0), fTS | TS::fSS_Millisecond, "0 seconds", "0s"  },
1702         { TS(0,0), fTS | TS::fSS_Microsecond, "0 seconds", "0s"  },
1703         { TS(0,0), fTS | TS::fSS_Nanosecond,  "0 seconds", "0s"  },
1704         { TS(0,0), fTS | TS::fSS_Precision1,  "0 seconds", "0s"  },
1705         { TS(0,0), fTS | TS::fSS_Precision2,  "0 seconds", "0s"  },
1706         { TS(0,0), fTS | TS::fSS_Precision3,  "0 seconds", "0s"  },
1707         { TS(0,0), fTS | TS::fSS_Precision4,  "0 seconds", "0s"  },
1708         { TS(0,0), fTS | TS::fSS_Precision5,  "0 seconds", "0s"  },
1709         { TS(0,0), fTS | TS::fSS_Precision6,  "0 seconds", "0s"  },
1710         { TS(0,0), fTS | TS::fSS_Precision7,  "0 seconds", "0s"  },
1711 
1712         // 1 second
1713         { TS(1,0), fTN | TS::fSS_Year,        "0 years",   "0y"  },
1714         { TS(1,0), fTN | TS::fSS_Month,       "0 months",  "0mo" },
1715         { TS(1,0), fTN | TS::fSS_Day,         "0 days",    "0d"  },
1716         { TS(1,0), fTN | TS::fSS_Minute,      "0 minutes", "0m"  },
1717         { TS(1,0), fTN | TS::fSS_Second,      "1 second",  "1s"  },
1718         { TS(1,0), fTN | TS::fSS_Millisecond, "1 second",  "1s"  },
1719         { TS(1,0), fTN | TS::fSS_Microsecond, "1 second",  "1s"  },
1720         { TS(1,0), fTN | TS::fSS_Nanosecond,  "1 second",  "1s"  },
1721         { TS(1,0), fTN | TS::fSS_Precision1,  "1 second",  "1s"  },
1722         { TS(1,0), fTN | TS::fSS_Precision2,  "1 second",  "1s"  },
1723         { TS(1,0), fTN | TS::fSS_Precision3,  "1 second",  "1s"  },
1724         { TS(1,0), fTN | TS::fSS_Precision4,  "1 second",  "1s"  },
1725         { TS(1,0), fTN | TS::fSS_Precision5,  "1 second",  "1s"  },
1726         { TS(1,0), fTN | TS::fSS_Precision6,  "1 second",  "1s"  },
1727         { TS(1,0), fTN | TS::fSS_Precision7,  "1 second",  "1s"  },
1728         { TS(1,0), fTN | TS::fSS_Year,        "0 years",   "0y"  },
1729         { TS(1,0), fTS | TS::fSS_Month,       "0 months",  "0mo" },
1730         { TS(1,0), fTS | TS::fSS_Day,         "0 days",    "0d"  },
1731         { TS(1,0), fTS | TS::fSS_Minute,      "0 minutes", "0m"  },
1732         { TS(1,0), fTS | TS::fSS_Second,      "1 second",  "1s"  },
1733         { TS(1,0), fTS | TS::fSS_Millisecond, "1 second",  "1s"  },
1734         { TS(1,0), fTS | TS::fSS_Microsecond, "1 second",  "1s"  },
1735         { TS(1,0), fTS | TS::fSS_Nanosecond,  "1 second",  "1s"  },
1736         { TS(1,0), fTS | TS::fSS_Precision1,  "1 second",  "1s"  },
1737         { TS(1,0), fTS | TS::fSS_Precision2,  "1 second",  "1s"  },
1738         { TS(1,0), fTS | TS::fSS_Precision3,  "1 second",  "1s"  },
1739         { TS(1,0), fTS | TS::fSS_Precision4,  "1 second",  "1s"  },
1740         { TS(1,0), fTS | TS::fSS_Precision5,  "1 second",  "1s"  },
1741         { TS(1,0), fTS | TS::fSS_Precision6,  "1 second",  "1s"  },
1742         { TS(1,0), fTS | TS::fSS_Precision7,  "1 second",  "1s"  },
1743 
1744         // 1 second 1 millisecond
1745         { TS(1,1000000), fTN | TS::fSS_Year,        "0 years",   "0y"  },
1746         { TS(1,1000000), fTN | TS::fSS_Month,       "0 months",  "0mo" },
1747         { TS(1,1000000), fTN | TS::fSS_Day,         "0 days",    "0d"  },
1748         { TS(1,1000000), fTN | TS::fSS_Minute,      "0 minutes", "0m"  },
1749         { TS(1,1000000), fTN | TS::fSS_Second,      "1 second",  "1s"  },
1750         { TS(1,1000000), fTN | TS::fSS_Millisecond, "1 second 1 millisecond", "1s 1ms" },
1751         { TS(1,1000000), fTN | TS::fSS_Microsecond, "1 second 1000 microseconds", "1s 1000us" },
1752         { TS(1,1000000), fTN | TS::fSS_Nanosecond,  "1 second 1000000 nanoseconds", "1s 1000000ns" },
1753         { TS(1,1000000), fTN | TS::fSS_Precision1,  "1 second",  "1s"  },
1754         { TS(1,1000000), fTN | TS::fSS_Precision2,  "1 second",  "1s"  },
1755         { TS(1,1000000), fTN | TS::fSS_Precision3,  "1 second",  "1s"  },
1756         { TS(1,1000000), fTN | TS::fSS_Precision4,  "1 second",  "1s"  },
1757         { TS(1,1000000), fTN | TS::fSS_Precision5,  "1 second",  "1s"  },
1758         { TS(1,1000000), fTN | TS::fSS_Precision6,  "1 second",  "1s"  },
1759         { TS(1,1000000), fTN | TS::fSS_Precision7,  "1 second",  "1s"  },
1760         { TS(1,1000000), fTS | TS::fSS_Year,        "0 years",   "0y"  },
1761         { TS(1,1000000), fTS | TS::fSS_Month,       "0 months",  "0mo" },
1762         { TS(1,1000000), fTS | TS::fSS_Day,         "0 days",    "0d"  },
1763         { TS(1,1000000), fTS | TS::fSS_Minute,      "0 minutes", "0m"  },
1764         { TS(1,1000000), fTS | TS::fSS_Second,      "1 second",  "1s"  },
1765         { TS(1,1000000), fTS | TS::fSS_Millisecond, "1 second 1 millisecond", "1s 1ms" },
1766         { TS(1,1000000), fTS | TS::fSS_Microsecond, "1 second 1000 microseconds", "1s 1000us" },
1767         { TS(1,1000000), fTS | TS::fSS_Nanosecond,  "1 second 1000000 nanoseconds", "1s 1000000ns" },
1768         { TS(1,1000000), fTS | TS::fSS_Precision1,  "1 second",  "1s"  },
1769         { TS(1,1000000), fTS | TS::fSS_Precision2,  "1 second",  "1s"  },
1770         { TS(1,1000000), fTS | TS::fSS_Precision3,  "1 second",  "1s"  },
1771         { TS(1,1000000), fTS | TS::fSS_Precision4,  "1 second",  "1s"  },
1772         { TS(1,1000000), fTS | TS::fSS_Precision5,  "1 second",  "1s"  },
1773         { TS(1,1000000), fTS | TS::fSS_Precision6,  "1 second",  "1s"  },
1774         { TS(1,1000000), fTS | TS::fSS_Precision7,  "1 second",  "1s"  },
1775 
1776         // 1 minute 1 second
1777         { TS(61,0), fTN | TS::fSS_Year,        "0 years",  "0y"  },
1778         { TS(61,0), fTN | TS::fSS_Month,       "0 months", "0mo" },
1779         { TS(61,0), fTN | TS::fSS_Day,         "0 days",   "0d"  },
1780         { TS(61,0), fTN | TS::fSS_Minute,      "1 minute", "1m"  },
1781         { TS(61,0), fTN | TS::fSS_Second,      "1 minute 1 second", "1m 1s" },
1782         { TS(61,0), fTN | TS::fSS_Millisecond, "1 minute 1 second", "1m 1s" },
1783         { TS(61,0), fTN | TS::fSS_Microsecond, "1 minute 1 second", "1m 1s" },
1784         { TS(61,0), fTN | TS::fSS_Nanosecond,  "1 minute 1 second", "1m 1s" },
1785         { TS(61,0), fTN | TS::fSS_Precision1,  "1 minute", "1m"  },
1786         { TS(61,0), fTN | TS::fSS_Precision2,  "1 minute 1 second", "1m 1s" },
1787         { TS(61,0), fTN | TS::fSS_Precision3,  "1 minute 1 second", "1m 1s" },
1788         { TS(61,0), fTN | TS::fSS_Precision4,  "1 minute 1 second", "1m 1s" },
1789         { TS(61,0), fTN | TS::fSS_Precision5,  "1 minute 1 second", "1m 1s" },
1790         { TS(61,0), fTN | TS::fSS_Precision6,  "1 minute 1 second", "1m 1s" },
1791         { TS(61,0), fTN | TS::fSS_Precision7,  "1 minute 1 second", "1m 1s" },
1792         { TS(61,0), fTS | TS::fSS_Year,        "0 years",  "0y"  },
1793         { TS(61,0), fTS | TS::fSS_Month,       "0 months", "0mo" },
1794         { TS(61,0), fTS | TS::fSS_Day,         "0 days",   "0d"  },
1795         { TS(61,0), fTS | TS::fSS_Minute,      "1 minute", "1m"  },
1796         { TS(61,0), fTS | TS::fSS_Second,      "1 minute 1 second", "1m 1s" },
1797         { TS(61,0), fTS | TS::fSS_Millisecond, "1 minute 1 second", "1m 1s" },
1798         { TS(61,0), fTS | TS::fSS_Microsecond, "1 minute 1 second", "1m 1s" },
1799         { TS(61,0), fTS | TS::fSS_Nanosecond,  "1 minute 1 second", "1m 1s" },
1800         { TS(61,0), fTS | TS::fSS_Precision1,  "1 minute", "1m"  },
1801         { TS(61,0), fTS | TS::fSS_Precision2,  "1 minute 1 second", "1m 1s" },
1802         { TS(61,0), fTS | TS::fSS_Precision3,  "1 minute 1 second", "1m 1s" },
1803         { TS(61,0), fTS | TS::fSS_Precision4,  "1 minute 1 second", "1m 1s" },
1804         { TS(61,0), fTS | TS::fSS_Precision5,  "1 minute 1 second", "1m 1s" },
1805         { TS(61,0), fTS | TS::fSS_Precision6,  "1 minute 1 second", "1m 1s" },
1806         { TS(61,0), fTS | TS::fSS_Precision7,  "1 minute 1 second", "1m 1s" },
1807 
1808         // 999 nanoseconds
1809         { TS(0,999), fTS | TS::fSS_Year,        "0 years",         "0y"    },
1810         { TS(0,999), fTS | TS::fSS_Month,       "0 months",        "0mo"   },
1811         { TS(0,999), fTS | TS::fSS_Day,         "0 days",          "0d"    },
1812         { TS(0,999), fTS | TS::fSS_Minute,      "0 minutes",       "0m"    },
1813         { TS(0,999), fTS | TS::fSS_Second,      "0 seconds",       "0s"    },
1814         { TS(0,999), fTS | TS::fSS_Millisecond, "0 seconds",       "0s"    },
1815         { TS(0,999), fTS | TS::fSS_Microsecond, "0 seconds",       "0s"    },
1816         { TS(0,999), fTS | TS::fSS_Nanosecond,  "999 nanoseconds", "999ns" },
1817         { TS(0,999), fRS | TS::fSS_Millisecond, "0 seconds",       "0s"    },
1818         { TS(0,999), fRS | TS::fSS_Microsecond, "1 microsecond",   "1us"   },
1819         { TS(0,999), fRS | TS::fSS_Nanosecond,  "999 nanoseconds", "999ns" },
1820 
1821         // 1000 nanoseconds
1822         { TS(0,1000), fTS | TS::fSS_Year,        "0 years",          "0y"  },
1823         { TS(0,1000), fTS | TS::fSS_Month,       "0 months",         "0mo" },
1824         { TS(0,1000), fTS | TS::fSS_Day,         "0 days",           "0d"  },
1825         { TS(0,1000), fTS | TS::fSS_Minute,      "0 minutes",        "0m"  },
1826         { TS(0,1000), fTS | TS::fSS_Second,      "0 seconds",        "0s"  },
1827         { TS(0,1000), fTS | TS::fSS_Millisecond, "0 seconds",        "0s"  },
1828         { TS(0,1000), fTS | TS::fSS_Microsecond, "1 microsecond",    "1us" },
1829         { TS(0,1000), fTS | TS::fSS_Nanosecond,  "1000 nanoseconds", "1000ns" },
1830 
1831         // 1,000,000 nanoseconds
1832         { TS(0,1000000), fTS | TS::fSS_Year,        "0 years",       "0y"  },
1833         { TS(0,1000000), fTS | TS::fSS_Month,       "0 months",      "0mo" },
1834         { TS(0,1000000), fTS | TS::fSS_Day,         "0 days",        "0d"  },
1835         { TS(0,1000000), fTS | TS::fSS_Minute,      "0 minutes",     "0m"  },
1836         { TS(0,1000000), fTS | TS::fSS_Second,      "0 seconds",     "0s"  },
1837         { TS(0,1000000), fTS | TS::fSS_Millisecond, "1 millisecond", "1ms" },
1838         { TS(0,1000000), fTS | TS::fSS_Microsecond, "1000 microseconds", "1000us" },
1839         { TS(0,1000000), fTS | TS::fSS_Nanosecond,  "1000000 nanoseconds", "1000000ns" },
1840 
1841         // 100,000,000 nanoseconds
1842         { TS(0,100000000), fTS | TS::fSS_Year,        "0 years",   "0y"  },
1843         { TS(0,100000000), fTS | TS::fSS_Month,       "0 months",  "0mo" },
1844         { TS(0,100000000), fTS | TS::fSS_Day,         "0 days",    "0d"  },
1845         { TS(0,100000000), fTS | TS::fSS_Minute,      "0 minutes", "0m"  },
1846         { TS(0,100000000), fTS | TS::fSS_Second,      "0 seconds", "0s"  },
1847         { TS(0,100000000), fTS | TS::fSS_Millisecond, "100 milliseconds", "100ms" },
1848         { TS(0,100000000), fTS | TS::fSS_Microsecond, "100000 microseconds", "100000us" },
1849         { TS(0,100000000), fTS | TS::fSS_Nanosecond,  "100000000 nanoseconds", "100000000ns" },
1850 
1851         // 1,000,000,000 nanoseconds
1852         { TS(0,1000000000), fTN | TS::fSS_Millisecond, "1 second",  "1s"  },
1853         { TS(0,1000000000), fTN | TS::fSS_Microsecond, "1 second",  "1s"  },
1854         { TS(0,1000000000), fTN | TS::fSS_Nanosecond,  "1 second",  "1s"  },
1855         { TS(0,1000000000), fTS | TS::fSS_Year,        "0 years",   "0y"  },
1856         { TS(0,1000000000), fTS | TS::fSS_Month,       "0 months",  "0mo" },
1857         { TS(0,1000000000), fTS | TS::fSS_Day,         "0 days",    "0d"  },
1858         { TS(0,1000000000), fTS | TS::fSS_Minute,      "0 minutes", "0m"  },
1859         { TS(0,1000000000), fTS | TS::fSS_Second,      "1 second",  "1s"  },
1860         { TS(0,1000000000), fTS | TS::fSS_Millisecond, "1 second",  "1s"  },
1861         { TS(0,1000000000), fTS | TS::fSS_Microsecond, "1 second",  "1s"  },
1862         { TS(0,1000000000), fTS | TS::fSS_Nanosecond,  "1 second",  "1s"  },
1863 
1864         // 1,000,000,001 nanoseconds
1865         { TS(0,1000000001), fTN | TS::fSS_Second,      "1 second",  "1s"  },
1866         { TS(0,1000000001), fTN | TS::fSS_Millisecond, "1 second",  "1s"  },
1867         { TS(0,1000000001), fTN | TS::fSS_Microsecond, "1 second",  "1s"  },
1868         { TS(0,1000000001), fTN | TS::fSS_Nanosecond,  "1 second 1 nanosecond", "1s 1ns" },
1869         { TS(0,1000000001), fTS | TS::fSS_Year,        "0 years",   "0y"  },
1870         { TS(0,1000000001), fTS | TS::fSS_Month,       "0 months",  "0mo" },
1871         { TS(0,1000000001), fTS | TS::fSS_Day,         "0 days",    "0d"  },
1872         { TS(0,1000000001), fTS | TS::fSS_Minute,      "0 minutes", "0m"  },
1873         { TS(0,1000000001), fTS | TS::fSS_Second,      "1 second",  "1s"  },
1874         { TS(0,1000000001), fTS | TS::fSS_Millisecond, "1 second",  "1s"  },
1875         { TS(0,1000000001), fTS | TS::fSS_Microsecond, "1 second",  "1s"  },
1876         { TS(0,1000000001), fTS | TS::fSS_Nanosecond,  "1 second 1 nanosecond", "1s 1ns" },
1877 
1878 #if (SIZEOF_LONG == 8)
1879         // 10,000,000,000 nanoseconds
1880         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Smart,       "10 seconds", "10s" },
1881         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Year,        "0 years",    "0y"  },
1882         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Month,       "0 months",   "0mo" },
1883         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Day,         "0 days",     "0d"  },
1884         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Minute,      "0 minutes",  "0m"  },
1885         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Second,      "10 seconds", "10s" },
1886         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Millisecond, "10 seconds", "10s" },
1887         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Microsecond, "10 seconds", "10s" },
1888         { TS(0,NCBI_CONST_INT8(10000000000)), fTS | TS::fSS_Nanosecond,  "10 seconds", "10s" },
1889 #endif
1890 
1891         // 60 second
1892         { TS(60,0), fTN | TS::fSS_Year,        "0 years",   "0y"  },
1893         { TS(60,0), fTN | TS::fSS_Month,       "0 months",  "0mo" },
1894         { TS(60,0), fTN | TS::fSS_Day,         "0 days",    "0d"  },
1895         { TS(60,0), fTN | TS::fSS_Minute,      "1 minute",  "1m"  },
1896         { TS(60,0), fTN | TS::fSS_Second,      "1 minute",  "1m"  },
1897         { TS(60,0), fTN | TS::fSS_Millisecond, "1 minute",  "1m"  },
1898         { TS(60,0), fTN | TS::fSS_Microsecond, "1 minute",  "1m"  },
1899         { TS(60,0), fTN | TS::fSS_Nanosecond,  "1 minute",  "1m"  },
1900         { TS(60,0), fTN | TS::fSS_Precision1,  "1 minute",  "1m"  },
1901         { TS(60,0), fTN | TS::fSS_Precision2,  "1 minute",  "1m"  },
1902         { TS(60,0), fTN | TS::fSS_Precision3,  "1 minute",  "1m"  },
1903         { TS(60,0), fTN | TS::fSS_Precision4,  "1 minute",  "1m"  },
1904         { TS(60,0), fTN | TS::fSS_Precision5,  "1 minute",  "1m"  },
1905         { TS(60,0), fTN | TS::fSS_Precision6,  "1 minute",  "1m"  },
1906         { TS(60,0), fTN | TS::fSS_Precision7,  "1 minute",  "1m"  },
1907         { TS(60,0), fTS | TS::fSS_Year,        "0 years",   "0y"  },
1908         { TS(60,0), fTS | TS::fSS_Month,       "0 months",  "0mo" },
1909         { TS(60,0), fTS | TS::fSS_Day,         "0 days",    "0d"  },
1910         { TS(60,0), fTS | TS::fSS_Minute,      "1 minute",  "1m"  },
1911         { TS(60,0), fTS | TS::fSS_Second,      "1 minute",  "1m"  },
1912         { TS(60,0), fTS | TS::fSS_Millisecond, "1 minute",  "1m"  },
1913         { TS(60,0), fTS | TS::fSS_Microsecond, "1 minute",  "1m"  },
1914         { TS(60,0), fTS | TS::fSS_Nanosecond,  "1 minute",  "1m"  },
1915         { TS(60,0), fTS | TS::fSS_Precision1,  "1 minute",  "1m"  },
1916         { TS(60,0), fTS | TS::fSS_Precision2,  "1 minute",  "1m"  },
1917         { TS(60,0), fTS | TS::fSS_Precision3,  "1 minute",  "1m"  },
1918         { TS(60,0), fTS | TS::fSS_Precision4,  "1 minute",  "1m"  },
1919         { TS(60,0), fTS | TS::fSS_Precision5,  "1 minute",  "1m"  },
1920         { TS(60,0), fTS | TS::fSS_Precision6,  "1 minute",  "1m"  },
1921         { TS(60,0), fTS | TS::fSS_Precision7,  "1 minute",  "1m"  },
1922 
1923         // 600 seconds
1924         { TS(600,0), fTN | TS::fSS_Year,        "0 years",    "0y"  },
1925         { TS(600,0), fTN | TS::fSS_Month,       "0 months",   "0mo" },
1926         { TS(600,0), fTN | TS::fSS_Day,         "0 days",     "0d"  },
1927         { TS(600,0), fTN | TS::fSS_Minute,      "10 minutes", "10m" },
1928         { TS(600,0), fTN | TS::fSS_Second,      "10 minutes", "10m" },
1929         { TS(600,0), fTN | TS::fSS_Millisecond, "10 minutes", "10m" },
1930         { TS(600,0), fTN | TS::fSS_Microsecond, "10 minutes", "10m" },
1931         { TS(600,0), fTN | TS::fSS_Nanosecond,  "10 minutes", "10m" },
1932         { TS(600,0), fTN | TS::fSS_Precision1,  "10 minutes", "10m" },
1933         { TS(600,0), fTN | TS::fSS_Precision2,  "10 minutes", "10m" },
1934         { TS(600,0), fTN | TS::fSS_Precision3,  "10 minutes", "10m" },
1935         { TS(600,0), fTN | TS::fSS_Precision4,  "10 minutes", "10m" },
1936         { TS(600,0), fTN | TS::fSS_Precision5,  "10 minutes", "10m" },
1937         { TS(600,0), fTN | TS::fSS_Precision6,  "10 minutes", "10m" },
1938         { TS(600,0), fTN | TS::fSS_Precision7,  "10 minutes", "10m" },
1939         { TS(600,0), fTS | TS::fSS_Year,        "0 years",    "0y"  },
1940         { TS(600,0), fTS | TS::fSS_Month,       "0 months",   "0mo" },
1941         { TS(600,0), fTS | TS::fSS_Day,         "0 days",     "0d"  },
1942         { TS(600,0), fTS | TS::fSS_Minute,      "10 minutes", "10m" },
1943         { TS(600,0), fTS | TS::fSS_Second,      "10 minutes", "10m" },
1944         { TS(600,0), fTS | TS::fSS_Millisecond, "10 minutes", "10m" },
1945         { TS(600,0), fTS | TS::fSS_Microsecond, "10 minutes", "10m" },
1946         { TS(600,0), fTS | TS::fSS_Nanosecond,  "10 minutes", "10m" },
1947         { TS(600,0), fTS | TS::fSS_Precision1,  "10 minutes", "10m" },
1948         { TS(600,0), fTS | TS::fSS_Precision2,  "10 minutes", "10m" },
1949         { TS(600,0), fTS | TS::fSS_Precision3,  "10 minutes", "10m" },
1950         { TS(600,0), fTS | TS::fSS_Precision4,  "10 minutes", "10m" },
1951         { TS(600,0), fTS | TS::fSS_Precision5,  "10 minutes", "10m" },
1952         { TS(600,0), fTS | TS::fSS_Precision6,  "10 minutes", "10m" },
1953         { TS(600,0), fTS | TS::fSS_Precision7,  "10 minutes", "10m" },
1954 
1955         // 3600 seconds
1956         { TS(3600,0), fTN | TS::fSS_Year,        "0 years",  "0y"  },
1957         { TS(3600,0), fTN | TS::fSS_Month,       "0 months", "0mo" },
1958         { TS(3600,0), fTN | TS::fSS_Day,         "0 days",   "0d"  },
1959         { TS(3600,0), fTN | TS::fSS_Minute,      "1 hour",   "1h"  },
1960         { TS(3600,0), fTN | TS::fSS_Second,      "1 hour",   "1h"  },
1961         { TS(3600,0), fTN | TS::fSS_Millisecond, "1 hour",   "1h"  },
1962         { TS(3600,0), fTN | TS::fSS_Microsecond, "1 hour",   "1h"  },
1963         { TS(3600,0), fTN | TS::fSS_Nanosecond,  "1 hour",   "1h"  },
1964         { TS(3600,0), fTN | TS::fSS_Precision1,  "1 hour",   "1h"  },
1965         { TS(3600,0), fTN | TS::fSS_Precision2,  "1 hour",   "1h"  },
1966         { TS(3600,0), fTN | TS::fSS_Precision3,  "1 hour",   "1h"  },
1967         { TS(3600,0), fTN | TS::fSS_Precision4,  "1 hour",   "1h"  },
1968         { TS(3600,0), fTN | TS::fSS_Precision5,  "1 hour",   "1h"  },
1969         { TS(3600,0), fTN | TS::fSS_Precision6,  "1 hour",   "1h"  },
1970         { TS(3600,0), fTN | TS::fSS_Precision7,  "1 hour",   "1h"  },
1971         { TS(3600,0), fTS | TS::fSS_Year,        "0 years",  "0y"  },
1972         { TS(3600,0), fTS | TS::fSS_Month,       "0 months", "0mo" },
1973         { TS(3600,0), fTS | TS::fSS_Day,         "0 days",   "0d"  },
1974         { TS(3600,0), fTS | TS::fSS_Minute,      "1 hour",   "1h"  },
1975         { TS(3600,0), fTS | TS::fSS_Second,      "1 hour",   "1h"  },
1976         { TS(3600,0), fTS | TS::fSS_Millisecond, "1 hour",   "1h"  },
1977         { TS(3600,0), fTS | TS::fSS_Microsecond, "1 hour",   "1h"  },
1978         { TS(3600,0), fTS | TS::fSS_Nanosecond,  "1 hour",   "1h"  },
1979         { TS(3600,0), fTS | TS::fSS_Precision1,  "1 hour",   "1h"  },
1980         { TS(3600,0), fTS | TS::fSS_Precision2,  "1 hour",   "1h"  },
1981         { TS(3600,0), fTS | TS::fSS_Precision3,  "1 hour",   "1h"  },
1982         { TS(3600,0), fTS | TS::fSS_Precision4,  "1 hour",   "1h"  },
1983         { TS(3600,0), fTS | TS::fSS_Precision5,  "1 hour",   "1h"  },
1984         { TS(3600,0), fTS | TS::fSS_Precision6,  "1 hour",   "1h"  },
1985         { TS(3600,0), fTS | TS::fSS_Precision7,  "1 hour",   "1h"  },
1986 
1987         // 36000 seconds
1988         { TS(36000,0), fTN | TS::fSS_Year,        "0 years",  "0y"  },
1989         { TS(36000,0), fTN | TS::fSS_Month,       "0 months", "0mo" },
1990         { TS(36000,0), fTN | TS::fSS_Day,         "0 days",   "0d"  },
1991         { TS(36000,0), fTN | TS::fSS_Minute,      "10 hours", "10h" },
1992         { TS(36000,0), fTN | TS::fSS_Second,      "10 hours", "10h" },
1993         { TS(36000,0), fTN | TS::fSS_Millisecond, "10 hours", "10h" },
1994         { TS(36000,0), fTN | TS::fSS_Microsecond, "10 hours", "10h" },
1995         { TS(36000,0), fTN | TS::fSS_Nanosecond,  "10 hours", "10h" },
1996         { TS(36000,0), fTN | TS::fSS_Precision1,  "10 hours", "10h" },
1997         { TS(36000,0), fTN | TS::fSS_Precision2,  "10 hours", "10h" },
1998         { TS(36000,0), fTN | TS::fSS_Precision3,  "10 hours", "10h" },
1999         { TS(36000,0), fTN | TS::fSS_Precision4,  "10 hours", "10h" },
2000         { TS(36000,0), fTN | TS::fSS_Precision5,  "10 hours", "10h" },
2001         { TS(36000,0), fTN | TS::fSS_Precision6,  "10 hours", "10h" },
2002         { TS(36000,0), fTN | TS::fSS_Precision7,  "10 hours", "10h" },
2003         { TS(36000,0), fTS | TS::fSS_Year,        "0 years",  "0y"  },
2004         { TS(36000,0), fTS | TS::fSS_Month,       "0 months", "0mo" },
2005         { TS(36000,0), fTS | TS::fSS_Day,         "0 days",   "0d"  },
2006         { TS(36000,0), fTS | TS::fSS_Minute,      "10 hours", "10h" },
2007         { TS(36000,0), fTS | TS::fSS_Second,      "10 hours", "10h" },
2008         { TS(36000,0), fTS | TS::fSS_Millisecond, "10 hours", "10h" },
2009         { TS(36000,0), fTS | TS::fSS_Microsecond, "10 hours", "10h" },
2010         { TS(36000,0), fTS | TS::fSS_Nanosecond,  "10 hours", "10h" },
2011         { TS(36000,0), fTS | TS::fSS_Precision1,  "10 hours", "10h" },
2012         { TS(36000,0), fTS | TS::fSS_Precision2,  "10 hours", "10h" },
2013         { TS(36000,0), fTS | TS::fSS_Precision3,  "10 hours", "10h" },
2014         { TS(36000,0), fTS | TS::fSS_Precision4,  "10 hours", "10h" },
2015         { TS(36000,0), fTS | TS::fSS_Precision5,  "10 hours", "10h" },
2016         { TS(36000,0), fTS | TS::fSS_Precision6,  "10 hours", "10h" },
2017         { TS(36000,0), fTS | TS::fSS_Precision7,  "10 hours", "10h" },
2018 
2019         // 86400 seconds
2020         { TS(86400,0), fTN | TS::fSS_Year,        "0 years",  "0y"  },
2021         { TS(86400,0), fTN | TS::fSS_Month,       "0 months", "0mo" },
2022         { TS(86400,0), fTN | TS::fSS_Day,         "1 day",    "1d"  },
2023         { TS(86400,0), fTN | TS::fSS_Minute,      "1 day",    "1d"  },
2024         { TS(86400,0), fTN | TS::fSS_Second,      "1 day",    "1d"  },
2025         { TS(86400,0), fTN | TS::fSS_Millisecond, "1 day",    "1d"  },
2026         { TS(86400,0), fTN | TS::fSS_Microsecond, "1 day",    "1d"  },
2027         { TS(86400,0), fTN | TS::fSS_Nanosecond,  "1 day",    "1d"  },
2028         { TS(86400,0), fTN | TS::fSS_Precision1,  "1 day",    "1d"  },
2029         { TS(86400,0), fTN | TS::fSS_Precision2,  "1 day",    "1d"  },
2030         { TS(86400,0), fTN | TS::fSS_Precision3,  "1 day",    "1d"  },
2031         { TS(86400,0), fTN | TS::fSS_Precision4,  "1 day",    "1d"  },
2032         { TS(86400,0), fTN | TS::fSS_Precision5,  "1 day",    "1d"  },
2033         { TS(86400,0), fTN | TS::fSS_Precision6,  "1 day",    "1d"  },
2034         { TS(86400,0), fTN | TS::fSS_Precision7,  "1 day",    "1d"  },
2035         { TS(86400,0), fTS | TS::fSS_Year,        "0 years",  "0y"  },
2036         { TS(86400,0), fTS | TS::fSS_Month,       "0 months", "0mo" },
2037         { TS(86400,0), fTS | TS::fSS_Day,         "1 day",    "1d"  },
2038         { TS(86400,0), fTS | TS::fSS_Minute,      "1 day",    "1d"  },
2039         { TS(86400,0), fTS | TS::fSS_Second,      "1 day",    "1d"  },
2040         { TS(86400,0), fTS | TS::fSS_Millisecond, "1 day",    "1d"  },
2041         { TS(86400,0), fTS | TS::fSS_Microsecond, "1 day",    "1d"  },
2042         { TS(86400,0), fTS | TS::fSS_Nanosecond,  "1 day",    "1d"  },
2043         { TS(86400,0), fTS | TS::fSS_Precision1,  "1 day",    "1d"  },
2044         { TS(86400,0), fTS | TS::fSS_Precision2,  "1 day",    "1d"  },
2045         { TS(86400,0), fTS | TS::fSS_Precision3,  "1 day",    "1d"  },
2046         { TS(86400,0), fTS | TS::fSS_Precision4,  "1 day",    "1d"  },
2047         { TS(86400,0), fTS | TS::fSS_Precision5,  "1 day",    "1d"  },
2048         { TS(86400,0), fTS | TS::fSS_Precision6,  "1 day",    "1d"  },
2049         { TS(86400,0), fTS | TS::fSS_Precision7,  "1 day",    "1d"  },
2050 
2051         // Some long time
2052         // "1 year 6 months 11 days 0 hours 59 minutes 41 seconds"
2053         // kAverageSecondsPerYear + kAverageSecondsPerMonth*6 + 11*24*3600 + 59*60 + 41 == 48289409 sec
2054 
2055         { TS(48289409,900500), fTN | TS::fSS_Year,        "1 year", "1y" },
2056         { TS(48289409,900500), fTN | TS::fSS_Month,       "1 year 6 months", "1y 6mo" },
2057         { TS(48289409,900500), fTN | TS::fSS_Day,         "1 year 6 months 11 days", "1y 6mo 11d" },
2058         { TS(48289409,900500), fTN | TS::fSS_Minute,      "1 year 6 months 11 days 0 hours 59 minutes", "1y 6mo 11d 0h 59m" },
2059         { TS(48289409,900500), fTN | TS::fSS_Second,      "1 year 6 months 11 days 0 hours 59 minutes 41 seconds", "1y 6mo 11d 0h 59m 41s" },
2060         { TS(48289409,900500), fTN | TS::fSS_Millisecond, "1 year 6 months 11 days 0 hours 59 minutes 41 seconds", "1y 6mo 11d 0h 59m 41s" },
2061         { TS(48289409,900500), fTN | TS::fSS_Microsecond, "1 year 6 months 11 days 0 hours 59 minutes 41 seconds 900 microseconds", "1y 6mo 11d 0h 59m 41s 900us" },
2062         { TS(48289409,900500), fTN | TS::fSS_Nanosecond,  "1 year 6 months 11 days 0 hours 59 minutes 41 seconds 900500 nanoseconds", "1y 6mo 11d 0h 59m 41s 900500ns" },
2063         { TS(48289409,900500), fTN | TS::fSS_Precision1,  "1 year", "1y" },
2064         { TS(48289409,900500), fTN | TS::fSS_Precision2,  "1 year 6 months", "1y 6mo" },
2065         { TS(48289409,900500), fTN | TS::fSS_Precision3,  "1 year 6 months 11 days", "1y 6mo 11d" },
2066         { TS(48289409,900500), fTN | TS::fSS_Precision4,  "1 year 6 months 11 days", "1y 6mo 11d" },
2067         { TS(48289409,900500), fTN | TS::fSS_Precision5,  "1 year 6 months 11 days 0 hours 59 minutes", "1y 6mo 11d 0h 59m" },
2068         { TS(48289409,900500), fTN | TS::fSS_Precision6,  "1 year 6 months 11 days 0 hours 59 minutes 41 seconds", "1y 6mo 11d 0h 59m 41s" },
2069         { TS(48289409,900500), fTN | TS::fSS_Precision7,  "1 year 6 months 11 days 0 hours 59 minutes 41 seconds", "1y 6mo 11d 0h 59m 41s" },
2070 
2071         { TS(48289409,900500), fTS | TS::fSS_Year,        "1 year", "1y" },
2072         { TS(48289409,900500), fTS | TS::fSS_Month,       "1 year 6 months", "1y 6mo" },
2073         { TS(48289409,900500), fTS | TS::fSS_Day,         "1 year 6 months 11 days", "1y 6mo 11d" },
2074         { TS(48289409,900500), fTS | TS::fSS_Minute,      "1 year 6 months 11 days 59 minutes", "1y 6mo 11d 59m" },
2075         { TS(48289409,900500), fTS | TS::fSS_Second,      "1 year 6 months 11 days 59 minutes 41 seconds", "1y 6mo 11d 59m 41s" },
2076         { TS(48289409,900500), fTS | TS::fSS_Millisecond, "1 year 6 months 11 days 59 minutes 41 seconds", "1y 6mo 11d 59m 41s" },
2077         { TS(48289409,900500), fTS | TS::fSS_Microsecond, "1 year 6 months 11 days 59 minutes 41 seconds 900 microseconds", "1y 6mo 11d 59m 41s 900us" },
2078         { TS(48289409,900500), fTS | TS::fSS_Nanosecond,  "1 year 6 months 11 days 59 minutes 41 seconds 900500 nanoseconds", "1y 6mo 11d 59m 41s 900500ns" },
2079         { TS(48289409,900500), fTS | TS::fSS_Precision1,  "1 year", "1y" },
2080         { TS(48289409,900500), fTS | TS::fSS_Precision2,  "1 year 6 months", "1y 6mo" },
2081         { TS(48289409,900500), fTS | TS::fSS_Precision3,  "1 year 6 months 11 days", "1y 6mo 11d" },
2082         { TS(48289409,900500), fTS | TS::fSS_Precision4,  "1 year 6 months 11 days", "1y 6mo 11d" },
2083         { TS(48289409,900500), fTS | TS::fSS_Precision5,  "1 year 6 months 11 days 59 minutes", "1y 6mo 11d 59m" },
2084         { TS(48289409,900500), fTS | TS::fSS_Precision6,  "1 year 6 months 11 days 59 minutes 41 seconds", "1y 6mo 11d 59m 41s" },
2085         { TS(48289409,900500), fTS | TS::fSS_Precision7,  "1 year 6 months 11 days 59 minutes 41 seconds", "1y 6mo 11d 59m 41s" },
2086 
2087         { TS(48289409,900500), fRN | TS::fSS_Year,        "2 years", "2y" },
2088         { TS(48289409,900500), fRN | TS::fSS_Month,       "1 year 6 months", "1y 6mo" },
2089         { TS(48289409,900500), fRN | TS::fSS_Day,         "1 year 6 months 11 days", "1y 6mo 11d" },
2090         { TS(48289409,900500), fRN | TS::fSS_Minute,      "1 year 6 months 11 days 1 hour", "1y 6mo 11d 1h" },
2091         { TS(48289409,900500), fRN | TS::fSS_Second,      "1 year 6 months 11 days 0 hours 59 minutes 41 seconds", "1y 6mo 11d 0h 59m 41s" },
2092         { TS(48289409,900500), fRN | TS::fSS_Millisecond, "1 year 6 months 11 days 0 hours 59 minutes 41 seconds 1 millisecond", "1y 6mo 11d 0h 59m 41s 1ms" },
2093         { TS(48289409,900500), fRN | TS::fSS_Microsecond, "1 year 6 months 11 days 0 hours 59 minutes 41 seconds 901 microseconds", "1y 6mo 11d 0h 59m 41s 901us" },
2094         { TS(48289409,900500), fRN | TS::fSS_Nanosecond,  "1 year 6 months 11 days 0 hours 59 minutes 41 seconds 900500 nanoseconds", "1y 6mo 11d 0h 59m 41s 900500ns" },
2095         { TS(48289409,900500), fRN | TS::fSS_Precision1,  "2 years", "2y" },
2096         { TS(48289409,900500), fRN | TS::fSS_Precision2,  "1 year 6 months", "1y 6mo" },
2097         { TS(48289409,900500), fRN | TS::fSS_Precision3,  "1 year 6 months 11 days", "1y 6mo 11d" },
2098         { TS(48289409,900500), fRN | TS::fSS_Precision4,  "1 year 6 months 11 days 1 hour", "1y 6mo 11d 1h" },
2099         { TS(48289409,900500), fRN | TS::fSS_Precision5,  "1 year 6 months 11 days 1 hour", "1y 6mo 11d 1h" },
2100         { TS(48289409,900500), fRN | TS::fSS_Precision6,  "1 year 6 months 11 days 0 hours 59 minutes 41 seconds", "1y 6mo 11d 0h 59m 41s" },
2101         { TS(48289409,900500), fRN | TS::fSS_Precision7,  "1 year 6 months 11 days 0 hours 59 minutes 41 seconds", "1y 6mo 11d 0h 59m 41s" },
2102 
2103         { TS(48289409,900500), fRS | TS::fSS_Year,        "2 years", "2y" },
2104         { TS(48289409,900500), fRS | TS::fSS_Month,       "1 year 6 months", "1y 6mo" },
2105         { TS(48289409,900500), fRS | TS::fSS_Day,         "1 year 6 months 11 days", "1y 6mo 11d" },
2106         { TS(48289409,900500), fRS | TS::fSS_Minute,      "1 year 6 months 11 days 1 hour", "1y 6mo 11d 1h" },
2107         { TS(48289409,900500), fRS | TS::fSS_Second,      "1 year 6 months 11 days 59 minutes 41 seconds", "1y 6mo 11d 59m 41s" },
2108         { TS(48289409,900500), fRS | TS::fSS_Millisecond, "1 year 6 months 11 days 59 minutes 41 seconds 1 millisecond", "1y 6mo 11d 59m 41s 1ms" },
2109         { TS(48289409,900500), fRS | TS::fSS_Microsecond, "1 year 6 months 11 days 59 minutes 41 seconds 901 microseconds", "1y 6mo 11d 59m 41s 901us" },
2110         { TS(48289409,900500), fRS | TS::fSS_Nanosecond,  "1 year 6 months 11 days 59 minutes 41 seconds 900500 nanoseconds", "1y 6mo 11d 59m 41s 900500ns" },
2111         { TS(48289409,900500), fRS | TS::fSS_Precision1,  "2 years", "2y" },
2112         { TS(48289409,900500), fRS | TS::fSS_Precision2,  "1 year 6 months", "1y 6mo" },
2113         { TS(48289409,900500), fRS | TS::fSS_Precision3,  "1 year 6 months 11 days", "1y 6mo 11d" },
2114         { TS(48289409,900500), fRS | TS::fSS_Precision4,  "1 year 6 months 11 days 1 hour", "1y 6mo 11d 1h" },
2115         { TS(48289409,900500), fRS | TS::fSS_Precision5,  "1 year 6 months 11 days 1 hour", "1y 6mo 11d 1h" },
2116         { TS(48289409,900500), fRS | TS::fSS_Precision6,  "1 year 6 months 11 days 59 minutes 41 seconds", "1y 6mo 11d 59m 41s" },
2117         { TS(48289409,900500), fRS | TS::fSS_Precision7,  "1 year 6 months 11 days 59 minutes 41 seconds", "1y 6mo 11d 59m 41s" },
2118 
2119         // stopper
2120         { TS(0,0), TS::fSS_Default,  NULL, NULL }
2121     };
2122 
2123     for (int i = 0;  s_Test[i].res_full;  i++) {
2124 
2125         // timespan -> string
2126 
2127         string s_full  = s_Test[i].timespan.AsSmartString(s_Test[i].flags | TS::fSS_Full);
2128         string s_short = s_Test[i].timespan.AsSmartString(s_Test[i].flags | TS::fSS_Short);
2129 #if 1
2130         assert(s_full  == s_Test[i].res_full);
2131         assert(s_short == s_Test[i].res_short);
2132 #else
2133         if (s_full != s_Test[i].res_full) {
2134             cout << i << ".  Print:" << s_full << " != " << s_Test[i].res_full << endl;
2135         }
2136         if (s_short != s_Test[i].res_short) {
2137             cout << i << ".  Print:" << s_short << " != " << s_Test[i].res_short << endl;
2138         }
2139 #endif
2140 
2141         // string -> timespan -> string (AssignFromSmartString() test)
2142 
2143         CTimeSpan ts;
2144         ts.AssignFromSmartString(s_full);
2145         string s_full_new  = ts.AsSmartString(s_Test[i].flags | TS::fSS_Full);
2146         ts.AssignFromSmartString(s_short);
2147         string s_short_new = ts.AsSmartString(s_Test[i].flags | TS::fSS_Short);
2148 #if 1
2149         assert(s_full_new  == s_Test[i].res_full);
2150         assert(s_short_new == s_Test[i].res_short);
2151 #else
2152         if (s_full_new != s_Test[i].res_full) {
2153             cout << i << ".  Assign:" << s_full_new << " != " << s_Test[i].res_full << endl;
2154         }
2155         if (s_short_new != s_Test[i].res_short) {
2156             cout << i << ".   Assign:" << s_short_new << " != " << s_Test[i].res_short << endl;
2157         }
2158 #endif
2159     }
2160 }
2161 
2162 
2163 
2164 //============================================================================
2165 //
2166 // TestTimeout
2167 //
2168 //============================================================================
2169 
s_TestTimeout(void)2170 static void s_TestTimeout(void)
2171 {
2172     unsigned long ms;
2173     double        ds;
2174     CTimeout      tmo_default;
2175     CTimeout      tmo_infinite(CTimeout::eInfinite);
2176     CTimeout      tmo_zero(CTimeout::eZero);
2177 
2178     // Special values
2179     {{
2180         assert(tmo_default.IsDefault());
2181         assert(tmo_infinite.IsInfinite());
2182         assert(tmo_zero.IsZero());
2183         try {
2184             tmo_default.GetAsDouble();
2185             _TROUBLE;
2186         }
2187         catch (CTimeException&) {}
2188         try {
2189             tmo_infinite.GetAsDouble();
2190             _TROUBLE;
2191         }
2192         catch (CTimeException&) {}
2193         assert(!tmo_infinite.IsZero());
2194         try {
2195             // Default value cannot be check on zero, unlike infinite timeout.
2196             assert(tmo_default.IsZero());
2197             _TROUBLE;
2198         }
2199         catch (CTimeException&) {}
2200     }}
2201 
2202     // Constructors
2203     {{
2204         CTimeout t1(3,400000);
2205         ms = t1.GetAsMilliSeconds();
2206         ds = t1.GetAsDouble();
2207         assert(ms == 3400);
2208         assert(ds > 3.3  &&  ds < 3.5);
2209         t1.Set(1,2000);
2210         assert(t1.GetAsMilliSeconds() == 1002);
2211 
2212         CTimeout t2(6.75);
2213         ms = t2.GetAsMilliSeconds();
2214         ds = t2.GetAsDouble();
2215         assert(ms > 6749  &&  ms < 6751);
2216         assert(ds > 6.74  &&  ds < 6.76);
2217         t1.Set(1,2000);
2218         assert(t1.GetAsMilliSeconds() == 1002);
2219 
2220         CTimeout t3(t1);
2221         assert(t3.GetAsMilliSeconds() == 1002);
2222         t3 = t1;
2223         assert(t1.GetAsMilliSeconds() == 1002);
2224         t3 = tmo_default;
2225         assert(t3.IsDefault());
2226         t3 = tmo_infinite;
2227         assert(t3.IsInfinite());
2228     }}
2229     {{
2230         CTimeSpan ts;
2231         CTimeSpan ts1(1,200);
2232         CTimeSpan ts2(1,200000);
2233         CTimeSpan ts3(-1,200);
2234 
2235         CTimeout t(ts1);
2236         // Nanoseconds truncates to 0 here
2237         ts = t.GetAsTimeSpan();
2238         assert(ts.GetCompleteSeconds() == 1);
2239         assert(ts.GetNanoSecondsAfterSecond() == 200);
2240         assert(ts == ts1);
2241 
2242         // Microseconds correcly converts to nanoseconds
2243         t = ts2;
2244         ts = t.GetAsTimeSpan();
2245         assert(ts.GetCompleteSeconds() == 1);
2246         assert(ts.GetNanoSecondsAfterSecond() == 200000);
2247         assert(ts == ts2);
2248 
2249         // Cannot copy from negative time span
2250         try {
2251             t = ts3;
2252             _TROUBLE;
2253         }
2254         catch (CTimeException&) {}
2255     }}
2256 
2257     // Check Get()
2258     {{
2259         CTimeout t(123, 456);
2260         unsigned int sec, usec;
2261         t.Get(&sec, &usec);
2262         assert(sec  == 123);
2263         assert(usec == 456);
2264         t.Set(CTimeout::eInfinite);
2265         try {
2266             t.Get(&sec, &usec);
2267             _TROUBLE;
2268         }
2269         catch (CTimeException&) {}
2270     }}
2271 
2272     // Comparison
2273     {{
2274         CTimeout t0;
2275         CTimeout ti(CTimeout::eInfinite);
2276         CTimeout t1(123.4);
2277         CTimeout t2(123.45);
2278         CTimeout t3(123.4);
2279 
2280         // Compare finite timeouts
2281         assert(t1 != t2);
2282         assert(t1 == t3);
2283         assert(t1 <  t2);
2284         assert(t2 >  t1);
2285         assert(t1 <= t2);
2286         assert(t2 >= t2);
2287 
2288         // Compare infinite timeout
2289         assert(t1 >  tmo_zero);
2290         assert(t1 <  tmo_infinite);
2291         assert(t1 <= tmo_infinite);
2292         assert(!(t1 > tmo_infinite));
2293         assert(ti == tmo_infinite);
2294         assert(tmo_infinite == tmo_infinite);
2295 
2296         // Default timeout is almost not comparable
2297         try {
2298             assert(t0 == tmo_default);
2299             _TROUBLE;
2300         }
2301         catch (CTimeException&) {}
2302         try {
2303             assert(t1 < tmo_default);
2304             _TROUBLE;
2305         }
2306         catch (CTimeException&) {}
2307         try {
2308             assert(tmo_default == tmo_default);
2309             _TROUBLE;
2310         }
2311         catch (CTimeException&) {}
2312         try {
2313             assert(tmo_default == tmo_infinite);
2314             _TROUBLE;
2315         }
2316         catch (CTimeException&) {}
2317         try {
2318             assert(tmo_default != tmo_infinite);
2319             _TROUBLE;
2320         }
2321         catch (CTimeException&) {}
2322         try {
2323             assert(t1 != tmo_default);
2324             _TROUBLE;
2325         }
2326         catch (CTimeException&) {}
2327         try {
2328             assert(tmo_default > tmo_zero);
2329             _TROUBLE;
2330         }
2331         catch (CTimeException&) {}
2332         try {
2333             assert(tmo_default < tmo_infinite);
2334             _TROUBLE;
2335         }
2336         catch (CTimeException&) {}
2337         try {
2338             assert(tmo_zero < tmo_default);
2339             _TROUBLE;
2340         }
2341         catch (CTimeException&) {}
2342         try {
2343             assert(tmo_infinite > tmo_default);
2344             _TROUBLE;
2345         }
2346         catch (CTimeException&) {}
2347 
2348         // Only >= and <= can be applied in some cases
2349         assert(tmo_infinite >= tmo_default);
2350         assert(tmo_default  <= tmo_infinite);
2351         assert(tmo_default  >= tmo_zero);
2352         assert(tmo_zero     <= tmo_default);
2353     }}
2354 
2355     // Assignment
2356     {{
2357         CTimeout t1(1.23);
2358         CTimeout t2(4.56);
2359         t1 = t2;
2360         assert(t1 == t2);
2361         t1 = tmo_default;
2362         assert(t1.IsDefault());
2363         try {
2364             // assert(t1 != t2);
2365             (void)(t1 != t2);
2366             _TROUBLE;
2367         }
2368         catch (CTimeException&) {}
2369     }}
2370 }
2371 
2372 
2373 //============================================================================
2374 //
2375 // DemoStopWatch
2376 //
2377 //============================================================================
2378 
s_DemoStopWatch(void)2379 static void s_DemoStopWatch(void)
2380 {
2381     for ( int t = 0; t < 2; ++t ) {
2382         CStopWatch sw;
2383         assert(!sw.IsRunning());
2384         assert(sw.Elapsed() == 0);
2385         if ( t == 0 ) {
2386             sw.Start();
2387         }
2388         else {
2389             assert(sw.Restart() == 0);
2390         }
2391         assert(sw.IsRunning());
2392         sw.SetFormat("S.n");
2393 
2394         CNcbiOstrstream s;
2395         for (int i=0; i<10; i++) {
2396             s << sw << endl;
2397         }
2398         assert(sw.IsRunning());
2399         sw.Stop();
2400         assert(!sw.IsRunning());
2401         SleepMilliSec(500);
2402         sw.Start();
2403         for (int i=0; i<10; i++) {
2404             s << sw << endl;
2405         }
2406         //ERR_POST(Note << (string)CNcbiOstrstreamToString(s));
2407     }
2408 }
2409 
2410 
2411 //============================================================================
2412 //
2413 // MAIN
2414 //
2415 //============================================================================
2416 
main()2417 int main()
2418 {
2419     // Set err.-posting and tracing to maximum
2420     SetDiagTrace(eDT_Enable);
2421     SetDiagPostFlag(eDPF_All);
2422     SetDiagPostLevel(eDiag_Info);
2423 
2424     // Reinit global timezone variables
2425     NcbiSys_tzset();
2426 
2427     // Run tests
2428     try {
2429         s_TestMisc();
2430         s_TestFormats();
2431         s_TestUTC();
2432         #if ENABLE_SPEED_TESTS
2433             s_TestUTCSpeed();
2434         #endif
2435         s_TestTimeSpan();
2436         s_TestTimeSpan_AsSmartString();
2437         s_TestTimeSpan_AssignFromSmartString();
2438         s_TestTimeout();
2439         s_DemoStopWatch();
2440     } catch (CException& e) {
2441         ERR_FATAL(e);
2442     }
2443     // Success
2444     return 0;
2445 }
2446