NCBI C++ ToolKit
ncbitime.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: ncbitime.cpp 102404 2024-05-01 14:04:19Z 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  *
29  */
30 
31 #include <ncbi_pch.hpp>
32 #include <corelib/ncbitime.hpp>
33 #include <corelib/ncbimtx.hpp>
34 #include <corelib/ncbithr.hpp>
36 #include <corelib/ncbi_limits.h>
37 #include <corelib/error_codes.hpp>
38 #include <stdlib.h>
39 #include <limits>
40 
41 #if defined(NCBI_OS_MSWIN)
42 # include <windows.h>
43 #elif defined(NCBI_OS_UNIX)
44 # include <sys/time.h>
45 #endif
46 
47 
48 // The current difference in seconds between UTC and local time on this computer.
49 // UTC = local time + TimeZone()
50 #if defined(__CYGWIN__) || defined(NCBI_COMPILER_MSVC)
51 # define TimeZone() _timezone
52 # define Daylight() _daylight
53 # define TZName() _tzname
54 #else
55 # define TimeZone() timezone
56 # define Daylight() daylight
57 # define TZName() tzname
58 #endif
59 
60 // Global timezone/daylight information is not available on selected platforms
61 #if defined(NCBI_OS_DARWIN) || defined(NCBI_OS_BSD)
62 # define NCBI_TIMEZONE_IS_UNDEFINED 1
63 #endif
64 
65 // The offset in seconds of daylight saving time.
66 // 1 hour for most time zones.
67 #if defined(NCBI_COMPILER_MSVC)
68 # define DSTBias() _dstbias
69 #else
70 # define DSTBias() -3600
71 #endif
72 
73 
74 #define NCBI_USE_ERRCODE_X Corelib_Util
75 
76 
78 
79 
80 // Protective mutex
81 DEFINE_STATIC_MUTEX(s_TimeMutex);
82 DEFINE_STATIC_MUTEX(s_TimeAdjustMutex);
83 DEFINE_STATIC_MUTEX(s_FastLocalTimeMutex);
84 
85 // Store global time/timespan formats in TLS
89 
90 // Global quick and dirty getter of local time
92 
93 
94 //============================================================================
95 
96 // Number of days per month
97 static int s_DaysInMonth[12] = {
98  31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
99 };
100 
101 // Month names
102 static const char* kMonthAbbr[12] = {
103  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
104  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
105 };
106 static const char* kMonthFull[12] = {
107  "January", "February", "March", "April", "May", "June",
108  "July", "August", "September", "October", "November", "December"
109 };
110 
111 // Day of week names
112 static const char* kWeekdayAbbr[7] = {
113  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
114 };
115 static const char* kWeekdayFull [7] = {
116  "Sunday", "Monday", "Tuesday", "Wednesday",
117  "Thursday", "Friday", "Saturday"
118 };
119 
120 // Default value for time/timespan format
121 static const char* kDefaultFormatTime = "M/D/Y h:m:s";
122 static const char* kDefaultFormatSpan = "-S.n";
123 static const char* kDefaultFormatSpanIn = "-G"; // default CTimeSpan init format
124 static const char* kDefaultFormatStopWatch = "S.n";
125 
126 // Set of the checked format symbols.
127 // For CStopWatch class the format symbols are equal
128 // to kFormatSymbolsSpan also.
129 static const char* kFormatSymbolsTime = "yYMbBDdhHmsSlrgGzZwWpPo";
130 static const char* kFormatSymbolsSpan = "-dhHmMsSnNgG";
131 
132 // Character used to escape formatted symbols.
133 const char kFormatEscapeSymbol = '$';
134 
135 
136 // Macro to check range for time components.
137 // See also:
138 // CTime::m_Data
139 // CTime::IsValid
140 // CTime::Set*() methods
141 
142 #define CHECK_RANGE_EXCEPTION(value, what, min, max) \
143  if ( value < min || value > max ) { \
144  NCBI_THROW(CTimeException, eArgument, \
145  what " value '" + \
146  NStr::Int8ToString((Int8)value) + "' is out of range"); \
147  }
148 
149 #define CHECK_RANGE2(value, what, min, max, err_action) \
150  if ( value < min || value > max ) { \
151  if ( err_action == eErr_Throw ) { \
152  NCBI_THROW(CTimeException, eArgument, \
153  what " value '" + \
154  NStr::Int8ToString((Int8)value) + "' is out of range"); \
155  } else { return false; } \
156  }
157 
158 #define CHECK_RANGE_YEAR(value) CHECK_RANGE_EXCEPTION(value, "Year", 1583, kMax_Int)
159 #define CHECK_RANGE_MONTH(value) CHECK_RANGE_EXCEPTION(value, "Month", 1, 12)
160 #define CHECK_RANGE_DAY(value) CHECK_RANGE_EXCEPTION(value, "Day", 1, 31)
161 #define CHECK_RANGE_HOUR(value) CHECK_RANGE_EXCEPTION(value, "Hour", 0, 23)
162 #define CHECK_RANGE_MIN(value) CHECK_RANGE_EXCEPTION(value, "Minute", 0, 59)
163 #define CHECK_RANGE_SEC(value) CHECK_RANGE_EXCEPTION(value, "Second", 0, 61)
164 #define CHECK_RANGE_NSEC(value) CHECK_RANGE_EXCEPTION(value, "Nanosecond", 0, kNanoSecondsPerSecond - 1)
165 
166 #define CHECK_RANGE2_YEAR(value, err) CHECK_RANGE2(value, "Year", 1583, kMax_Int, err)
167 #define CHECK_RANGE2_MONTH(value, err) CHECK_RANGE2(value, "Month", 1, 12, err)
168 #define CHECK_RANGE2_DAY(value, err) CHECK_RANGE2(value, "Day", 1, 31, err)
169 #define CHECK_RANGE2_HOUR24(value, err) CHECK_RANGE2(value, "Hour", 0, 23, err)
170 #define CHECK_RANGE2_HOUR12(value, err) CHECK_RANGE2(value, "Hour", 0, 12, err)
171 #define CHECK_RANGE2_MIN(value, err) CHECK_RANGE2(value, "Minute", 0, 59, err)
172 #define CHECK_RANGE2_SEC(value, err) CHECK_RANGE2(value, "Second", 0, 61, err)
173 #define CHECK_RANGE2_NSEC(value, err) CHECK_RANGE2(value, "Nanosecond", 0, kNanoSecondsPerSecond - 1, err)
174 
175 // Bitfilds setters (to avoid warnings)
176 
177 #define SET_YEAR(value) m_Data.year = static_cast<unsigned int>((value) & 0xFFF)
178 #define SET_MONTH(value) m_Data.month = static_cast<unsigned char>((value) & 0x0F)
179 #define SET_DAY(value) m_Data.day = static_cast<unsigned char>((value) & 0x1F)
180 #define SET_HOUR(value) m_Data.hour = static_cast<unsigned char>((value) & 0x1F)
181 #define SET_MIN(value) m_Data.min = static_cast<unsigned char>((value) & 0x3F)
182 #define SET_SEC(value) m_Data.sec = static_cast<unsigned char>((value) & 0x3F)
183 
184 
185 
186 //============================================================================
187 
188 // Get number of days in "date"
189 static unsigned s_Date2Number(const CTime& date)
190 {
191  if ( date.IsEmptyDate() ) {
192  NCBI_THROW(CTimeException, eArgument, "The date is empty");
193  }
194  unsigned d = date.Day();
195  unsigned m = date.Month();
196  unsigned y = date.Year();
197  unsigned c, ya;
198 
199  if (m > 2) {
200  m -= 3;
201  } else {
202  m += 9;
203  --y;
204  }
205  c = y / 100;
206  ya = y - 100 * c;
207 
208  return ((146097 * c) >> 2) + ((1461 * ya) >> 2) +
209  (153 * m + 2) / 5 + d + 1721119;
210 }
211 
212 
213 // Conversion number of days in date format
214 // timezone value compute on base <t>
215 static CTime s_Number2Date(unsigned num, const CTime& t)
216 {
217  unsigned d;
218  unsigned j = num - 1721119;
219  unsigned year;
220  unsigned day;
221  int month;
222 
223  year = (((j<<2) - 1) / 146097);
224  j = (j<<2) - 1 - 146097 * year;
225  d = (j>>2);
226  j = ((d<<2) + 3) / 1461;
227  d = (d<<2) + 3 - 1461 * j;
228  d = (d + 4) >> 2;
229  month = (5*d - 3) / 153;
230  d = 5*d - 3 - 153 * month;
231  day = (d + 5) / 5;
232  year = 100 * year + j;
233 
234  if (month < 10) {
235  month += 3;
236  } else {
237  month -= 9;
238  ++year;
239  }
240  // Construct new CTime object
241  return
242  CTime(year, month, day, t.Hour(), t.Minute(), t.Second(),
243  t.NanoSecond(), t.GetTimeZone(), t.GetTimeZonePrecision());
244 }
245 
246 
247 // Calc <value> + <offset> on module <bound>.
248 // Returns normalized value in <value>.
249 // The <major> will have a remainder after dividing.
250 static inline
251 void s_Offset(long *value, Int8 offset, long bound, int *major)
252 {
253  Int8 v = *value + offset;
254  *major += (int)(v / bound);
255  *value = (long)(v % bound);
256  if (*value < 0) {
257  *major -= 1;
258  *value += bound;
259  }
260 }
261 
262 
263 // Convert 'value' to string, append result to string 'str'.
264 static inline
265 void s_AddInt(string& str, long value)
266 {
267  const size_t size = CHAR_BIT * sizeof(value);
268  char buf[size];
269  size_t pos = size;
270  do {
271  buf[--pos] = char((value % 10) + '0');
272  value /= 10;
273  } while (value);
274  str.append(buf + pos, size - pos);
275 }
276 
277 
278 // Convert 'value' to string, add leading '0' to size 'len'.
279 // Append result to string 'str'.
280 static inline
281 void s_AddZeroPadInt(string& str, long value, size_t len, bool ignore_trailing_zeros = false)
282 {
283  _ASSERT(value >= 0);
284  _ASSERT((len > 0) && (len < 10));
285 
286  const size_t size = 9;
287  char buf[size];
288  memset(buf, '0', size);
289 
290  size_t pos = size;
291  do {
292  buf[--pos] = char((value % 10) + '0');
293  value /= 10;
294  } while (value);
295 
296  if (size - pos > len) {
297  len = size - pos;
298  }
299  char* p = buf + size - len;
300  if (ignore_trailing_zeros) {
301  for (; len > 1 && p[len-1] == '0'; --len) {}
302  }
303  str.append(p, len);
304 }
305 
306 
307 // Optimized variant of s_AddZeroPadInt() for len = 2.
308 static inline
309 void s_AddZeroPadInt2(string& str, long value)
310 {
311  _ASSERT((value >= 0) && (value <= 99));
312  char buf[2];
313  buf[1] = char((value % 10) + '0');
314  buf[0] = char((value / 10) + '0');
315  str.append(buf, 2);
316 }
317 
318 
319 
320 //============================================================================
321 //
322 // CTimeFormat
323 //
324 //============================================================================
325 
326 
328  : m_Flags(fDefault)
329 {
330  return;
331 }
332 
333 
335 {
336  *this = fmt;
337 }
338 
339 
341 {
342  SetFormat(fmt, flags);
343 }
344 
345 
347 {
348  SetFormat(fmt, flags);
349 }
350 
351 
352 void CTimeFormat::SetFormat(const string& fmt, TFlags flags)
353 {
354  // Check flags compatibility
355 
357  if ((flags & f) == f) {
358  NCBI_THROW(CTimeException, eArgument,
359  "Incompatible flags specified together: fFormat_Simple | fFormat_Ncbi");
360  }
361  if ((flags & f) == 0) {
362  flags |= fFormat_Simple; // default
363  }
364 
365  if ((flags & fMatch_Strict) && (flags & fMatch_Weak)) {
366  NCBI_THROW(CTimeException, eArgument,
367  "Incompatible flags specified together: fMatch_Strict | fMatch_Weak");
368  }
369  if ((flags & (fMatch_Strict | fMatch_Weak)) == 0) {
370  flags |= fMatch_Strict; // default
371  }
372 
373  m_Str = fmt;
374  m_Flags = flags;
375 }
376 
377 
379 {
380  if ( &fmt == this ) {
381  return *this;
382  }
383  m_Str = fmt.m_Str;
384  m_Flags = fmt.m_Flags;
385  return *this;
386 }
387 
388 
390 {
391  // Predefined time formats
392  static const char* s_Predefined[][2] =
393  {
394  {"Y", "$Y"},
395  {"Y-M", "$Y-$M"},
396  {"Y-M-D", "$Y-$M-$D"},
397  {"Y-M-DTh:m", "$Y-$M-$DT$h:$m"},
398  {"Y-M-DTh:m:s", "$Y-$M-$DT$h:$m:$s"},
399  {"Y-M-DTh:m:G", "$Y-$M-$DT$h:$m:$G"},
400  };
401  int fmt_type = (flags & fFormat_Ncbi) ? 1 : 0;
402  return CTimeFormat(s_Predefined[(int)fmt][(int)fmt_type], flags);
403 }
404 
405 
406 //============================================================================
407 //
408 // CTime
409 //
410 //============================================================================
411 
412 static string s_TimeDump(const CTime& time)
413 {
414  string out;
415  out.reserve(128);
416  out = string("[") +
417  "year=" + NStr::Int8ToString(time.Year()) + ", " +
418  "month=" + NStr::Int8ToString(time.Month()) + ", " +
419  "day=" + NStr::Int8ToString(time.Day()) + ", " +
420  "hour=" + NStr::Int8ToString(time.Hour()) + ", " +
421  "min=" + NStr::Int8ToString(time.Minute()) + ", " +
422  "sec=" + NStr::Int8ToString(time.Second()) + ", " +
423  "nanosec=" + NStr::Int8ToString(time.NanoSecond()) + ", " +
424  "tz=" + (time.IsUniversalTime() ? "UTC" : "Local") +
425  "]";
426  return out;
427 }
428 
429 
431 {
432  *this = t;
433 }
434 
435 
436 CTime::CTime(int year, int yearDayNumber,
438 {
439  memset(&m_Data, 0, sizeof(m_Data));
440  m_Data.tz = tz;
441  m_Data.tzprec = tzp;
442 
443  CTime t = CTime(year, 1, 1);
444  t.AddDay(yearDayNumber - 1);
445  m_Data.year = t.m_Data.year;
446  m_Data.month = t.m_Data.month;
447  m_Data.day = t.m_Data.day;
448 }
449 
450 
451 // Helper macro for x_Init() errors
452 #define X_INIT_ERROR(type, msg) \
453  if (err_action == eErr_Throw) { \
454  NCBI_THROW(CTimeException, type, msg); \
455  } else { \
456  return false; \
457  }
458 
459 // Skip white spaces
460 #define SKIP_SPACES(s) \
461  while (isspace((unsigned char)(*s))) ++s;
462 
463 
464 // The helper to check string with 'o' format symbol specified
466 {
468 
469  bool fmt(const char*& f) {
470  _ASSERT(f);
471  return m_Active = *f == 'o';
472  }
473  bool str(const char*& s) {
474  _ASSERT(s);
475  if (m_Active) {
476  if (*s != ':') return false;
477  ++s;
478  m_Active = false;
479  }
480  return true;
481  }
482 private:
483  bool m_Active;
484 };
485 
486 // The helper to compose string with 'o' format symbol specified
488 {
490 
491  void activate() {
492  m_Active = true;
493  }
494  void str(string& s) {
495  if (m_Active) {
496  s += ':';
497  m_Active = false;
498  }
499  }
500  bool active() const { return m_Active; }
501 
502 private:
503  bool m_Active;
504 };
505 
506 
507 bool CTime::x_Init(const string& str, const CTimeFormat& format, EErrAction err_action)
508 {
509  Clear();
510 
511  // Special case, always create empty CTime object if str is empty, ignoring format.
512  // See IsEmpty().
513  if ( str.empty() ) {
514  return true;
515  }
516 
517  // Use guard against accidental exceptions from other parts of API or NStr::,
518  // we do best to avoid exceptions if requested, but it is not alway possible
519  // to control all calling code from here, so just to be safe...
520  try {
521 
522  // For partially defined times use default values
523  bool is_year_present = false;
524  bool is_month_present = false;
525  bool is_day_present = false;
526  bool is_time_present = false;
527 
528  const string& fmt = format.GetString();
529  bool is_escaped_fmt = ((format.GetFlags() & CTimeFormat::fFormat_Simple) == 0);
530  bool is_escaped_symbol = false;
531 
532  const char* fff;
533  const char* sss = str.c_str();
534  bool adjust_needed = false;
535  long adjust_tz = 0;
536 
537  enum EHourFormat{
538  e24, eAM, ePM
539  };
540  EHourFormat hour_format = e24;
541  int weekday = -1;
542  bool is_12hour = false;
543 
544  // Used to check white spaces for fMatch_IgnoreSpaces
545  bool is_ignore_spaces = ((format.GetFlags() & CTimeFormat::fMatch_IgnoreSpaces) != 0);
546  bool is_format_space = false;
547  STzFormatCheck tz_fmt_check;
548 
549  for (fff = fmt.c_str(); *fff != '\0'; ++fff) {
550 
551  // White space processing -- except directly after escape symbols
552 
553  if (!is_escaped_symbol) {
554  // Skip space symbols in format string
555  if (isspace((unsigned char)(*fff))) {
556  is_format_space = true;
557  continue;
558  }
559  if (is_ignore_spaces) {
560  // Skip space symbols in time string also
561  SKIP_SPACES(sss);
562  } else {
563  // match spaces
564  if (isspace((unsigned char)(*sss))) {
565  if (is_format_space) {
566  // Skip space symbols in time string
567  SKIP_SPACES(sss);
568  } else {
569  break; // error: non-matching spaces
570  }
571  } else {
572  if (is_format_space) {
573  break; // error: non-matching spaces
574  }
575  }
576  is_format_space = false;
577  }
578  }
579 
580  // Skip preceding symbols for some formats
581  if (is_escaped_fmt && !is_escaped_symbol) {
582  if (*fff == kFormatEscapeSymbol) {
583  is_escaped_symbol = true;
584  continue;
585  }
586  }
587 
588  // Match non-format symbols
589 
590  if (is_escaped_fmt) {
591  if (!(is_escaped_symbol && *fff != kFormatEscapeSymbol)) {
592  // Match non-format symbols
593  if (*fff == *sss) {
594  ++sss;
595  continue;
596  }
597  break; // error: non-matching symbols
598  }
599  // format symbol found, process as usual
600  is_escaped_symbol = false;
601  } else {
602  // Regular non-escaped format, each symbol can be a format symbol.
603  // Check allowed format symbols
604  if (strchr(kFormatSymbolsTime, *fff) == 0) {
605  // Match non-format symbols
606  if (*fff == *sss) {
607  ++sss;
608  continue;
609  }
610  break; // error: non-matching symbols
611  }
612  }
613 
614  // Process format symbols
615 
616  // Month
617  if (*fff == 'b' || *fff == 'B') {
618  const char** name;
619  if (*fff == 'b') {
620  name = kMonthAbbr;
621  } else {
622  name = kMonthFull;
623  }
624  for (unsigned char i = 0; i < 12; ++i) {
625  size_t namelen = strlen(*name);
626  if (NStr::strncasecmp(sss, *name, namelen) == 0) {
627  sss += namelen;
628  SET_MONTH(i + 1);
629  break;
630  }
631  ++name;
632  }
633  is_month_present = true;
634  continue;
635  }
636 
637  // Day of week
638  if (*fff == 'w' || *fff == 'W') {
639  const char** day = (*fff == 'w') ? kWeekdayAbbr : kWeekdayFull;
640  for (unsigned char i = 0; i < 7; ++i) {
641  size_t len = strlen(*day);
642  if (NStr::strncasecmp(sss, *day, len) == 0) {
643  sss += len;
644  weekday = i;
645  break;
646  }
647  ++day;
648  }
649  continue;
650  }
651 
652  // Timezone (UTC time)
653  if (*fff == 'Z') {
654  if ((NStr::strncasecmp(sss, "UTC", 3) == 0) ||
655  (NStr::strncasecmp(sss, "GMT", 3) == 0) ||
656  (*sss == 'Z')) {
657  m_Data.tz = eUTC;
658  sss += ((*sss == 'Z') ? 1 : 3);
659  } else {
660  m_Data.tz = eLocal;
661  }
662  continue;
663  }
664 
665  // Timezone (local time in format '[GMT/UTC]+/-HHMM')
666  if (*fff == 'z' || tz_fmt_check.fmt(fff)) {
667  m_Data.tz = eUTC;
668  if ((NStr::strncasecmp(sss, "UTC", 3) == 0) ||
669  (NStr::strncasecmp(sss, "GMT", 3) == 0)) {
670  sss += 3;
671  }
672  SKIP_SPACES(sss);
673  int sign = (*sss == '+') ? 1 : ((*sss == '-') ? -1 : 0);
674  if ( sign ) {
675  ++sss;
676  } else {
677  sign = 1;
678  }
679  long x_hour = 0;
680  long x_min = 0;
681 
682  char value_str[3];
683  char* s = value_str;
684  for (size_t len = 2;
685  len && *sss && isdigit((unsigned char)(*sss));
686  --len) {
687  *s++ = *sss++;
688  }
689  *s = '\0';
690  try {
691  x_hour = NStr::StringToLong(value_str);
692  }
693  catch (const CStringException&) {
694  x_hour = 0;
695  }
696  try {
697  if ( *sss != '\0' ) {
698  if (!tz_fmt_check.str(sss)) {
699  break; // error: not matched format symbol ':'
700  }
701  s = value_str;
702  for (size_t len = 2;
703  len && *sss && isdigit((unsigned char)(*sss));
704  --len) {
705  *s++ = *sss++;
706  }
707  *s = '\0';
708  x_min = NStr::StringToLong(value_str,
710  }
711  }
712  catch (const CStringException&) {
713  x_min = 0;
714  }
715  adjust_needed = true;
716  adjust_tz = sign * (x_hour * 60 + x_min) * 60;
717  continue;
718  }
719 
720  // AM/PM modifier
721  if (*fff == 'p' || *fff == 'P') {
722  if (NStr::strncasecmp(sss, "AM", 2) == 0) {
723  hour_format = eAM;
724  sss += 2;
725  } else if (NStr::strncasecmp(sss, "PM", 2) == 0) {
726  hour_format = ePM;
727  sss += 2;
728  }
729  continue;
730  }
731 
732  // Other format symbols -- read the next data ingredient
733  char value_str[10];
734  char* s = value_str;
735  size_t len = 2;
736  switch (*fff) {
737  case 'Y': len = 4; break;
738  case 'S': len = 9; break;
739  case 'l': len = 3; break;
740  case 'r': len = 6; break;
741  }
742  for ( ; len && *sss && isdigit((unsigned char)(*sss)); --len) {
743  *s++ = *sss++;
744  }
745  *s = '\0';
746  long value = NStr::StringToLong(value_str);
747 
748  // Set time part
749  switch ( *fff ) {
750  case 'Y':
751  CHECK_RANGE2_YEAR(value, err_action);
752  SET_YEAR(value);
753  is_year_present = true;
754  break;
755  case 'y':
756  if (value >= 0 && value < 50) {
757  value += 2000;
758  } else if (value >= 50 && value < 100) {
759  value += 1900;
760  }
761  CHECK_RANGE2_YEAR(value, err_action);
762  SET_YEAR(value);
763  is_year_present = true;
764  break;
765  case 'M':
766  CHECK_RANGE2_MONTH(value, err_action);
767  SET_MONTH(value);
768  is_month_present = true;
769  break;
770  case 'D':
771  case 'd':
772  CHECK_RANGE2_DAY(value, err_action);
773  SET_DAY(value);
774  is_day_present = true;
775  break;
776  case 'h':
777  CHECK_RANGE2_HOUR24(value, err_action);
778  SET_HOUR(value);
779  is_time_present = true;
780  break;
781  case 'H':
782  CHECK_RANGE2_HOUR12(value, err_action);
783  SET_HOUR(value % 12);
784  is_12hour = true;
785  is_time_present = true;
786  break;
787  case 'm':
788  CHECK_RANGE2_MIN(value, err_action);
789  SET_MIN(value);
790  is_time_present = true;
791  break;
792  case 's':
793  CHECK_RANGE2_SEC(value, err_action);
794  SET_SEC(value);
795  is_time_present = true;
796  break;
797  case 'l':
798  CHECK_RANGE2_NSEC((Int8)value * 1000000, err_action);
799  m_Data.nanosec = (Int4)value * 1000000;
800  is_time_present = true;
801  break;
802  case 'r':
803  CHECK_RANGE2_NSEC((Int8)value * 1000, err_action);
804  m_Data.nanosec = (Int4)value * 1000;
805  is_time_present = true;
806  break;
807  case 'S':
808  CHECK_RANGE2_NSEC(value, err_action);
810  is_time_present = true;
811  break;
812  case 'g':
813  case 'G':
814  CHECK_RANGE2_SEC(value, err_action);
815  SET_SEC(value);
816  if ( *sss == '.' ) {
817  ++sss;
818  s = value_str;
819  // Limit fraction of second to 9 digits max,
820  // ignore all other digits in string if any.
821  for (size_t n = 9;
822  n && *sss && isdigit((unsigned char)(*sss)); --n) {
823  *s++ = *sss++;
824  }
825  *s = '\0';
826  value = NStr::StringToLong(value_str);
827  size_t n = strlen(value_str);
828  // 'n' cannot have more then 9 (max for nanoseconds) - see above.
829  _ASSERT(n <= 9);
830  for (; n < 9; ++n) {
831  value *= 10;
832  }
833  CHECK_RANGE2_NSEC(value, err_action);
835  // Ignore extra digits
836  while ( isdigit((unsigned char)(*sss)) ) {
837  ++sss;
838  }
839  }
840  is_time_present = true;
841  break;
842 
843  default:
844  X_INIT_ERROR(eFormat, "Format '" + fmt + "' has incorrect format symbol '" + *fff + "'");
845  }
846  }
847 
848  // Correct 12-hour time if needed
849  if (is_12hour && hour_format == ePM) {
850  SET_HOUR(m_Data.hour + 12);
851  }
852 
853  // Skip all remaining white spaces in the string
854  if (is_ignore_spaces) {
855  SKIP_SPACES(sss);
856  } else {
857  if (isspace((unsigned char)(*sss)) && is_format_space) {
858  SKIP_SPACES(sss);
859  }
860  // else { error: non-matching spaces -- processed below }
861  }
862 
863  if (*fff != '\0' &&
864  !(format.GetFlags() & CTimeFormat::fMatch_ShortTime)) {
865  X_INIT_ERROR(eFormat, "Time string '" + str +
866  "' is too short for time format '" + fmt + "'");
867  }
868  if (*sss != '\0' &&
869  !(format.GetFlags() & CTimeFormat::fMatch_ShortFormat)) {
870  X_INIT_ERROR(eFormat, "Time string '" + str +
871  "' is too long for time format '" + fmt + "'");
872  }
873  if (*fff != '\0' && *sss != '\0' &&
875  X_INIT_ERROR(eFormat, "Time string '" + str +
876  "' does not match time format '" + fmt + "'");
877  }
878 
879  // For partially defined times use default values
880  int ptcache = 0;
881  ptcache += (is_year_present ? 2000 : 1000);
882  ptcache += (is_month_present ? 200 : 100);
883  ptcache += (is_day_present ? 20 : 10);
884  ptcache += (is_time_present ? 2 : 1);
885 
886  // Use empty or current time to set missed time components
887  CTime current;
888  if ( !adjust_needed ) {
889  switch (ptcache) {
890  case 1222:
891  case 1221:
892  case 1211:
893  case 1121:
894  case 1122:
895  case 1112:
896  current.SetCurrent();
897  }
898  }
899  switch (ptcache) {
900  case 2211: // Y,M -> D = 1
901  m_Data.day = 1;
902  break;
903  case 2111: // Y -> M,D = 1
904  m_Data.month = 1;
905  m_Data.day = 1;
906  break;
907  case 1222: // M,D,time -> Y = current
908  case 1221: // M,D -> Y = current
909  m_Data.year = current.m_Data.year;
910  break;
911  case 1211: // M -> Y = current, D = 1
912  m_Data.year = current.m_Data.year;
913  m_Data.day = 1;
914  break;
915  case 1122: // D, time -> Y,M = current
916  case 1121: // D -> Y,M = current
917  m_Data.year = current.m_Data.year;
918  m_Data.month = current.m_Data.month;
919  break;
920  case 1112: // time -> Y,M,D = current
921  m_Data.year = current.m_Data.year;
922  m_Data.month = current.m_Data.month;
923  m_Data.day = current.m_Data.day;
924  break;
925  }
926 
927  // Check on errors for weekday
928  if (weekday != -1 && weekday != DayOfWeek()) {
929  X_INIT_ERROR(eConvert, "Invalid day of week " + NStr::IntToString(weekday));
930  }
931  // Validate time value
932  if ( !IsValid() ) {
933  X_INIT_ERROR(eConvert, "Unable to convert string '" + str + "' to CTime");
934  }
935  // Adjust time to universal (see 'z' format symbol above)
936  if ( adjust_needed ) {
937  AddSecond(-adjust_tz, CTime::eIgnoreDaylight);
938  }
939 
940  // see 'try' at the beginning of the method
941  } catch (const CException&) {
942  if (err_action == eErr_Throw) {
943  throw;
944  } else {
945  return false;
946  }
947  }
948  return true;
949 }
950 
951 
952 CTime::CTime(int year, int month, int day, int hour,
953  int minute, int second, long nanosecond,
955 {
956  memset(&m_Data, 0, sizeof(m_Data));
957 
958  CHECK_RANGE_YEAR(year);
959  CHECK_RANGE_MONTH(month);
960  CHECK_RANGE_DAY(day);
961  CHECK_RANGE_HOUR(hour);
962  CHECK_RANGE_MIN(minute);
963  CHECK_RANGE_SEC(second);
964  CHECK_RANGE_NSEC(nanosecond);
965 
966  SET_YEAR(year);
967  SET_MONTH(month);
968  SET_DAY(day);
969  SET_HOUR(hour);
970  SET_MIN(minute);
971  SET_SEC(second);
972 
973  m_Data.nanosec = (Int4)nanosecond;
974  m_Data.tz = tz;
975  m_Data.tzprec = tzp;
976  m_Data.adjTimeDiff = 0;
977 
978  if ( !IsValid() ) {
979  NCBI_THROW(CTimeException, eInvalid,
980  string("Invalid time ") + s_TimeDump(*this));
981  }
982 }
983 
984 
986 {
987  memset(&m_Data, 0, sizeof(m_Data));
988  m_Data.tz = tz;
989  m_Data.tzprec = tzp;
990  if (mode == eCurrent) {
991  SetCurrent();
992  }
993 }
994 
995 
997 {
998  memset(&m_Data, 0, sizeof(m_Data));
999  m_Data.tz = eUTC;
1000  m_Data.tzprec = tzp;
1001  SetTimeT(t);
1002 }
1003 
1004 
1005 CTime::CTime(const struct tm& t, ETimeZonePrecision tzp)
1006 {
1007  memset(&m_Data, 0, sizeof(m_Data));
1008  m_Data.tz = eLocal;
1009  m_Data.tzprec = tzp;
1010  SetTimeTM(t);
1011 }
1012 
1013 
1014 CTime::CTime(const string& str, const CTimeFormat& fmt,
1015  ETimeZone tz, ETimeZonePrecision tzp)
1016 {
1017  memset(&m_Data, 0, sizeof(m_Data));
1018  _ASSERT(eLocal > 0);
1019  _ASSERT(eUTC > 0);
1020  _ASSERT(eGmt > 0);
1021  if ( !m_Data.tz ) {
1022  m_Data.tz = tz;
1023  }
1024  m_Data.tzprec = tzp;
1025  if (fmt.IsEmpty()) {
1026  x_Init(str, GetFormat());
1027  } else {
1028  x_Init(str, fmt);
1029  }
1030 }
1031 
1032 
1033 bool CTime::ValidateString(const string& str, const CTimeFormat& fmt)
1034 {
1035  CTime t;
1036  return t.x_Init(str, fmt.IsEmpty() ? GetFormat() : fmt, eErr_NoThrow);
1037 }
1038 
1039 
1040 void CTime::SetYear(int year)
1041 {
1042  CHECK_RANGE_YEAR(year);
1043  SET_YEAR(year);
1044  int n_days = DaysInMonth();
1045  if ( m_Data.day > n_days ) {
1046  SET_DAY(n_days);
1047  }
1048  // Additional checks
1049  if ( !IsValid() ) {
1050  NCBI_THROW(CTimeException, eInvalid,
1051  "Unable to set year number '" +
1052  NStr::IntToString(year) + "'");
1053  }
1054 }
1055 
1056 
1057 void CTime::SetMonth(int month)
1058 {
1059  CHECK_RANGE_MONTH(month);
1060  SET_MONTH(month);
1061  int n_days = DaysInMonth();
1062  if ( m_Data.day > n_days ) {
1063  SET_DAY(n_days);
1064  }
1065  // Additional checks
1066  if ( !IsValid() ) {
1067  NCBI_THROW(CTimeException, eInvalid,
1068  "Unable to set month number '" +
1069  NStr::IntToString(month) + "'");
1070  }
1071 }
1072 
1073 
1074 void CTime::SetDay(int day)
1075 {
1076  CHECK_RANGE_DAY(day);
1077  int n_days = DaysInMonth();
1078  if ( day > n_days ) {
1079  SET_DAY(n_days);
1080  } else {
1081  SET_DAY(day);
1082  }
1083  // Additional checks
1084  if ( !IsValid() ) {
1085  NCBI_THROW(CTimeException, eInvalid,
1086  "Unable to set day number '" +
1087  NStr::IntToString(day) + "'");
1088  }
1089 }
1090 
1091 
1092 void CTime::SetHour(int hour)
1093 {
1094  CHECK_RANGE_HOUR(hour);
1095  SET_HOUR(hour);
1096 }
1097 
1098 
1099 void CTime::SetMinute(int minute)
1100 {
1101  CHECK_RANGE_MIN(minute);
1102  SET_MIN(minute);
1103 }
1104 
1105 
1106 void CTime::SetSecond(int second)
1107 {
1108  CHECK_RANGE_SEC(second);
1109  SET_SEC(second);
1110 }
1111 
1112 
1113 void CTime::SetMilliSecond(long millisecond)
1114 {
1115  CHECK_RANGE_NSEC(millisecond * 1000000);
1116  m_Data.nanosec = (Int4)millisecond * 1000000;
1117 }
1118 
1119 
1120 void CTime::SetMicroSecond(long microsecond)
1121 {
1122  CHECK_RANGE_NSEC(microsecond * 1000);
1123  m_Data.nanosec = (Int4)microsecond * 1000;
1124 }
1125 
1126 
1127 void CTime::SetNanoSecond(long nanosecond)
1128 {
1129  CHECK_RANGE_NSEC(nanosecond);
1130  m_Data.nanosec = (Int4)nanosecond;
1131 }
1132 
1133 
1134 int CTime::YearDayNumber(void) const
1135 {
1136  unsigned first = s_Date2Number(CTime(Year(), 1, 1));
1137  unsigned self = s_Date2Number(*this);
1138  _ASSERT(first <= self && self < first + (IsLeap() ? 366 : 365));
1139  return int(self - first + 1);
1140 }
1141 
1142 
1143 int CTime::YearWeekNumber(EDayOfWeek first_day_of_week) const
1144 {
1145  if ( IsEmptyDate() ) {
1146  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1147  }
1148  if (first_day_of_week > eSaturday) {
1149  NCBI_THROW(CTimeException, eArgument,
1150  "Day of week with value " +
1151  NStr::IntToString((int)first_day_of_week) +
1152  " is incorrect");
1153  }
1154 
1155  int week_num = 0;
1156  int wday = DayOfWeek();
1157 
1158  // Adjust day of week (from default Sunday)
1159  wday -= first_day_of_week;
1160  if (wday < 0) {
1161  wday += 7;
1162  }
1163 
1164  // Calculate week number
1165  int yday = YearDayNumber() - 1; // YearDayNumber() returns 1..366
1166  if (yday >= wday) {
1167  week_num = yday / 7;
1168  if ( (yday % 7) >= wday ) {
1169  ++week_num;
1170  }
1171  }
1172  // Adjust range from [0..53] to [1..54]
1173  return week_num + 1;
1174 }
1175 
1176 
1177 int CTime::MonthWeekNumber(EDayOfWeek first_day_of_week) const
1178 {
1179  CTime first_of_month(Year(), Month(), 1);
1180  int week_num_first = first_of_month.YearWeekNumber(first_day_of_week);
1181  int week_num_current = YearWeekNumber(first_day_of_week);
1182  return week_num_current - week_num_first + 1;
1183 }
1184 
1185 
1186 int CTime::DayOfWeek(void) const
1187 {
1188  if ( IsEmptyDate() ) {
1189  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1190  }
1191  int y = Year();
1192  int m = Month();
1193 
1194  y -= int(m < 3);
1195  return (y + y/4 - y/100 + y/400 + "-bed=pen+mad."[m] + Day()) % 7;
1196 }
1197 
1198 
1199 int CTime::DaysInMonth(void) const
1200 {
1201  if ( IsEmptyDate() ) {
1202  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1203  }
1204  int n_days = s_DaysInMonth[Month()-1];
1205  if (n_days == 0) {
1206  n_days = IsLeap() ? 29 : 28;
1207  }
1208  return n_days;
1209 }
1210 
1211 
1212 int CTime::MonthNameToNum(const string& month)
1213 {
1214  const char** name = month.length() == 3 ? kMonthAbbr : kMonthFull;
1215  for (int i = 0; i < 12; ++i) {
1216  if ( NStr::CompareNocase(month, name[i]) == 0 ) {
1217  return i+1;
1218  }
1219  }
1220  // Always throw exceptions here.
1221  // Next if statements avoid compilation warnings.
1222  if ( name ) {
1223  NCBI_THROW(CTimeException, eArgument,
1224  "Invalid month name '" + month + "'");
1225  }
1226  return -1;
1227 }
1228 
1229 
1230 string CTime::MonthNumToName(int month, ENameFormat fmt)
1231 {
1232  if (month < 1 || month > 12) {
1233  NCBI_THROW(CTimeException, eArgument,
1234  "Invalid month number " + NStr::IntToString(month));
1235  }
1236  --month;
1237  return fmt == eFull ? kMonthFull[month] : kMonthAbbr[month];
1238 }
1239 
1240 
1241 int CTime::DayOfWeekNameToNum(const string& day)
1242 {
1243  const char** name = day.length() == 3 ? kWeekdayAbbr : kWeekdayFull;
1244  for (int i = 0; i <= 6; ++i) {
1245  if (NStr::CompareNocase(day, name[i]) == 0) {
1246  return i;
1247  }
1248  }
1249  // Always throw exceptions here.
1250  // Next if statements avoid compilation warnings.
1251  if ( name ) {
1252  NCBI_THROW(CTimeException, eArgument,
1253  "Invalid day of week name '" + day + "'");
1254  }
1255  return -1;
1256 }
1257 
1258 
1260 {
1261  if (day < 0 || day > 6) {
1262  return kEmptyStr;
1263  }
1264  return fmt == eFull ? kWeekdayFull[day] : kWeekdayAbbr[day];
1265 }
1266 
1267 
1269 {
1270  // Here we do not need to delete a previous value stored in the TLS.
1271  // The TLS will destroy it using cleanup function.
1272  CTimeFormat* ptr = new CTimeFormat(fmt);
1273  s_TlsFormatTime.SetValue(ptr, CTlsBase::DefaultCleanup<CTimeFormat>);
1274 }
1275 
1276 
1278 {
1279  CTimeFormat fmt;
1280  CTimeFormat* ptr = s_TlsFormatTime.GetValue();
1281  if ( !ptr ) {
1283  } else {
1284  fmt = *ptr;
1285  }
1286  return fmt;
1287 }
1288 
1289 
1290 // Internal version without checks and locks
1291 time_t s_GetTimeT(const CTime& ct)
1292 {
1293  struct tm t;
1294 
1295  // Convert time to time_t value at base local time
1296 #if defined(HAVE_TIMEGM) || defined(NCBI_OS_DARWIN)
1297  t.tm_sec = ct.Second();
1298 #else
1299  // see below
1300  t.tm_sec = ct.Second() + (int)(ct.IsUniversalTime() ? -TimeZone() : 0);
1301 #endif
1302  t.tm_min = ct.Minute();
1303  t.tm_hour = ct.Hour();
1304  t.tm_mday = ct.Day();
1305  t.tm_mon = ct.Month()-1;
1306  t.tm_year = ct.Year()-1900;
1307  t.tm_isdst = -1;
1308 #if defined(NCBI_OS_DARWIN)
1309  time_t tt = mktime(&t);
1310  if ( tt == (time_t)(-1L) ) {
1311  return tt;
1312  }
1313  return ct.IsUniversalTime() ? tt+t.tm_gmtoff : tt;
1314 #elif defined(HAVE_TIMEGM)
1315  return ct.IsUniversalTime() ? timegm(&t) : mktime(&t);
1316 #else
1317  struct tm *ttemp;
1318  time_t timer;
1319  timer = mktime(&t);
1320  if ( timer == (time_t)(-1L) ) {
1321  return timer;
1322  }
1323 
1324  // Correct timezone for UTC time
1325  if ( ct.IsUniversalTime() ) {
1326 
1327  // Somewhat hackish, but seem to work.
1328  // Local time is ambiguous and we don't know is DST on
1329  // for specified date/time or not, so we call mktime()
1330  // second time for GMT/UTC time:
1331  // 1st - to get correct value of TimeZone().
1332  // 2nd - to get value of "timer".
1333 
1334  t.tm_sec = ct.Second() - (int)TimeZone();
1335  t.tm_min = ct.Minute();
1336  t.tm_hour = ct.Hour();
1337  t.tm_mday = ct.Day();
1338  t.tm_mon = ct.Month()-1;
1339  t.tm_year = ct.Year()-1900;
1340  t.tm_isdst = -1;
1341  timer = mktime(&t);
1342  if ( timer == (time_t)(-1L) ) {
1343  return timer;
1344  }
1345 
1346 # if defined(HAVE_LOCALTIME_R)
1347  struct tm temp;
1348  localtime_r(&timer, &temp);
1349  ttemp = &temp;
1350 # else
1351  ttemp = localtime(&timer);
1352 # endif
1353  if (ttemp == NULL)
1354  return (time_t)(-1L);
1355  if (ttemp->tm_isdst > 0 && Daylight())
1356  timer -= DSTBias(); // +1 hour in common case
1357  }
1358  return timer;
1359 #endif
1360 }
1361 
1362 
1363 // Internal version without checks and locks
1364 bool s_IsDST(const CTime& ct)
1365 {
1366  time_t timer = s_GetTimeT(ct);
1367  if (timer == (time_t)(-1L)) {
1368  return false;
1369  }
1370  struct tm *t;
1371 # if defined(HAVE_LOCALTIME_R)
1372  struct tm temp;
1373  localtime_r(&timer, &temp);
1374  t = &temp;
1375 # else
1376  t = localtime(&timer);
1377 # endif
1378  if (t == NULL) {
1379  return false;
1380  }
1381  return (t->tm_isdst > 0);
1382 }
1383 
1384 
1385 bool CTime::IsDST(void) const
1386 {
1387  if ( IsEmptyDate() ) {
1388  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1389  }
1390  // MT-Safe protect
1391  CMutexGuard LOCK(s_TimeMutex);
1392  return s_IsDST(*this);
1393 }
1394 
1395 
1396 time_t CTime::GetTimeT(void) const
1397 {
1398  if ( IsEmptyDate() ) {
1399  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1400  }
1401  // MT-Safe protect
1402  CMutexGuard LOCK(s_TimeMutex);
1403  return s_GetTimeT(*this);
1404 }
1405 
1406 
1407 struct tm CTime::GetTimeTM(void) const
1408 {
1409  CTime lt = GetLocalTime();
1410  struct tm t;
1411  t.tm_sec = lt.Second();
1412  t.tm_min = lt.Minute();
1413  t.tm_hour = lt.Hour();
1414  t.tm_mday = lt.Day();
1415  t.tm_mon = lt.Month()-1;
1416  t.tm_year = lt.Year()-1900;
1417  t.tm_wday = lt.DayOfWeek();
1418  t.tm_yday = -1;
1419  t.tm_isdst = -1;
1420  return t;
1421 }
1422 
1423 
1424 CTime& CTime::SetTimeTM(const struct tm& t)
1425 {
1426  CHECK_RANGE_YEAR (t.tm_year + 1900);
1427  CHECK_RANGE_MONTH (t.tm_mon + 1);
1428  CHECK_RANGE_DAY (t.tm_mday);
1429  CHECK_RANGE_HOUR (t.tm_hour);
1430  CHECK_RANGE_MIN (t.tm_min);
1431  CHECK_RANGE_SEC (t.tm_sec);
1432 
1433  SET_YEAR (t.tm_year + 1900);
1434  SET_MONTH (t.tm_mon + 1);
1435  SET_DAY (t.tm_mday);
1436  SET_HOUR (t.tm_hour);
1437  SET_MIN (t.tm_min);
1438  SET_SEC (t.tm_sec);
1439 
1440  m_Data.nanosec = 0;
1441  m_Data.tz = eLocal;
1442  //m_Data.tzprec -- not changed;
1443  m_Data.adjTimeDiff = 0;
1444 
1445  if ( !IsValid() ) {
1446  NCBI_THROW(CTimeException, eInvalid,
1447  "Invalid time " + s_TimeDump(*this));
1448  }
1449  return *this;
1450 }
1451 
1452 
1453 
1455 {
1456  CTime t = GetLocalTime();
1457  unsigned first = s_Date2Number(CTime(1900, 1, 1));
1458  unsigned curr = s_Date2Number(t);
1459 
1460  TDBTimeU dbt;
1461  dbt.days = (Uint2)(curr - first);
1462  dbt.time = (Uint2)(t.Hour() * 60 + t.Minute());
1463  return dbt;
1464 }
1465 
1466 
1468 {
1469  CTime t = GetLocalTime();
1470  unsigned first = s_Date2Number(CTime(1900, 1, 1));
1471  unsigned curr = s_Date2Number(t);
1472 
1473  TDBTimeI dbt;
1474  dbt.days = (Int4)(curr - first);
1475  dbt.time = (Int4)((t.Hour() * 3600 + t.Minute() * 60 + t.Second()) * 300 +
1476  (Int8(t.NanoSecond()) * 300) / kNanoSecondsPerSecond);
1477  return dbt;
1478 }
1479 
1480 
1482 {
1483  // Local time - 1/1/1900 00:00:00.0
1484  CTime time(1900, 1, 1, 0, 0, 0, 0, eLocal);
1485 
1487  time.AddDay(t.days);
1488  time.AddMinute(t.time);
1489  time.ToTime(GetTimeZone());
1490 
1491  *this = time;
1492  return *this;
1493 }
1494 
1495 
1497 {
1498  // Local time - 1/1/1900 00:00:00.0
1499  CTime time(1900, 1, 1, 0, 0, 0, 0, eLocal);
1500 
1502  time.AddDay(t.days);
1503  time.AddSecond(t.time / 300);
1504  time.AddNanoSecond(long((Int8(t.time % 300) * kNanoSecondsPerSecond)/300));
1505  time.ToTime(GetTimeZone());
1506 
1507  *this = time;
1508  return *this;
1509 }
1510 
1511 
1512 string CTime::AsString(const CTimeFormat& format, TSeconds out_tz) const
1513 {
1514  if ( !IsValid() ) {
1515  NCBI_THROW(CTimeException, eInvalid,
1516  "Invalid time " + s_TimeDump(*this));
1517  }
1518  if ( IsEmpty() ) {
1519  return kEmptyStr;
1520  }
1521 
1522  // Time format
1523 
1524  string fmt;
1525  CTimeFormat::TFlags fmt_flags;
1526  if ( format.IsEmpty() ) {
1527  CTimeFormat f = GetFormat();
1528  fmt = f.GetString();
1529  fmt_flags = f.GetFlags();
1530  } else {
1531  fmt = format.GetString();
1532  fmt_flags = format.GetFlags();
1533  }
1534  bool is_escaped = ((fmt_flags & CTimeFormat::fFormat_Simple) == 0);
1535  bool is_format_symbol = !is_escaped;
1536  STzFormatMake tz_fmt_make;
1537 
1538 
1539  // Adjust time to timezone if necessary
1540 
1541  const CTime* t = this;
1542  CTime* t_out = 0;
1543 
1544 #if defined(NCBI_TIMEZONE_IS_UNDEFINED)
1545  if (out_tz != eCurrentTimeZone) {
1546  ERR_POST_X(4, "Output timezone is unsupported on this platform");
1547  }
1548 #else
1549  // Cache some not MT-safe values, so we can unlock mutex as fast as possible
1550  TSeconds x_timezone = 0, x_dstbias = 0;
1551  bool x_isdst = false;
1552 
1553  // Speedup:: timezone information can be used if defined or for 'z' format symbols.
1554  if (out_tz != eCurrentTimeZone || fmt.find('z') != NPOS)
1555  {{
1556  CMutexGuard LOCK(s_TimeMutex);
1557  // Adjust time for output timezone (should be MT protected)
1558  {{
1559  if (out_tz != eCurrentTimeZone) {
1560  if (out_tz != TimeZone()) {
1561  t_out = new CTime(*this);
1562  t_out->AddSecond(TimeZone() - out_tz);
1563  t = t_out;
1564  }
1565  }
1566  }}
1567  // Cache values - now we should avoid to use functions specified at right side.
1568  x_timezone = TimeZone();
1569  x_dstbias = DSTBias();
1570  x_isdst = s_IsDST(*this);
1571  }}
1572 #endif
1573 
1574  string str;
1575  str.reserve(64); // try to save on memory allocations
1576 
1577  ITERATE(string, it, fmt) {
1578 
1579  if ( !is_format_symbol ) {
1580  if ( *it == kFormatEscapeSymbol ) {
1581  is_format_symbol = true;
1582  } else {
1583  str += *it;
1584  }
1585  continue;
1586  }
1587  if ( is_escaped ) {
1588  is_format_symbol = false;
1589  }
1590  switch ( *it ) {
1591  case 'y': s_AddZeroPadInt2(str, t->Year() % 100); break;
1592  case 'Y': s_AddZeroPadInt(str, t->Year(), 4); break;
1593  case 'M': s_AddZeroPadInt2(str, t->Month()); break;
1594  case 'b': str += kMonthAbbr[t->Month()-1]; break;
1595  case 'B': str += kMonthFull[t->Month()-1]; break;
1596  case 'D': s_AddZeroPadInt2(str, t->Day()); break;
1597  case 'd': s_AddZeroPadInt(str, t->Day(),1); break;
1598  case 'h': s_AddZeroPadInt2(str, t->Hour()); break;
1599  case 'H': s_AddZeroPadInt2(str, (t->Hour()+11) % 12+1);
1600  break;
1601  case 'm': s_AddZeroPadInt2(str, t->Minute()); break;
1602  case 's': s_AddZeroPadInt2(str, t->Second()); break;
1603  case 'l': s_AddZeroPadInt(str, t->NanoSecond() / 1000000, 3);
1604  break;
1605  case 'r': s_AddZeroPadInt(str, t->NanoSecond() / 1000, 6);
1606  break;
1607  case 'S': s_AddZeroPadInt(str, t->NanoSecond(), 9); break;
1608  case 'G': s_AddZeroPadInt2(str, t->Second());
1609  str += ".";
1610  s_AddZeroPadInt(str, t->NanoSecond(), 9, true);
1611  break;
1612  case 'g': s_AddInt(str, t->Second());
1613  str += ".";
1614  s_AddZeroPadInt(str, t->NanoSecond(), 9, true);
1615  break;
1616  case 'p': str += ( t->Hour() < 12) ? "am" : "pm" ; break;
1617  case 'P': str += ( t->Hour() < 12) ? "AM" : "PM" ; break;
1618  case 'o': tz_fmt_make.activate(); /* FALL THROUGH */
1619  case 'z': {
1620 #if defined(NCBI_TIMEZONE_IS_UNDEFINED)
1621  ERR_POST_X(5, "Format symbol 'z' is unsupported "
1622  "on this platform");
1623 #else
1624  if (!tz_fmt_make.active()) {
1625  str += (fmt_flags & CTimeFormat::fConf_UTC) ? "UTC" : "GMT";
1626  }
1627  if (IsUniversalTime()) {
1628  break;
1629  }
1630  TSeconds tz = out_tz;
1631  if (tz == eCurrentTimeZone) {
1632  tz = x_timezone;
1633  if (x_isdst) {
1634  tz += x_dstbias; // DST in effect
1635  }
1636  }
1637  str += (tz > 0) ? '-' : '+';
1638  if (tz < 0) tz = -tz;
1639  tz /= 60;
1640  s_AddZeroPadInt2(str, (long)(tz / 60));
1641  tz_fmt_make.str(str);
1642  s_AddZeroPadInt2(str, (long)(tz % 60));
1643 #endif
1644  break;
1645  }
1646  case 'Z': if (IsUniversalTime()) {
1647  str += (fmt_flags & CTimeFormat::fConf_UTC) ? "UTC" : "GMT";
1648  }
1649  break;
1650  case 'w': str += kWeekdayAbbr[t->DayOfWeek()]; break;
1651  case 'W': str += kWeekdayFull[t->DayOfWeek()]; break;
1652  default : str += *it; break;
1653  }
1654  }
1655  // Free used memory
1656  if ( t_out ) {
1657  delete t_out;
1658  }
1659  return str;
1660 }
1661 
1662 
1664 {
1665  // MT-Safe protect
1666  CMutexGuard LOCK(s_TimeMutex);
1667  x_SetTime(value);
1668  return *this;
1669 }
1670 
1671 
1672 void CTime::GetCurrentTimeT(time_t* sec, long* nanosec)
1673 {
1674  _ASSERT(sec);
1675  long ns;
1676 #if defined(NCBI_OS_MSWIN)
1677  FILETIME systime;
1678  Uint8 systemp;
1679 
1680  GetSystemTimeAsFileTime(&systime);
1681 
1682  systemp = systime.dwHighDateTime;
1683  systemp <<= 32;
1684  systemp |= systime.dwLowDateTime;
1685  *sec = systemp / 10000000 - NCBI_CONST_UINT8(11644473600);
1686  ns = (systemp % 10000000) * 100;
1687 #elif defined(NCBI_OS_UNIX)
1688  struct timeval tp;
1689  if (gettimeofday(&tp,0) == 0) {
1690  *sec = tp.tv_sec;
1691  ns = tp.tv_usec * (kNanoSecondsPerSecond / kMicroSecondsPerSecond);
1692  } else {
1693  *sec = (time_t)(-1L);
1694  ns = 0;
1695  }
1696 #else
1697  *sec = time(0);
1698  ns = 0;
1699 #endif
1700  if (*sec == (time_t)(-1L)) {
1701  NCBI_THROW(CTimeException, eConvert,
1702  "Unable to get time value");
1703  }
1704  if (nanosec) {
1705  *nanosec = ns;
1706  }
1707 }
1708 
1709 
1711 {
1712  time_t timer;
1713  long ns = 0;
1714 
1715  // Get time with nanoseconds
1716  if ( value ) {
1717  timer = *value;
1718  } else {
1719  GetCurrentTimeT(&timer, &ns);
1720  }
1721 
1722  // Bind values to internal variables
1723  struct tm *t;
1724 
1725 #ifdef HAVE_LOCALTIME_R
1726  struct tm temp;
1727  if (GetTimeZone() == eLocal) {
1728  localtime_r(&timer, &temp);
1729  } else {
1730  gmtime_r(&timer, &temp);
1731  }
1732  t = &temp;
1733 #else
1734  t = ( GetTimeZone() == eLocal ) ? localtime(&timer) : gmtime(&timer);
1735  if ( !t ) {
1736  // Error was detected: incorrect timer value or system error
1737  NCBI_THROW(CTimeException, eConvert,
1738  "localtime/gmtime error, possible incorrect time_t value");
1739  }
1740 #endif
1741  m_Data.adjTimeDiff = 0;
1742 
1743  SET_YEAR (t->tm_year + 1900);
1744  SET_MONTH (t->tm_mon + 1);
1745  SET_DAY (t->tm_mday);
1746  SET_HOUR (t->tm_hour);
1747  SET_MIN (t->tm_min);
1748  SET_SEC (t->tm_sec);
1749 
1750  CHECK_RANGE_NSEC(ns);
1751  m_Data.nanosec = (Int4)ns;
1752 
1753  return *this;
1754 }
1755 
1756 
1758 {
1759  if ( IsEmptyDate() ) {
1760  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1761  }
1762  if ( !months ) {
1763  return *this;
1764  }
1765  CTime *pt = 0;
1766  bool aflag = false;
1767  if ((adl == eAdjustDaylight) && x_NeedAdjustTime()) {
1768  pt = new CTime(*this);
1769  if ( !pt ) {
1770  NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
1771  }
1772  aflag = true;
1773  }
1774  long newMonth = Month() - 1;
1775  int newYear = Year();
1776  s_Offset(&newMonth, months, 12, &newYear);
1777  SET_YEAR(newYear);
1778  SET_MONTH(newMonth + 1);
1779  x_AdjustDay();
1780  if ( aflag ) {
1781  x_AdjustTime(*pt);
1782  delete pt;
1783  }
1784  return *this;
1785 }
1786 
1787 
1789 {
1790  if ( IsEmptyDate() ) {
1791  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1792  }
1793  if ( !days ) {
1794  return *this;
1795  }
1796  CTime *pt = 0;
1797  bool aflag = false;
1798  if ((adl == eAdjustDaylight) && x_NeedAdjustTime()) {
1799  pt = new CTime(*this);
1800  if ( !pt ) {
1801  NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
1802  }
1803  aflag = true;
1804  }
1805 
1806  // Make necessary object
1807  *this = s_Number2Date(s_Date2Number(*this) + days, *this);
1808 
1809  // If need, make adjustment time specially
1810  if ( aflag ) {
1811  x_AdjustTime(*pt);
1812  delete pt;
1813  }
1814  return *this;
1815 }
1816 
1817 
1818 // Parameter <shift_time> access or denied use time shift in process
1819 // adjust hours.
1820 CTime& CTime::x_AddHour(int hours, EDaylight adl, bool shift_time)
1821 {
1822  if ( IsEmptyDate() ) {
1823  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1824  }
1825  if ( !hours ) {
1826  return *this;
1827  }
1828  CTime *pt = 0;
1829  bool aflag = false;
1830  if ((adl == eAdjustDaylight) && x_NeedAdjustTime()) {
1831  pt = new CTime(*this);
1832  if ( !pt ) {
1833  NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
1834  }
1835  aflag = true;
1836  }
1837  int dayOffset = 0;
1838  long newHour = Hour();
1839  s_Offset(&newHour, hours, 24, &dayOffset);
1840  SET_HOUR(newHour);
1841  AddDay(dayOffset, eIgnoreDaylight);
1842  if ( aflag ) {
1843  x_AdjustTime(*pt, shift_time);
1844  delete pt;
1845  }
1846  return *this;
1847 }
1848 
1849 
1851 {
1852  if ( IsEmptyDate() ) {
1853  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1854  }
1855  if ( !minutes ) {
1856  return *this;
1857  }
1858  CTime *pt = 0;
1859  bool aflag = false;
1860  if ((adl == eAdjustDaylight) && x_NeedAdjustTime()) {
1861  pt = new CTime(*this);
1862  if ( !pt ) {
1863  NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
1864  }
1865  aflag = true;
1866  }
1867  int hourOffset = 0;
1868  long newMinute = Minute();
1869  s_Offset(&newMinute, minutes, 60, &hourOffset);
1870  SET_MIN(newMinute);
1871  AddHour(hourOffset, eIgnoreDaylight);
1872  if ( aflag ) {
1873  x_AdjustTime(*pt);
1874  delete pt;
1875  }
1876  return *this;
1877 }
1878 
1879 
1881 {
1882  if ( IsEmptyDate() ) {
1883  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1884  }
1885  if ( !seconds ) {
1886  return *this;
1887  }
1888  int minuteOffset = 0;
1889  long newSecond = Second();
1890  s_Offset(&newSecond, seconds, 60, &minuteOffset);
1891  SET_SEC(newSecond);
1892  return AddMinute(minuteOffset, adl);
1893 }
1894 
1895 
1897 {
1898  if ( IsEmptyDate() ) {
1899  NCBI_THROW(CTimeException, eArgument, "The date is empty");
1900  }
1901  if ( !ns ) {
1902  return *this;
1903  }
1904  int secondOffset = 0;
1905  long newNanoSecond = NanoSecond();
1906  s_Offset(&newNanoSecond, ns, kNanoSecondsPerSecond, &secondOffset);
1907  m_Data.nanosec = (Int4)newNanoSecond;
1908  return AddSecond(secondOffset);
1909 }
1910 
1911 
1913 {
1914  if ( ts.GetSign() == eZero ) {
1915  return *this;
1916  }
1919  return *this;
1920 }
1921 
1922 
1924 {
1925  if ( IsEmptyDate() ) {
1926  return *this;
1927  }
1928  switch (precision) {
1929  case eRound_Day:
1930  if ( m_Data.hour >= 12 )
1931  AddDay(1, adl);
1932  break;
1933  case eRound_Hour:
1934  if ( m_Data.min >= 30 )
1935  AddHour(1, adl);
1936  break;
1937  case eRound_Minute:
1938  if ( m_Data.sec >= 30 )
1939  AddMinute(1, adl);
1940  break;
1941  case eRound_Second:
1943  AddSecond(1, adl);
1944  m_Data.nanosec = 0;
1945  break;
1946  case eRound_Millisecond:
1947  m_Data.nanosec =
1949  / 1000000 * 1000000;
1950  break;
1951  case eRound_Microsecond:
1952  m_Data.nanosec =
1954  / 1000 * 1000;
1955  break;
1956  default:
1957  NCBI_THROW(CTimeException, eArgument,
1958  "Rounding precision is out of range");
1959  }
1961  AddSecond(1, adl);
1962  m_Data.nanosec = 0;
1963  }
1964  // Clean time components with lesser precision
1966  return *this;
1967 }
1968 
1969 
1971 {
1972  // Clean time components with lesser precision
1973  switch (precision) {
1974  case eRound_Day:
1975  m_Data.hour = 0;
1976  // fall through
1977  case eRound_Hour:
1978  m_Data.min = 0;
1979  // fall through
1980  case eRound_Minute:
1981  m_Data.sec = 0;
1982  // fall through
1983  case eRound_Second:
1984  m_Data.nanosec = 0;
1985  break;
1986  case eRound_Millisecond:
1987  m_Data.nanosec = m_Data.nanosec / 1000000 * 1000000;
1988  break;
1989  case eRound_Microsecond:
1990  m_Data.nanosec = m_Data.nanosec / 1000 * 1000;
1991  break;
1992  default:
1993  break;
1994  }
1995  return *this;
1996 }
1997 
1998 
2000 {
2001  m_Data.year = 0;
2002  m_Data.month = 0;
2003  m_Data.day = 0;
2004  m_Data.hour = 0;
2005  m_Data.min = 0;
2006  m_Data.sec = 0;
2007  m_Data.nanosec = 0;
2008  m_Data.adjTimeDiff = 0;
2009  return *this;
2010 }
2011 
2012 
2013 bool CTime::IsValid(void) const
2014 {
2015  if ( IsEmpty() )
2016  return true;
2017 
2018  _ASSERT(m_Data.tz);
2019  if ( !m_Data.tz ) {
2020  return false;
2021  }
2022 
2023  if (Year() < 1583) // first Gregorian date February 24, 1582
2024  return false;
2025  if (Month() < 1 || Month() > 12)
2026  return false;
2027  if (Month() == 2) {
2028  if (Day() < 1 || Day() > (IsLeap() ? 29 : 28))
2029  return false;
2030  } else {
2031  if (Day() < 1 || Day() > s_DaysInMonth[Month() - 1])
2032  return false;
2033  }
2034  if (Hour() < 0 || Hour() > 23)
2035  return false;
2036  if (Minute() < 0 || Minute() > 59)
2037  return false;
2038  // leap seconds are supported
2039  if (Second() < 0 || Second() > 61)
2040  return false;
2041  if (NanoSecond() < 0 || NanoSecond() >= kNanoSecondsPerSecond)
2042  return false;
2043 
2044  return true;
2045 }
2046 
2047 
2049 {
2050  if ( IsEmptyDate() ) {
2051  NCBI_THROW(CTimeException, eArgument, "The date is empty");
2052  }
2053  if ( IsLocalTime() ) {
2054  return *this;
2055  }
2056  CTime t(*this);
2057  return t.ToLocalTime();
2058 }
2059 
2060 
2062 {
2063  if ( IsEmptyDate() ) {
2064  NCBI_THROW(CTimeException, eArgument, "The date is empty");
2065  }
2066  if ( IsUniversalTime() ) {
2067  return *this;
2068  }
2069  CTime t(*this);
2070  return t.ToUniversalTime();
2071 }
2072 
2073 
2075 {
2076  if ( IsEmptyDate() ) {
2077  NCBI_THROW(CTimeException, eArgument, "The date is empty");
2078  }
2079  if (GetTimeZone() != tz) {
2080  struct tm* t;
2081  time_t timer;
2082  timer = GetTimeT();
2083  if (timer == (time_t)(-1L)) {
2084  return *this;
2085  }
2086  // MT-Safe protect
2087  CMutexGuard LOCK(s_TimeMutex);
2088 
2089 #if defined(HAVE_LOCALTIME_R)
2090  struct tm temp;
2091  if (tz == eLocal) {
2092  localtime_r(&timer, &temp);
2093  }
2094  else {
2095  gmtime_r(&timer, &temp);
2096  }
2097  t = &temp;
2098 #else
2099  t = (tz == eLocal) ? localtime(&timer) : gmtime(&timer);
2100  if (!t) {
2101  // Error was detected: incorrect timer value or system error
2102  NCBI_THROW(CTimeException, eConvert,
2103  "localtime/gmtime error, possible incorrect time_t value");
2104  }
2105 #endif
2106  LOCK.Release();
2107 
2108  SET_YEAR (t->tm_year + 1900);
2109  SET_MONTH (t->tm_mon + 1);
2110  SET_DAY (t->tm_mday);
2111  SET_HOUR (t->tm_hour);
2112  SET_MIN (t->tm_min);
2113  SET_SEC (t->tm_sec);
2114  m_Data.tz = tz;
2115  }
2116  return *this;
2117 }
2118 
2119 
2120 bool CTime::operator== (const CTime& t) const
2121 {
2122  CTime tmp(t);
2123  if ( !tmp.IsEmptyDate() ) {
2124  tmp.ToTime(GetTimeZone());
2125  }
2126  return
2127  Year() == tmp.Year() &&
2128  Month() == tmp.Month() &&
2129  Day() == tmp.Day() &&
2130  Hour() == tmp.Hour() &&
2131  Minute() == tmp.Minute() &&
2132  Second() == tmp.Second() &&
2133  NanoSecond() == tmp.NanoSecond();
2134 }
2135 
2136 
2137 bool CTime::operator> (const CTime& t) const
2138 {
2139  CTime tmp(t);
2140  if ( !tmp.IsEmptyDate() ) {
2141  tmp.ToTime(GetTimeZone());
2142  }
2143  if (Year() > tmp.Year())
2144  return true;
2145  if (Year() < tmp.Year())
2146  return false;
2147  if (Month() > tmp.Month())
2148  return true;
2149  if (Month() < tmp.Month())
2150  return false;
2151  if (Day() > tmp.Day())
2152  return true;
2153  if (Day() < tmp.Day())
2154  return false;
2155  if (Hour() > tmp.Hour())
2156  return true;
2157  if (Hour() < tmp.Hour())
2158  return false;
2159  if (Minute() > tmp.Minute())
2160  return true;
2161  if (Minute() < tmp.Minute())
2162  return false;
2163  if (Second() > tmp.Second())
2164  return true;
2165  if (Second() < tmp.Second())
2166  return false;
2167  if (NanoSecond() > tmp.NanoSecond())
2168  return true;
2169 
2170  return false;
2171 }
2172 
2173 
2174 bool CTime::operator< (const CTime& t) const
2175 {
2176  CTime tmp(t);
2177  if ( !tmp.IsEmptyDate() ) {
2178  tmp.ToTime(GetTimeZone());
2179  }
2180  if (Year() < tmp.Year())
2181  return true;
2182  if (Year() > tmp.Year())
2183  return false;
2184  if (Month() < tmp.Month())
2185  return true;
2186  if (Month() > tmp.Month())
2187  return false;
2188  if (Day() < tmp.Day())
2189  return true;
2190  if (Day() > tmp.Day())
2191  return false;
2192  if (Hour() < tmp.Hour())
2193  return true;
2194  if (Hour() > tmp.Hour())
2195  return false;
2196  if (Minute() < tmp.Minute())
2197  return true;
2198  if (Minute() > tmp.Minute())
2199  return false;
2200  if (Second() < tmp.Second())
2201  return true;
2202  if (Second() > tmp.Second())
2203  return false;
2204  if (NanoSecond() < tmp.NanoSecond())
2205  return true;
2206 
2207  return false;
2208 }
2209 
2210 
2211 bool CTime::IsLeap(void) const
2212 {
2213  int year = Year();
2214  return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
2215 }
2216 
2217 
2219 {
2220  const CTime tl(GetLocalTime());
2221  const CTime tg(GetUniversalTime());
2222 
2223  TSeconds dSecs = tl.Second() - tg.Second();
2224  TSeconds dMins = tl.Minute() - tg.Minute();
2225  TSeconds dHours = tl.Hour() - tg.Hour();
2226  TSeconds dDays = tl.DiffWholeDays(tg);
2227  return ((dDays * 24 + dHours) * 60 + dMins) * 60 + dSecs;
2228 }
2229 
2230 
2232 {
2233  int tz = (int)(TimeZoneOffset() / 60);
2234  string str;
2235  str.reserve(5);
2236  if (tz > 0) {
2237  str = '+';
2238  } else {
2239  str = '-';
2240  tz = -tz;
2241  }
2242  s_AddZeroPadInt2(str, tz / 60);
2243  s_AddZeroPadInt2(str, tz % 60);
2244  return str;
2245 }
2246 
2247 
2249 {
2250  time_t timer = GetTimeT();
2251  if (timer == (time_t)(-1L)) {
2252  return kEmptyStr;
2253  }
2254  // MT-Safe protect
2255  CMutexGuard LOCK(s_TimeMutex);
2256 
2257  struct tm* t;
2258 #if defined(HAVE_LOCALTIME_R)
2259  struct tm temp;
2260  localtime_r(&timer, &temp);
2261  t = &temp;
2262 #else
2263  t = localtime(&timer);
2264 #endif
2265  if ( !t ) {
2266  return kEmptyStr;
2267  }
2268 #if defined(__USE_BSD)
2269  if (t->tm_zone) {
2270  return t->tm_zone;
2271  }
2272 #endif
2273  return t->tm_isdst > 0 ? TZName()[1] : TZName()[0];
2274 }
2275 
2276 
2277 int CTime::DiffWholeDays(const CTime& t) const
2278 {
2279  return int(s_Date2Number(*this) - s_Date2Number(t));
2280 }
2281 
2283 {
2284  const CTime* p1, *p2;
2285  CTime t1, t2;
2286  if (GetTimeZone() != from.GetTimeZone()) {
2287  t1 = *this;
2288  t2 = from;
2289  t1.ToUniversalTime();
2290  t2.ToUniversalTime();
2291  p1 = &t1;
2292  p2 = &t2;
2293  } else {
2294  p1 = this;
2295  p2 = &from;
2296  }
2297  TSeconds dSecs = p1->Second() - p2->Second();
2298  TSeconds dMins = p1->Minute() - p2->Minute();
2299  TSeconds dHours = p1->Hour() - p2->Hour();
2300  TSeconds dDays = p1->DiffWholeDays(*p2);
2301  return ((dDays * 24 + dHours) * 60 + dMins) * 60 + dSecs;
2302 }
2303 
2304 
2306 {
2307  TSeconds sec = DiffSecond(t);
2308  if (sec < kMin_Long || sec > kMax_Long) {
2309  NCBI_THROW(CTimeException, eConvert,
2310  "Difference in time " +
2311  NStr::Int8ToString(sec) +
2312  " is too big to convert to CTimeSpan");
2313  }
2314  return CTimeSpan((long)sec , NanoSecond() - t.NanoSecond());
2315 }
2316 
2317 
2318 void CTimeSpan::Set(double seconds)
2319 {
2320  if (seconds < (double)kMin_Long || seconds > (double)kMax_Long) {
2321  NCBI_THROW(CTimeException, eConvert,
2322  "Value " + NStr::DoubleToString(seconds) +
2323  " is too big to convert to CTimeSpan");
2324  }
2325  m_Sec = long(seconds);
2326  m_NanoSec = long((seconds - (double)m_Sec) * kNanoSecondsPerSecond);
2327  x_Normalize();
2328 }
2329 
2330 
2332 {
2333  int n_days = DaysInMonth();
2334  if (Day() > n_days) {
2335  SET_DAY(n_days);
2336  }
2337 }
2338 
2339 
2340 CTime& CTime::x_AdjustTime(const CTime& from, bool shift_time)
2341 {
2342  if ( !x_NeedAdjustTime() )
2343  return *this;
2344 
2345  switch ( GetTimeZonePrecision() ) {
2346  case eMinute:
2347  if (Minute() != from.Minute())
2348  return x_AdjustTimeImmediately(from, shift_time);
2349  case eHour:
2350  if (Hour() != from.Hour())
2351  return x_AdjustTimeImmediately(from, shift_time);
2352  case eDay:
2353  if (Day() != from.Day())
2354  return x_AdjustTimeImmediately(from, shift_time);
2355  case eMonth:
2356  if (Month() != from.Month())
2357  return x_AdjustTimeImmediately(from, shift_time);
2358  default:
2359  break;
2360  }
2361  return *this;
2362 }
2363 
2364 
2365 CTime& CTime::x_AdjustTimeImmediately(const CTime& from, bool shift_time)
2366 {
2367  // Time in hours for temporary time shift.
2368  // Shift used for obtainment correct result at changeover daytime saving.
2369  // Must be > 3 (Linux distinction). On other platforms may be == 3.
2370  const int kShiftHours = 4;
2371 
2372  // MT-Safe protect
2373  CMutexGuard LOCK(s_TimeAdjustMutex);
2374 
2375  // Special conversion from <const CTime> to <CTime>
2376  CTime tmp(from);
2377  int sign = 0;
2378  TSeconds diff = 0;
2379  // Primary procedure call
2380  if ( shift_time ) {
2381  sign = ( *this > from ) ? 1 : -1;
2382  // !!! Run TimeZoneOffset() first for old time value
2383  diff = -tmp.TimeZoneOffset() + TimeZoneOffset();
2384  // Correction needs if time already in identical timezone
2385  if (!diff || diff == m_Data.adjTimeDiff) {
2386  return *this;
2387  }
2388  }
2389  // Recursive procedure call. Inside below
2390  // x_AddHour(*, eAdjustDaylight, false)
2391  else {
2392  // Correction needn't if difference not found
2393  if (diff == m_Data.adjTimeDiff) {
2394  return *this;
2395  }
2396  }
2397  // Make correction with temporary time shift
2398  time_t t = GetTimeT();
2399  CTime tn(t + (time_t)diff + 3600 * kShiftHours * sign);
2400  if (from.GetTimeZone() == eLocal) {
2401  tn.ToLocalTime();
2402  }
2404 
2405  // Release adjust time mutex
2406  LOCK.Release();
2407 
2408  // Primary procedure call
2409  if ( shift_time ) {
2410  // Cancel temporary time shift
2411  tn.x_AddHour(-kShiftHours * sign, eAdjustDaylight, false);
2412  tn.m_Data.adjTimeDiff = (Int4)diff; /* NCBI_FAKE_WARNING */
2413  }
2414  *this = tn;
2415  return *this;
2416 }
2417 
2418 
2419 
2420 //=============================================================================
2421 //
2422 // CTimeSpan
2423 //
2424 //=============================================================================
2425 
2426 
2427 CTimeSpan::CTimeSpan(long days, long hours, long minutes, long seconds,
2428  long nanoseconds)
2429 {
2430  TSeconds sec = (((TSeconds)days*24 + hours)*60 + minutes)*60 +
2431  seconds + nanoseconds/kNanoSecondsPerSecond;
2432  if (sec < kMin_Long || seconds > kMax_Long) {
2433  NCBI_THROW(CTimeException, eConvert,
2434  "Value (" +
2435  NStr::Int8ToString(days) + ", " +
2436  NStr::Int8ToString(hours) + ", " +
2437  NStr::Int8ToString(minutes) + ", " +
2438  NStr::Int8ToString(seconds) +
2439  ", nanosec) is too big to convert to CTimeSpan");
2440  }
2441  m_Sec = (long)sec;
2442  m_NanoSec = nanoseconds % kNanoSecondsPerSecond;
2443  x_Normalize();
2444 }
2445 
2446 
2447 CTimeSpan::CTimeSpan(const string& str, const CTimeFormat& fmt)
2448 {
2449  if (fmt.IsEmpty()) {
2450  // Use another format to init from string by default
2451  // if global format has not set.
2452  CTimeFormat* ptr = s_TlsFormatSpan.GetValue();
2453  if (!ptr) {
2454  CTimeFormat default_fmt(kDefaultFormatSpanIn);
2455  x_Init(str, default_fmt);
2456  } else {
2457  x_Init(str, *ptr);
2458  }
2459  } else {
2460  x_Init(str, fmt);
2461  }
2462 }
2463 
2464 
2466 {
2467  // Use another format to init from string by default
2468  // if global format has not set.
2469  CTimeFormat* ptr = s_TlsFormatSpan.GetValue();
2470  if (!ptr) {
2472  x_Init(str, fmt);
2473  } else {
2474  x_Init(str, *ptr);
2475  }
2476  return *this;
2477 }
2478 
2479 
2480 void CTimeSpan::x_Init(const string& str, const CTimeFormat& format)
2481 {
2482  Clear();
2483  if ( str.empty() ) {
2484  return;
2485  }
2486  const string& fmt = format.GetString();
2487  bool is_escaped_fmt = ((format.GetFlags() & CTimeFormat::fFormat_Simple) == 0);
2488  bool is_escaped_symbol = false;
2489 
2490  const char* fff;
2491  char f;
2492  const char* sss = str.c_str();
2493  int sign = 1;
2494 
2495  for (fff = fmt.c_str(); *fff != '\0'; ++fff) {
2496 
2497  // Skip preceding symbols for some formats
2498  if (is_escaped_fmt && !is_escaped_symbol) {
2499  if (*fff == kFormatEscapeSymbol) {
2500  is_escaped_symbol = true;
2501  continue;
2502  }
2503  }
2504 
2505  // Match non-format symbols
2506 
2507  if (is_escaped_fmt) {
2508  if (!(is_escaped_symbol && *fff != kFormatEscapeSymbol)) {
2509  // Match non-format symbols
2510  if (*fff == *sss) {
2511  ++sss;
2512  continue;
2513  }
2514  break; // error: non-matching symbols
2515  }
2516  // format symbol found, process as usual
2517  is_escaped_symbol = false;
2518  } else {
2519  // Regular non-escaped format, each symbol can be a format symbol.
2520  // Check allowed format symbols
2521  if (strchr(kFormatSymbolsSpan, *fff) == 0) {
2522  // Match non-format symbols
2523  if (*fff == *sss) {
2524  ++sss;
2525  continue;
2526  }
2527  break; // error: non-matching symbols
2528  }
2529  }
2530 
2531  // Process format symbols
2532 
2533  // Sign: if specified that the time span is negative
2534  if (*fff == '-') {
2535  if (*sss == '-') {
2536  sign = -1;
2537  ++sss;
2538  }
2539  continue;
2540  }
2541  f = *fff;
2542 
2543  read_next_value:
2544 
2545  // Other format symbols -- read the next data ingredient
2546  char value_str[11];
2547  char* s = value_str;
2548  // Read 9 (special case) or 10 digits only, ignore all other.
2549  size_t len = (f == '\1') ? 9 : 10;
2550  for (; len && *sss && isdigit((unsigned char)(*sss)); --len) {
2551  *s++ = *sss++;
2552  }
2553  *s = '\0';
2554  long value = NStr::StringToLong(value_str);
2555 
2556  switch ( f ) {
2557  case 'd':
2558  m_Sec += value * 3600L * 24L;
2559  break;
2560  case 'h':
2561  m_Sec += value * 3600L;
2562  break;
2563  case 'H':
2564  m_Sec = value * 3600L;
2565  break;
2566  case 'm':
2567  m_Sec += value * 60L;
2568  break;
2569  case 'M':
2570  m_Sec = value * 60L;
2571  break;
2572  case 's':
2573  m_Sec += value;
2574  break;
2575  case 'S':
2576  m_Sec = value;
2577  break;
2578  case 'n':
2579  m_NanoSec = value;
2580  break;
2581  case 'g':
2582  m_Sec += value;
2583  if ( *sss == '.' ) {
2584  // Read fraction
2585  ++sss;
2586  f = '\1';
2587  goto read_next_value;
2588  }
2589  break;
2590  case 'G':
2591  m_Sec = value;
2592  if ( *sss == '.' ) {
2593  // Read fraction
2594  ++sss;
2595  f = '\1';
2596  goto read_next_value;
2597  }
2598  break;
2599  case '\1':
2600  {
2601  // Special format symbol.
2602  // Process a fraction of a second for format symbols 'g' and 'G'.
2603  // Convert value to nanoseconds.
2604  size_t n = strlen(value_str);
2605  // 'n' cannot have more then 9 (max for nanoseconds)
2606  // ignore all other digits
2607  for (; n < 9; ++n) {
2608  value *= 10;
2609  }
2610  m_NanoSec = value;
2611  // Limit fraction of second to 9 digits max,
2612  // ignore all other digits in string if any.
2613  while ( isdigit((unsigned char)(*sss)) ) {
2614  ++sss;
2615  }
2616  }
2617  break;
2618  default:
2619  NCBI_THROW(CTimeException, eFormat, "Format '" + fmt + "' has incorrect format symbol '" + f + "'");
2620  }
2621  }
2622 
2623  // Check on errors
2624  if (*fff != '\0' &&
2625  !(format.GetFlags() & CTimeFormat::fMatch_ShortTime)) {
2626  NCBI_THROW(CTimeException, eFormat,
2627  "Time string '" + str +
2628  "' is too short for time format '" + fmt + "'");
2629  }
2630  if (*sss != '\0' &&
2631  !(format.GetFlags() & CTimeFormat::fMatch_ShortFormat)) {
2632  NCBI_THROW(CTimeException, eFormat,
2633  "Time string '" + str +
2634  "' is too long for time format '" + fmt + "'");
2635  }
2636  // Normalize time span
2637  if (sign < 0) {
2638  Invert();
2639  }
2640  x_Normalize();
2641 }
2642 
2643 
2645 {
2648  // If signs are different then make timespan correction
2649  if (m_Sec > 0 && m_NanoSec < 0) {
2650  --m_Sec;
2652  } else if (m_Sec < 0 && m_NanoSec > 0) {
2653  ++m_Sec;
2655  }
2656 }
2657 
2658 
2660 {
2661  // Here we do not need to delete a previous value stored in the TLS.
2662  // The TLS will destroy it using cleanup function.
2663  CTimeFormat* ptr = new CTimeFormat(fmt);
2664  s_TlsFormatSpan.SetValue(ptr, CTlsBase::DefaultCleanup<CTimeFormat>);
2665 }
2666 
2667 
2669 {
2670  CTimeFormat fmt;
2671  CTimeFormat* ptr = s_TlsFormatSpan.GetValue();
2672  if ( !ptr ) {
2674  } else {
2675  fmt = *ptr;
2676  }
2677  return fmt;
2678 }
2679 
2680 
2682 {
2683  string str;
2684  str.reserve(64); // try to save on memory allocations
2685  string fmt;
2686  CTimeFormat::TFlags fmt_flags;
2687 
2688  if ( format.IsEmpty() ) {
2689  CTimeFormat f = GetFormat();
2690  fmt = f.GetString();
2691  fmt_flags = f.GetFlags();
2692  } else {
2693  fmt = format.GetString();
2694  fmt_flags = format.GetFlags();
2695  }
2696  bool is_escaped = ((fmt_flags & CTimeFormat::fFormat_Simple) == 0);
2697  bool is_format_symbol = !is_escaped;
2698 
2699  ITERATE(string, it, fmt) {
2700 
2701  if ( !is_format_symbol ) {
2702  if ( *it == kFormatEscapeSymbol ) {
2703  is_format_symbol = true;
2704  } else {
2705  str += *it;
2706  }
2707  continue;
2708  }
2709  if ( is_escaped ) {
2710  is_format_symbol = false;
2711  }
2712  switch ( *it ) {
2713  case '-': if (GetSign() == eNegative) {
2714  str += "-";
2715  }
2716  break;
2717  case 'd': s_AddInt(str, abs(GetCompleteDays()));
2718  break;
2719  case 'h': s_AddZeroPadInt2(str, abs(x_Hour()));
2720  break;
2721  case 'H': s_AddInt(str, abs(GetCompleteHours()));
2722  break;
2723  case 'm': s_AddZeroPadInt2(str, abs(x_Minute()));
2724  break;
2725  case 'M': s_AddInt(str, abs(GetCompleteMinutes()));
2726  break;
2727  case 's': s_AddZeroPadInt2(str, abs(x_Second()));
2728  break;
2729  case 'S': s_AddInt(str, abs(GetCompleteSeconds()));
2730  break;
2732  break;
2733  case 'g': s_AddInt(str, abs(x_Second()));
2734  str += ".";
2736  break;
2737  case 'G': s_AddInt(str, abs(GetCompleteSeconds()));
2738  str += ".";
2740  break;
2741  default : str += *it;
2742  break;
2743  }
2744  }
2745  return str;
2746 }
2747 
2748 
2749 // Number of time components
2750 const unsigned int kUnitCount = 9;
2751 
2752 // Time components
2753 enum EUnit {
2754  eYear = 0,
2755  eMonth = 1,
2756  eDay = 2,
2757  eHour = 3,
2758  eMinute = 4,
2759  eSecond = 5,
2763 
2764  // Special value, some precision based (see fSS_Precision*).
2765  // Must be last and go after eNanosecond.
2766  ePrecision = 9
2767 };
2768 
2769 // Structure to store time component names/abbreviations
2770 struct SUnitName {
2771  const char* name_full;
2772  const char* name_short;
2773 };
2775  { "year", "y" },
2776  { "month", "mo"},
2777  { "day", "d" },
2778  { "hour", "h" },
2779  { "minute", "m" },
2780  { "second", "s" },
2781  { "millisecond", "ms" },
2782  { "microsecond", "us" },
2783  { "nanosecond", "ns" }
2784 };
2785 
2786 // Multipliers for parts of time in seconds/nanoseconds
2788  // second based parts
2789  kAverageSecondsPerYear, // year
2790  kAverageSecondsPerMonth, // month
2791  3600L * 24L, // day
2792  3600L, // hour
2793  60L, // minute
2794  1, // seconds
2795  // nanosecond based parts
2796  1000000L, // milliseconds
2797  1000L, // microseconds
2798  1 // nanoseconds
2799 };
2800 
2801 
2802 // Helper functions to convert to smart string for "smart" mode
2803 // and timespans >= 1 min. Do not use with smaller timespans!
2804 
2806 {
2807  _ASSERT(*this >= CTimeSpan(60,0) );
2808  _ASSERT(GetSign() != eNegative);
2809  _ASSERT((flags & fSS_Smart) == fSS_Smart);
2810 
2811  // Make a copy (for rounding)
2812  CTimeSpan ts(*this);
2813 
2814  // Round timespan
2815  if ( flags & fSS_Round ) {
2816 
2817  // Find first non-zero value for proper rounding (2 level max)
2818  long sec = GetCompleteSeconds();
2819  int adjust_level;
2820  for (adjust_level = eYear; adjust_level < eSecond; adjust_level++) {
2821  if (sec >= kTimeSpanUnitMultipliers[adjust_level]) {
2822  break;
2823  }
2824  }
2825  _ASSERT(adjust_level < eMicrosecond);
2826  ++adjust_level; // one level down
2827 
2828  // Add adjustment time span
2829  switch ( EUnit(adjust_level) ) {
2830  case eMonth:
2831  ts += CTimeSpan(15, 0, 0, 0);
2832  break;
2833  case eDay:
2834  ts += CTimeSpan(0, 12, 0, 0);
2835  break;
2836  case eHour:
2837  ts += CTimeSpan(0, 0, 30, 0);
2838  break;
2839  case eMinute:
2840  ts += CTimeSpan(0, 0, 0, 30);
2841  break;
2842  case eSecond:
2843  ts += CTimeSpan(0, 0, 0, 0, kNanoSecondsPerSecond/2);
2844  break;
2845  default:
2846  ; // years, seconds and below -- nothing to do
2847  }
2848  }
2849 
2850  // Prepare data
2851  const int max_count = 6;
2852  long span[max_count];
2853  long sec = ts.GetCompleteSeconds();
2854 
2857  span[eDay] = sec/(3600L*24); sec %= (3600L*24);
2858  span[eHour] = sec/3600L; sec %= 3600L;
2859  span[eMinute] = sec/60L; sec %= 60L;
2860  span[eSecond] = sec;
2861 
2862  string result; // result string
2863  int start = 0; // precision level to start from (first non-zero)
2864  int prec; // end precision
2865 
2866  // Get start precision after rounding (it can changes there)
2867  for (; start < 5; ++start) {
2868  if ( span[start] ) {
2869  break;
2870  }
2871  }
2872  // Allow 2 levels maximum for smart mode
2873  if (start == eSecond) {
2874  prec = start;
2875  } else {
2876  prec = start + 1;
2877  }
2878 
2879  // Compose result string
2880  while (start <= prec) {
2881  long val = span[start];
2882  if ( !val ) {
2883  ++start;
2884  continue;
2885  }
2886  if ( !result.empty() ) {
2887  result += " ";
2888  }
2890  if (flags & fSS_Full) {
2891  result += string(" ") + kUnitNames[start].name_full;
2892  if (val != 1) {
2893  result += "s";
2894  }
2895  } else {
2896  result += kUnitNames[start].name_short;
2897  }
2898  ++start;
2899  }
2900  return result;
2901 }
2902 
2903 
2904 // Helper functions to convert to smart string for "smart" mode
2905 // and timespans < 1 min. Do not use with sbigger timespans!
2906 
2908 {
2909  _ASSERT(*this < CTimeSpan(60, 0));
2910  _ASSERT(GetSign() != eNegative);
2911  _ASSERT((flags & fSS_Smart) == fSS_Smart);
2912 
2913  // Get timespan components
2914  int sec = x_Second();
2915  long nanoseconds = GetNanoSecondsAfterSecond();
2916  // Split nanoseconds to 3 digit parts AAABBBCCC
2917  // AAA - milli, BBB - micro, CCC - nano
2918  int milli = int(nanoseconds / 1000000);
2919  int micro = int(nanoseconds / 1000 % 1000);
2920  int nano = int(nanoseconds % 1000);
2921 
2922  // We would like to have 3 digits in result,
2923  // so we need 2 components max.
2924  EUnit unit = eSecond;
2925  long v1 = 0;
2926  long v2 = 0;
2927 
2928  if ( sec ) {
2929  v1 = sec;
2930  v2 = milli;
2931  } else if ( milli ) {
2932  unit = eMillisecond;
2933  v1 = milli;
2934  v2 = micro;
2935  } else if ( micro ) {
2936  unit = eMicrosecond;
2937  v1 = micro;
2938  v2 = nano;
2939  } else if ( nano ) {
2940  unit = eNanosecond;
2941  v1 = nano;
2942  v2 = 0;
2943  } else {
2944  // Empty timespan
2945  return (flags & fSS_Full) ? "0 seconds" : "0s";
2946  }
2947 
2948  string result = NStr::LongToString(v1);
2949  bool plural = (v1 != 1);
2950  size_t len = result.length();
2951 
2952  // Rounding
2953  if ( flags & fSS_Round ) {
2954  // Rounding depends on number of digits we already have in v1
2955  if (len == 1) {
2956  v2 += 5;
2957  } else if (len == 2) {
2958  v2 += 50;
2959  } else { // len == 3
2960  v2 += 500;
2961  }
2962  // Check on overflow
2963  if ( v2 > 999 ) {
2964  ++v1;
2965  v2 = 0;
2966  if (unit == eSecond) {
2967  if ( v1 > 59 ) {
2968  // Special case, because we work with timespans < 1 min
2969  return (flags & fSS_Full) ? "1 minute" : "1m";
2970  }
2971  } else {
2972  if ( v1 > 999 ) {
2973  // Shift to bigger units
2974  v1 = 1;
2975  unit = EUnit(unit-1);
2976  }
2977  }
2978  // Reconvert v1
2979  result = NStr::LongToString(v1);
2980  plural = (v1 != 1);
2981  len = result.length();
2982  }
2983  }
2984 
2985  // Add (3-n) digits from v2 after "."
2986  if (v2 && len < 3) {
2987  int n = int(v2 / 10);
2988  if (len == 2) {
2989  n = n / 10;
2990  }
2991  if ( n ) {
2992  result += "." + NStr::LongToString(n);
2993  plural = true;
2994  }
2995  }
2996  if ( flags & fSS_Full ) {
2997  result += string(" ") + kUnitNames[unit].name_full;
2998  if (plural) {
2999  result += "s";
3000  }
3001  } else {
3002  result += kUnitNames[unit].name_short;
3003  }
3004  return result;
3005 }
3006 
3007 
3008 // Helper functions for all modes except "smart".
3010 {
3011  _ASSERT(GetSign() != eNegative);
3012  _ASSERT((flags & fSS_Smart) != fSS_Smart);
3013 
3014  // Convert precision flags to continuous numeric value (bit position - 1)
3015  int precision = -1;
3017  while (pf) {
3018  pf >>= 1; ++precision;
3019  }
3020  _ASSERT(precision >= 0);
3021 
3022  // Named or float precision level
3023  bool is_named_precision = (precision < ePrecision);
3024 
3025  // Make a copy (for rounding)
3026  CTimeSpan ts(*this);
3027 
3028  // Round time span if necessary
3029  if ( flags & fSS_Round ) {
3030  int adjust_level = precision;
3031 
3032  // Calculate adjustment for floating precision level
3033  if ( !is_named_precision ) {
3034 
3035  // Find first non-zero value
3036  long sec = GetCompleteSeconds();
3037  for (adjust_level = eYear; adjust_level <= eSecond; adjust_level++) {
3038  if (sec >= kTimeSpanUnitMultipliers[adjust_level]) {
3039  break;
3040  }
3041  }
3042  // Calculate adjustment level
3043  if (adjust_level <= eSecond) {
3044  adjust_level += (precision - eNanosecond - 1);
3045  } else {
3046  // ms, us, ns
3047  if (GetNanoSecondsAfterSecond() % 1000 == 0) {
3048  adjust_level = eMillisecond;
3049  }
3050  else if (GetNanoSecondsAfterSecond() % 1000000 == 0) {
3051  adjust_level = eMicrosecond;
3052  } else {
3053  // no adjustment otherwise
3054  adjust_level = eNanosecond;
3055  }
3056  }
3057  }
3058  // Add adjustment time span
3059  switch ( EUnit(adjust_level) ) {
3060  case eYear:
3061  ts += CTimeSpan((long)kAverageSecondsPerYear/2);
3062  break;
3063  case eMonth:
3064  ts += CTimeSpan((long)kAverageSecondsPerMonth/2);
3065  break;
3066  case eDay:
3067  ts += CTimeSpan(0, 12, 0, 0);
3068  break;
3069  case eHour:
3070  ts += CTimeSpan(0, 0, 30, 0);
3071  break;
3072  case eMinute:
3073  ts += CTimeSpan(0, 0, 0, 30);
3074  break;
3075  case eSecond:
3076  ts += CTimeSpan(0, 0, 0, 0, kNanoSecondsPerSecond/2);
3077  break;
3078  case eMillisecond:
3079  ts += CTimeSpan(0, 0, 0, 0, kNanoSecondsPerSecond/2000);
3080  break;
3081  case eMicrosecond:
3082  ts += CTimeSpan(0, 0, 0, 0, kNanoSecondsPerSecond/2000000);
3083  break;
3084  default:
3085  ; // nanoseconds -- nothing to do
3086  }
3087  }
3088 
3089  // Prepare data
3090 
3091  long sec = ts.GetCompleteSeconds();
3092  long nanoseconds = ts.GetNanoSecondsAfterSecond();
3093 
3094  struct SItem {
3095  SItem(void) : value(0), unit(eYear) {};
3096  SItem(long v, EUnit u) : value(v), unit(u) {};
3097  long value;
3098  EUnit unit;
3099  };
3100  const int max_count = 7;
3101  SItem span[max_count];
3102 
3103  span[0] = SItem(sec/kAverageSecondsPerYear, eYear ); sec %= kAverageSecondsPerYear;
3104  span[1] = SItem(sec/kAverageSecondsPerMonth, eMonth ); sec %= kAverageSecondsPerMonth;
3105  span[2] = SItem(sec/(3600L*24), eDay ); sec %= (3600L*24);
3106  span[3] = SItem(sec/3600L, eHour ); sec %= 3600L;
3107  span[4] = SItem(sec/60L, eMinute); sec %= 60L;
3108  span[5] = SItem(sec, eSecond);
3109 
3110  switch (precision) {
3111  case eMillisecond:
3112  span[6] = SItem(nanoseconds / 1000000, eMillisecond);
3113  break;
3114  case eMicrosecond:
3115  span[6] = SItem(nanoseconds / 1000, eMicrosecond);
3116  break;
3117  case eNanosecond:
3118  span[6] = SItem(nanoseconds, eNanosecond);
3119  break;
3120  default:
3121  ; // other not-nanoseconds based precisions
3122  }
3123 
3124  // Result string
3125  string result;
3126  // Precision level to start from (first non-zero)
3127  int start = is_named_precision ? eYear : ePrecision;
3128 
3129  // Compose resulting string
3130 
3131  for (int i = 0; i < max_count && start <= precision; ++i) {
3132  long val = span[i].value;
3133 
3134  // Adjust precision to skip zero values
3135  if ( !val ) {
3136  if ( result.empty() ) {
3137  if (start == precision && start != ePrecision) {
3138  break;
3139  }
3140  if ( is_named_precision ) {
3141  ++start;
3142  }
3143  continue;
3144  }
3145  if ( flags & fSS_SkipZero ) {
3146  ++start;
3147  continue;
3148  } else {
3149  long sum = 0;
3150  int cp = start + 1;
3151  for (int j = i + 1;
3152  j < max_count && (cp <= precision); ++j, ++cp) {
3153  sum += span[j].value;
3154  }
3155  if ( !sum ) {
3156  // all trailing parts are zeros -- skip all
3157  break;
3158  }
3159  }
3160  }
3161  ++start;
3162  if ( !result.empty() ) {
3163  result += " ";
3164  }
3166  if (flags & fSS_Full) {
3167  result += string(" ") + kUnitNames[span[i].unit].name_full;
3168  if (val != 1) {
3169  result += "s";
3170  }
3171  } else {
3172  result += kUnitNames[span[i].unit].name_short;
3173  }
3174  }
3175  if ( result.empty() ) {
3176  if ( precision >= eSecond ) {
3177  return (flags & fSS_Full) ? "0 seconds" : "0s";
3178  } else {
3179  if (flags & fSS_Full) {
3180  return string("0 ") + kUnitNames[span[precision].unit].name_full + "s";
3181  }
3182  return string("0") + kUnitNames[span[precision].unit].name_short;
3183  }
3184  }
3185  return result;
3186 }
3187 
3188 
3190 {
3191  // Check on negative value
3192  if (GetSign() == eNegative) {
3193  NCBI_THROW(CTimeException, eArgument,
3194  "Negative CTimeSpan cannot be converted to smart string");
3195  }
3196 
3197  // Check flags compatibility
3198 
3200  (fSS_Year | fSS_Month | fSS_Day |
3206  );
3207 
3208  const string kMsg = "Incompatible flags specified together: ";
3209 
3211  if (f == 0) {
3212  flags |= fSS_Smart; // default
3213  } else {
3214  if ( !(f && !(f & (f-1))) ) {
3215  NCBI_THROW(CTimeException, eArgument, "Only one precision flag can be specified");
3216  }
3217  }
3218 
3219  // Default flags
3220 
3221  // Truncation
3222  f = fSS_Trunc | fSS_Round;
3223  if ((flags & f) == f) {
3224  NCBI_THROW(CTimeException, eArgument, kMsg + "fSS_Trunc | fSS_Round");
3225  }
3226  if ((flags & f) == 0) {
3227  flags |= fSS_Trunc;
3228  }
3229  // SkipZero
3231  if ((flags & f) == f) {
3232  NCBI_THROW(CTimeException, eArgument, kMsg + "fSS_SkipZero | fSS_NoSkipZero");
3233  }
3235  if ((flags & f) == f) {
3236  NCBI_THROW(CTimeException, eArgument, kMsg + "fSS_Smart | fSS_NoSkipZero");
3237  }
3238  if ((flags & f) == 0) {
3239  flags |= fSS_SkipZero;
3240  }
3241  // Naming
3242  f = fSS_Short | fSS_Full;
3243  if ((flags & f) == f) {
3244  NCBI_THROW(CTimeException, eArgument, kMsg + "fSS_Short | fSS_Full");
3245  }
3246  if ((flags & f) == 0) {
3247  flags |= fSS_Full;
3248  }
3249 
3250  // Use specific code depends on precision
3251 
3252  if ((flags & fSS_Smart) == fSS_Smart) {
3253  if (*this < CTimeSpan(60, 0)) {
3255  }
3257  } else {
3259  }
3260 }
3261 
3262 
3264 {
3265  Clear();
3266  if ( str.empty() ) {
3267  return *this;
3268  }
3269 
3270  const char* sss = str.c_str();
3271  bool numeric_expected = true;
3272  long value = 0;
3273  long frac = 0;
3274  size_t frac_len = 0;
3275  bool repetitions[kUnitCount];
3276 
3277  memset(repetitions, 0, kUnitCount * sizeof(repetitions[0]));
3278 
3279  for (; *sss != '\0'; ++sss) {
3280 
3281  // Skip all white spaces
3282  if (isspace((unsigned char)(*sss))) {
3283  continue;
3284  }
3285 
3286  // Numeric data expected
3287  if (numeric_expected) {
3288 
3289  value = 0; frac = 0;
3290 
3291  if (isdigit((unsigned char)(*sss))) {
3292  // Get numeric value
3293  const char* start = sss++;
3294  while (*sss && isdigit((unsigned char)(*sss))) ++sss;
3295  size_t n = sss - start;
3296  if (n > 10) {
3297  NCBI_THROW(CTimeException, eConvert,
3298  "Too long numeric value '" + string(start, n) +
3299  "': string '" + str + "' (pos = " +
3300  NStr::NumericToString(start - str.c_str()) + ")" );
3301  }
3303  } else
3304  if (*sss != '.') {
3305  // no digits and no fraction part (".n" case)
3306  break; // error
3307  }
3308 
3309  // Check on fraction
3310  if (*sss == '.') {
3311  ++sss;
3312  if (*sss && isdigit((unsigned char)(*sss))) {
3313  const char* start = sss++;
3314  while (*sss && isdigit((unsigned char)(*sss))) ++sss;
3315  frac_len = sss - start;
3316  if (frac_len > 9) {
3317  NCBI_THROW(CTimeException, eConvert,
3318  "Too long fractional part '" + string(start, frac_len) +
3319  "': string '" + str + "' (pos = " +
3320  NStr::NumericToString(start - str.c_str()) + ")" );
3321  }
3322  frac = NStr::StringToULong(CTempString(start, frac_len));
3323  }
3324  // else { "n." case --= nothing to do }
3325  }
3326  --sss;
3327  numeric_expected = false;
3328  continue;
3329  }
3330 
3331  // Unit specifier expected after numeric value
3332  else {
3333  if (!isalpha((unsigned char)(*sss))) {
3334  break; // error
3335  }
3336  const char* start = sss++;
3337  while (*sss && isalpha((unsigned char)(*sss))) ++sss;
3338  size_t n = sss - start;
3339  --sss;
3340  string spec(start, n);
3341  NStr::ToLower(spec);
3342 
3343  unsigned int i = 0;
3344  for (; i < kUnitCount; ++i) {
3345  if (spec == kUnitNames[i].name_full ||
3346  spec == kUnitNames[i].name_full + string("s") ||
3347  spec == kUnitNames[i].name_short) {
3348  break;
3349  }
3350  }
3351  if (i >= kUnitCount) {
3352  NCBI_THROW(CTimeException, eConvert,
3353  "Unknown time specifier '" + spec + "': string '" + str +
3354  "' (pos = " + NStr::NumericToString(start - str.c_str()) + ")" );
3355  }
3356 
3357  // Use bigger values for calculations to check on possible overflow
3358  TSeconds sec = m_Sec;
3359  TSeconds ns = m_NanoSec;
3360 
3361  // Add component to timespan
3362  switch (EUnit(i)) {
3363  case eYear:
3364  case eMonth:
3365  case eDay:
3366  case eHour:
3367  case eMinute:
3368  case eSecond:
3369  sec += value * kTimeSpanUnitMultipliers[i];
3370  break;
3371  case eMillisecond:
3372  case eMicrosecond:
3373  ns += value * kTimeSpanUnitMultipliers[i];
3374  break;
3375  case eNanosecond:
3376  ns += value;
3377  break;
3378  default:
3379  _TROUBLE;
3380  }
3381 
3382  // Add fractional part
3383  if (frac) {
3384  // div = 10 ^ frac_len
3385  unsigned int div = 10;
3386  _ASSERT(frac_len > 0);
3387  while (--frac_len) div *= 10;
3388 
3389  if (i < eSecond) {
3390  // fraction of year, month, day, hour, minute
3391  sec += ((TSeconds)frac * kTimeSpanUnitMultipliers[i] / div);
3392  } else
3393  if (i == eSecond) {
3394  // sec -- increase nanoseconds
3395  ns += ((TSeconds)frac * (kNanoSecondsPerSecond / div));
3396  } else {
3397  if (i == eNanosecond) {
3398  // Round fractional nanoseconds to nearest value
3399  if (((TSeconds)frac * 10 / div) >=5 ) {
3400  ++ns;
3401  }
3402  } else
3403  // us, ms -- increase nanoseconds
3404  ns += ((TSeconds)frac * (kTimeSpanUnitMultipliers[i] / div));
3405  }
3406  }
3407 
3408  // Check repetition of time components -- not allowed
3409  if (repetitions[i]) {
3410  NCBI_THROW(CTimeException, eConvert,
3411  "Time component for '" + string(kUnitNames[i].name_full) +
3412  "s' already exists: string '" + str +
3413  "' (pos = " + NStr::NumericToString(start - str.c_str()) + ")");
3414  }
3415  repetitions[i] = true;
3416  if (frac && (i >= eSecond)) {
3417  // disable all subsequent ms, us, ns and fraction of second
3418  repetitions[eMillisecond] = true;
3419  repetitions[eMicrosecond] = true;
3420  repetitions[eNanosecond] = true;
3421  }
3422 
3423  // Check on overflow
3424  if ( sec <= kMin_Long || sec >= kMax_Long ||
3425  ns <= kMin_Long || ns >= kMax_Long) {
3426  NCBI_THROW(CTimeException, eConvert,
3427  "Value is too big to convert to CTimeSpan: string '" + str +
3428  "' (pos = " + NStr::NumericToString(start - str.c_str()) + ")");
3429  }
3430  m_Sec = (long)sec;
3431  m_NanoSec = (long)ns;
3432  numeric_expected = true;
3433  }
3434  }
3435 
3436  // Check on errors
3437  if (!numeric_expected) {
3438  NCBI_THROW(CTimeException, eConvert,
3439  "Time specifier expected: string '" + str +
3440  "' (pos = " + NStr::NumericToString(sss - str.c_str()) + ")");
3441  }
3442  if (*sss != '\0') {
3443  NCBI_THROW(CTimeException, eConvert,
3444  "Unexpected symbol: string '" + str +
3445  "' (pos = " + NStr::NumericToString(sss - str.c_str()) + ")");
3446  }
3447  // Normalize time span
3448  x_Normalize();
3449 
3450  return *this;
3451 }
3452 
3453 
3454 
3455 //=============================================================================
3456 //
3457 // CTimeout
3458 //
3459 //=============================================================================
3460 
3461 
3463 {
3464  switch(type) {
3465  case CTimeout::eDefault:
3466  return "eDefault";
3467  case CTimeout::eInfinite:
3468  return "eInfinity";
3469  default:
3470  break;
3471  }
3472  return kEmptyStr;
3473 }
3474 
3475 
3476 bool CTimeout::IsZero(void) const
3477 {
3478  if ( !IsFinite() ) {
3479  if (m_Type == eDefault) {
3480  NCBI_THROW(CTimeException, eInvalid,
3481  "IsZero() cannot be used with " +
3482  s_SpecialValueName(m_Type) + " timeout");
3483  }
3484  return false;
3485  }
3486  return !(m_Sec | m_NanoSec);
3487 }
3488 
3489 
3490 unsigned long CTimeout::GetAsMilliSeconds(void) const
3491 {
3492  if ( !IsFinite() ) {
3493  NCBI_THROW(CTimeException, eConvert,
3494  "Cannot convert from " +
3495  s_SpecialValueName(m_Type) + " timeout value");
3496  }
3497 #if (SIZEOF_INT == SIZEOF_LONG)
3498  // Roughly calculate maximum number of seconds that can be safely converted
3499  // to milliseconds without an overflow.
3500  if (m_Sec > kMax_ULong / kMilliSecondsPerSecond - 1) {
3501  NCBI_THROW(CTimeException, eConvert,
3502  "Timeout value " +
3504  " too big to convert to unsigned long");
3505  }
3506 #endif
3507  return m_Sec * kMilliSecondsPerSecond +
3509 }
3510 
3511 
3512 double CTimeout::GetAsDouble(void) const
3513 {
3514  if ( !IsFinite() ) {
3515  NCBI_THROW(CTimeException, eConvert,
3516  "Cannot convert from " +
3517  s_SpecialValueName(m_Type) + " timeout value");
3518  }
3519  return m_Sec + double(m_NanoSec) / kNanoSecondsPerSecond;
3520 }
3521 
3522 
3524 {
3525  if ( !IsFinite() ) {
3526  NCBI_THROW(CTimeException, eConvert,
3527  "Cannot convert from " +
3528  s_SpecialValueName(m_Type) + " timeout value");
3529  }
3530 #if (SIZEOF_INT == SIZEOF_LONG)
3531  if ( m_Sec > (unsigned int) kMax_Long ) {
3532  NCBI_THROW(CTimeException, eConvert,
3533  "Timeout value " +
3535  " too big to convert to CTimeSpan");
3536  // We don't need to check microseconds here, because it always keeps a
3537  // normalized value and can always be safely converted to nanoseconds.
3538  }
3539 #endif
3540  CTimeSpan ts(m_Sec, m_NanoSec);
3541  return ts;
3542 }
3543 
3544 
3545 void CTimeout::Get(unsigned int* sec, unsigned int* usec) const
3546 {
3547  if ( !IsFinite() ) {
3548  NCBI_THROW(CTimeException, eConvert,
3549  "Cannot convert from " +
3550  s_SpecialValueName(m_Type) + " timeout value");
3551  }
3552  if ( sec ) {
3553  *sec = m_Sec;
3554  }
3555  if ( usec ) {
3557  }
3558 }
3559 
3560 
3561 void CTimeout::GetNano(unsigned int *sec, unsigned int *nanosec) const
3562 {
3563  if ( !IsFinite() ) {
3564  NCBI_THROW(CTimeException, eConvert,
3565  "Cannot convert from " +
3566  s_SpecialValueName(m_Type) + " timeout value");
3567  }
3568  if ( sec ) {
3569  *sec = m_Sec;
3570  }
3571  if ( nanosec ) {
3572  *nanosec = m_NanoSec;
3573  }
3574 }
3575 
3576 
3578 {
3579  switch(type) {
3580  case eDefault:
3581  case eInfinite:
3582  m_Type = type;
3583  break;
3584  case eZero:
3585  m_Type = eFinite;
3586  Set(0,0);
3587  break;
3588  default:
3589  NCBI_THROW(CTimeException, eArgument,
3590  "Incorrect type value " + NStr::IntToString(type));
3591  }
3592 }
3593 
3594 
3595 void CTimeout::Set(unsigned int sec, unsigned int usec)
3596 {
3597  m_Type = eFinite;
3598  m_Sec = usec / (unsigned int)kMicroSecondsPerSecond + sec;
3599  m_NanoSec = (usec % (unsigned int)kMicroSecondsPerSecond) *
3601 }
3602 
3603 
3604 void CTimeout::SetNano(unsigned int sec, unsigned int nanosec)
3605 {
3606  m_Type = eFinite;
3607  m_Sec = nanosec / (unsigned int)kNanoSecondsPerSecond + sec;
3608  m_NanoSec = nanosec % (unsigned int)kNanoSecondsPerSecond;
3609 }
3610 
3611 
3612 void CTimeout::Set(double sec)
3613 {
3614  if (sec < 0) {
3615  NCBI_THROW(CTimeException, eArgument,
3616  "Cannot set negative value " +
3617  NStr::DoubleToString(sec));
3618  }
3619  if (sec > kMax_UInt) {
3620  NCBI_THROW(CTimeException, eArgument,
3621  "Timeout value " +
3622  NStr::DoubleToString(sec) + " too big");
3623  }
3624  m_Type = eFinite;
3625  m_Sec = (unsigned int) sec;
3626  m_NanoSec = (unsigned int)((sec - m_Sec) * kNanoSecondsPerSecond);
3627 }
3628 
3629 
3630 void CTimeout::Set(const CTimeSpan& ts)
3631 {
3632  if (ts.GetSign() == eNegative) {
3633  NCBI_THROW(CTimeException, eArgument,
3634  "Cannot convert from negative CTimeSpan(" +
3635  ts.AsString() + ")");
3636  }
3637  if ((Uint8) ts.GetCompleteSeconds() > kMax_UInt) {
3638  NCBI_THROW(CTimeException, eArgument,
3639  "CTimeSpan value (" +
3640  ts.AsString() + ") too big");
3641  // We don't need to check nanoseconds, because CTimeSpan always has it
3642  // normalized value, and its value can always be safely converted
3643  // to microseconds.
3644  }
3645  m_Type = eFinite;
3646  m_Sec = (unsigned int) ts.GetCompleteSeconds();
3647  m_NanoSec = (unsigned int) ts.GetNanoSecondsAfterSecond();
3648 }
3649 
3650 
3651 #define COMPARE_TIMEOUT_TYPES(t1, t2) ((int(t1) << 2) | int(t2))
3652 
3653 
3655 {
3656  switch (COMPARE_TIMEOUT_TYPES(m_Type, t.m_Type)) {
3658  return m_Sec == t.m_Sec && m_NanoSec == t.m_NanoSec;
3660  return true; // infinite == infinite
3663  return false; // infinite != value
3664  default:
3665  NCBI_THROW(CTimeException, eArgument,
3666  "Unable to compare with " +
3667  s_SpecialValueName(eDefault) + " timeout");
3668  }
3669 }
3670 
3671 
3672 bool CTimeout::operator< (const CTimeout& t) const
3673 {
3674  switch (COMPARE_TIMEOUT_TYPES(m_Type, t.m_Type)) {
3676  return m_Sec == t.m_Sec ? m_NanoSec < t.m_NanoSec : m_Sec < t.m_Sec;
3678  return true; // value < infinite
3681  return false;
3682  default:
3683  NCBI_THROW(CTimeException, eArgument,
3684  "Unable to compare with " +
3685  s_SpecialValueName(eDefault) + " timeout");
3686  }
3687 }
3688 
3689 
3690 bool CTimeout::operator> (const CTimeout& t) const
3691 {
3692  switch (COMPARE_TIMEOUT_TYPES(m_Type, t.m_Type)) {
3694  return m_Sec == t.m_Sec ? m_NanoSec > t.m_NanoSec : m_Sec > t.m_Sec;
3696  return true; // infinite > value
3699  return false;
3700  default:
3701  NCBI_THROW(CTimeException, eArgument,
3702  "Unable to compare with " +
3703  s_SpecialValueName(eDefault) + " timeout");
3704  }
3705 }
3706 
3707 
3709 {
3710  switch (COMPARE_TIMEOUT_TYPES(m_Type, t.m_Type)) {
3712  return m_Sec == t.m_Sec ? m_NanoSec >= t.m_NanoSec : m_Sec >= t.m_Sec;
3714  return false; // value < infinity
3718  return true; // infinity >= anything
3720  if ( t.IsZero() )
3721  return true; // default >= zero
3722  // fall through
3723  default:
3724  NCBI_THROW(CTimeException, eArgument,
3725  "Unable to compare with " +
3726  s_SpecialValueName(eDefault) + " timeout");
3727  }
3728 }
3729 
3730 
3732 {
3733  switch (COMPARE_TIMEOUT_TYPES(m_Type, t.m_Type)) {
3735  return m_Sec == t.m_Sec ? m_NanoSec <= t.m_NanoSec : m_Sec <= t.m_Sec;
3737  return false; // infinity > value
3741  return true; // anything <= infinity
3743  if ( IsZero() )
3744  return true; // zero <= default
3745  // fall through
3746  default:
3747  NCBI_THROW(CTimeException, eArgument,
3748  "Unable to compare with " +
3749  s_SpecialValueName(eDefault) + " timeout");
3750  }
3751 }
3752 
3753 
3754 
3755 //=============================================================================
3756 //
3757 // CDeadline
3758 //
3759 //=============================================================================
3760 
3762  : m_Seconds(0), m_Nanoseconds(0), m_Infinite(type == eInfinite)
3763 {
3764 }
3765 
3766 
3767 CDeadline::CDeadline(unsigned int seconds, unsigned int nanoseconds)
3768  : m_Seconds(0), m_Nanoseconds(0), m_Infinite(false)
3769 {
3770  // Unless expires immediately
3771  if (seconds || nanoseconds) {
3772  x_SetNowPlus(seconds, nanoseconds);
3773  }
3774 }
3775 
3776 
3778  : m_Seconds(0), m_Nanoseconds(0), m_Infinite(false)
3779 {
3780  if (timeout.IsInfinite()) {
3781  m_Infinite = true;
3782  }
3783  else if (timeout.IsZero()) {
3784  return;
3785  }
3786  else if (timeout.IsFinite()) {
3787  unsigned int sec, usec;
3788  timeout.Get(&sec, &usec);
3789  x_SetNowPlus(sec, usec * (unsigned int)(kNanoSecondsPerSecond / kMicroSecondsPerSecond));
3790  }
3791  else if (timeout.IsDefault()) {
3792  NCBI_THROW(CTimeException, eArgument, "Cannot convert from default CTimeout");
3793  }
3794 }
3795 
3796 
3797 void CDeadline::x_SetNowPlus(unsigned int seconds, unsigned int nanoseconds)
3798 {
3799 #if defined(NCBI_OS_MSWIN)
3800  FILETIME systime;
3801  Uint8 systemp;
3802 
3803  GetSystemTimeAsFileTime(&systime);
3804 
3805  systemp = systime.dwHighDateTime;
3806  systemp <<= 32;
3807  systemp |= systime.dwLowDateTime;
3808  m_Seconds = systemp / 10000000 - NCBI_CONST_UINT8(11644473600);
3809  m_Nanoseconds = (systemp % 10000000) * 100;
3810 #else
3811 # if 0
3812  struct timespec timebuffer;
3813  if (clock_gettime(CLOCK_REALTIME, &timebuffer) == 0) {
3814  m_Seconds = timebuffer.tv_sec;
3815  m_Nanoseconds = timebuffer.tv_nsec;
3816  } else {
3817  NCBI_THROW(CTimeException, eInvalid,
3818  "Cannot get current deadline time value");
3819  }
3820 # else
3821  struct timeval tp;
3822  if (gettimeofday(&tp, 0) == 0) {
3823  m_Seconds = tp.tv_sec;
3824  m_Nanoseconds = (unsigned int)
3825  (tp.tv_usec * (kNanoSecondsPerSecond / kMicroSecondsPerSecond));
3826  } else {
3827  NCBI_THROW(CTimeException, eInvalid,
3828  "Cannot get current deadline time value");
3829  }
3830 # endif
3831 #endif
3832 
3833  if (seconds || nanoseconds) {
3834  nanoseconds += m_Nanoseconds;
3835  seconds += nanoseconds / (unsigned int)kNanoSecondsPerSecond;
3836  m_Nanoseconds = nanoseconds % (unsigned int)kNanoSecondsPerSecond;
3837  m_Seconds += seconds;
3838  }
3839 }
3840 
3841 
3842 void CDeadline::GetExpirationTime(time_t* sec, unsigned int* nanosec) const
3843 {
3844  if ( IsInfinite() ) {
3845  NCBI_THROW(CTimeException, eConvert,
3846  "Cannot convert from " +
3848  " deadline value");
3849  }
3850  if ( sec ) {
3851  *sec = m_Seconds;
3852  }
3853  if ( nanosec ) {
3854  *nanosec = m_Nanoseconds;
3855  }
3856 }
3857 
3858 
3860 {
3861  if ( IsInfinite() ) {
3862  NCBI_THROW(CTimeException, eConvert,
3863  "Cannot convert from " +
3865  " deadline value");
3866  }
3867 
3868  // CDeadline::eNoWait / CDeadline(0, 0) / CDeadline(CTimeout::eZero)
3869  if (!m_Seconds) {
3870  return CNanoTimeout(0, 0);
3871  }
3872 
3873  CDeadline now(0,0);
3874 
3875  // Immediately expiring deadlines do not get actual seconds/nanoseconds anymore,
3876  // so the latter are explicitly set here for 'now' using x_SetNowPlus()
3877  now.x_SetNowPlus(0, 0);
3878 
3879  time_t thenS = m_Seconds;
3880  unsigned int thenNS = m_Nanoseconds;
3881  time_t nowS = now.m_Seconds;
3882  unsigned int nowNS = now.m_Nanoseconds;
3883 
3884  if (thenS < nowS || (thenS == nowS && thenNS <= nowNS)) {
3885  return CNanoTimeout(0,0);
3886  }
3887  if (thenNS >= nowNS) {
3888  thenNS -= nowNS;
3889  } else {
3890  --thenS;
3891  thenNS = (unsigned int)kNanoSecondsPerSecond - (nowNS - thenNS);
3892  }
3893  _ASSERT(thenS >= nowS);
3894  thenS -= nowS;
3895 
3896  return CNanoTimeout((unsigned int)thenS, thenNS);
3897 }
3898 
3899 
3900 bool CDeadline::operator< (const CDeadline& right_hand_operand) const
3901 {
3902  if (!IsInfinite()) {
3903  return right_hand_operand.IsInfinite()
3904  || m_Seconds < right_hand_operand.m_Seconds
3905  || (m_Seconds == right_hand_operand.m_Seconds &&
3906  m_Nanoseconds < right_hand_operand.m_Nanoseconds);
3907  }
3908  if (right_hand_operand.IsInfinite()) {
3909  NCBI_THROW(CTimeException, eInvalid,
3910  "Cannot compare two " +
3912  " deadline values");
3913  }
3914  return false;
3915 }
3916 
3917 
3918 
3919 //=============================================================================
3920 //
3921 // CFastLocalTime
3922 //
3923 //=============================================================================
3924 
3925 CFastLocalTime::CFastLocalTime(unsigned int sec_after_hour)
3926  : m_SecAfterHour(sec_after_hour),
3927  m_LastTuneupTime(0), m_LastSysTime(0),
3928  m_Timezone(0), m_IsTuneup(NULL)
3929 {
3930 #if !defined(NCBI_TIMEZONE_IS_UNDEFINED)
3931  // MT-Safe protect: use CTime locking mutex
3932  CMutexGuard LOCK(s_TimeMutex);
3933  m_Timezone = (int)TimeZone();
3934  m_Daylight = Daylight();
3935  LOCK.Release();
3936 #else
3937  m_Daylight = -1;
3938 #endif
3941 }
3942 
3943 
3945 {
3946  if ( m_IsTuneup ) {
3947  return;
3948  }
3949  // Get system time
3950  time_t timer;
3951  long ns;
3952  CTime::GetCurrentTimeT(&timer, &ns);
3953  x_Tuneup(timer, ns);
3954 }
3955 
3956 
3957 bool CFastLocalTime::x_Tuneup(time_t timer, long nanosec)
3958 {
3959  // Tuneup in progress
3960  if (SwapPointers(&m_IsTuneup, (void*)1))
3961  return false;
3962 
3963  // MT-Safe protect: use CTime locking mutex
3964  CMutexGuard LOCK(s_TimeMutex);
3965  m_TunedTime.x_SetTime(&timer);
3966  m_TunedTime.SetNanoSecond(nanosec);
3967 
3968 #if !defined(NCBI_TIMEZONE_IS_UNDEFINED)
3969  m_Timezone = (int)TimeZone();
3970  m_Daylight = Daylight();
3971 #endif
3972 
3973  LOCK.Release();
3974 
3975  // Copy tuned time to cached local time
3976  CMutexGuard FLT_LOCK(s_FastLocalTimeMutex);
3977  m_LastTuneupTime = timer;
3980 
3981  // Clear flag
3982  m_IsTuneup = NULL;
3983 
3984  return true;
3985 }
3986 
3987 
3989 {
3990  CMutexGuard LOCK(eEmptyGuard);
3991 
3992 retry:
3993  // Get system time
3994  time_t timer;
3995  long ns;
3996  CTime::GetCurrentTimeT(&timer, &ns);
3997 
3998  // Avoid to make time tune up in first m_SecAfterHour for each hour
3999  // Otherwise do this at each hours/timezone change.
4000  if ( !m_IsTuneup ) {
4001 #if !defined(NCBI_TIMEZONE_IS_UNDEFINED)
4002  // Get current timezone
4003  TSeconds x_timezone;
4004  int x_daylight;
4005  {{
4006  // MT-Safe protect: use CTime locking mutex
4007  CMutexGuard LOCK_TM(s_TimeMutex);
4008  x_timezone = TimeZone();
4009  x_daylight = Daylight();
4010  }}
4011 #endif
4012  if ( !m_LastTuneupTime ||
4013  ((timer / 3600 != m_LastTuneupTime / 3600) &&
4014  (timer % 3600 > (time_t)m_SecAfterHour))
4015 #if !defined(NCBI_TIMEZONE_IS_UNDEFINED)
4016  || (x_timezone != m_Timezone || x_daylight != m_Daylight)
4017 #endif
4018  ) {
4019  if (x_Tuneup(timer, ns)) {
4020  return m_LocalTime;
4021  }
4022  }
4023  }
4024  // MT-Safe protect
4025  LOCK.Guard(s_FastLocalTimeMutex);
4026 
4027  if ( !m_LastTuneupTime ) {
4028  LOCK.Release();
4029  NCBI_SCHED_YIELD();
4030  goto retry;
4031  } else {
4032  // Adjust local time on base of system time without any system calls
4035  }
4036  m_LastSysTime = timer;
4037 
4038  // Return computed local time
4039  return m_LocalTime;
4040 }
4041 
4042 
4044 {
4045 #if !defined(NCBI_TIMEZONE_IS_UNDEFINED)
4046  // Get system timer
4047  time_t timer;
4048  long ns;
4049  CTime::GetCurrentTimeT(&timer, &ns);
4050 
4051  // Avoid to make time tune up in first m_SecAfterHour for each hour
4052  // Otherwise do this at each hours/timezone change.
4053  if ( !m_IsTuneup ) {
4054  // Get current timezone
4055  TSeconds x_timezone;
4056  int x_daylight;
4057  {{
4058  // MT-Safe protect: use CTime locking mutex
4059  CMutexGuard LOCK(s_TimeMutex);
4060  x_timezone = TimeZone();
4061  x_daylight = Daylight();
4062  }}
4063  if ( !m_LastTuneupTime ||
4064  ((timer / 3600 != m_LastTuneupTime / 3600) &&
4065  (timer % 3600 > (time_t)m_SecAfterHour))
4066  || (x_timezone != m_Timezone || x_daylight != m_Daylight)
4067  ) {
4068  x_Tuneup(timer, ns);
4069  }
4070  }
4071 #endif
4072  // Return local timezone
4073  return m_Timezone;
4074 }
4075 
4076 
4077 //=============================================================================
4078 //
4079 // CStopWatch
4080 //
4081 //=============================================================================
4082 
4083 /// @deprecated
4085 {
4086  m_Total = 0;
4087  m_Start = 0;
4088  m_State = eStop;
4089  if ( start ) {
4090  Start();
4091  }
4092 } // NCBI_FAKE_WARNING
4093 
4094 
4096 {
4097 #if defined(NCBI_OS_MSWIN)
4098  // For Win32, we use QueryPerformanceCounter()
4099 
4100  LARGE_INTEGER bigint;
4101  static double freq;
4102  static bool first = true;
4103 
4104  if ( first ) {
4105  LARGE_INTEGER nfreq;
4106  QueryPerformanceFrequency(&nfreq);
4107  freq = double(nfreq.QuadPart);
4108  first = false;
4109  }
4110 
4111  if ( !QueryPerformanceCounter(&bigint) ) {
4112  return 0.0;
4113  }
4114  return double(bigint.QuadPart) / freq;
4115 #else
4116  // For Unixes, we use gettimeofday()
4117 
4118  struct timeval time;
4119  if ( gettimeofday (&time, 0) ) {
4120  return 0.0;
4121  }
4122  return double(time.tv_sec) + double(time.tv_usec) / 1e6;
4123 #endif
4124 }
4125 
4126 
4128 {
4129  // Here we do not need to delete a previous value stored in the TLS.
4130  // The TLS will destroy it using cleanup function.
4131  CTimeFormat* ptr = new CTimeFormat(fmt);
4132  s_TlsFormatStopWatch.SetValue(ptr, CTlsBase::DefaultCleanup<CTimeFormat>);
4133 }
4134 
4135 
4137 {
4138  CTimeFormat fmt;
4139  CTimeFormat* ptr = s_TlsFormatStopWatch.GetValue();
4140  if ( !ptr ) {
4142  } else {
4143  fmt = *ptr;
4144  }
4145  return fmt;
4146 }
4147 
4148 
4149 string CStopWatch::AsString(const CTimeFormat& fmt) const
4150 {
4151  double e = Elapsed();
4152  CTimeSpan ts(e < 0.0 ? 0.0 : e);
4153  if ( fmt.IsEmpty() ) {
4154  return ts.AsString(GetFormat());
4155  }
4156  return ts.AsString(fmt);
4157 }
4158 
4159 
4160 //============================================================================
4161 //
4162 // Extern
4163 //
4164 //============================================================================
4165 
4166 
4168 {
4169  return s_FastLocalTime->GetLocalTime();
4170 }
4171 
4172 
4174 {
4175  s_FastLocalTime->Tuneup();
4176 }
4177 
4178 const char* CTimeException::GetErrCodeString(void) const
4179 {
4180  switch (GetErrCode()) {
4181  case eArgument: return "eArgument";
4182  case eConvert: return "eConvert";
4183  case eInvalid: return "eInvalid";
4184  case eFormat: return "eFormat";
4185  default: return CException::GetErrCodeString();
4186  }
4187 }
4188 
CCoreException –.
Definition: ncbiexpt.hpp:1476
CDeadline.
Definition: ncbitime.hpp:1830
void Guard(resource_type &resource)
Manually force the guard to protect some other resource.
Definition: guard.hpp:175
void Release()
Manually force the resource to be released.
Definition: guard.hpp:166
CNanoTimeout – Timeout interval, using nanoseconds.
Definition: ncbitime.hpp:1810
CSafeStatic<>::
CStringException –.
Definition: ncbistr.hpp:4508
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
CTimeException –.
Definition: ncbitime.hpp:2075
CTimeFormat –.
Definition: ncbitime.hpp:131
CTimeSpan.
Definition: ncbitime.hpp:1313
CTime –.
Definition: ncbitime.hpp:296
CTimeout – Timeout interval.
Definition: ncbitime.hpp:1693
static uch flags
std::ofstream out("events_result.xml")
main entry point for tests
const char * months[]
Definition: ftaerr.cpp:118
#define false
Definition: bool.h:36
static DLIST_TYPE *DLIST_NAME() first(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:46
static char precision
Definition: genparams.c:28
static int type
Definition: getdata.c:31
static const char * str(char *buf, int n)
Definition: stats.c:84
static char tmp[3200]
Definition: utf8.c:42
int offset
Definition: replacements.h:160
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
@ eNegative
Value is negative.
Definition: ncbimisc.hpp:121
@ eZero
Value is zero.
Definition: ncbimisc.hpp:122
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
Definition: ncbidiag.hpp:550
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
TErrCode GetErrCode(void) const
Definition: ncbiexpt.hpp:1493
virtual const char * GetErrCodeString(void) const
Get error code interpreted as text.
Definition: ncbiexpt.cpp:444
const CVect2< U > & v2
Definition: globals.hpp:440
int32_t Int4
4-byte (32-bit) signed integer
Definition: ncbitype.h:102
uint16_t Uint2
2-byte (16-bit) unsigned integer
Definition: ncbitype.h:101
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#define kMax_UInt
Definition: ncbi_limits.h:185
#define CHAR_BIT
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static string Int8ToString(Int8 value, TNumToStringFlags flags=0, int base=10)
Convert Int8 to string.
Definition: ncbistr.hpp:5161
static string DoubleToString(double value, int precision=-1, TNumToStringFlags flags=0)
Convert double to string.
Definition: ncbistr.hpp:5189
#define kEmptyStr
Definition: ncbistr.hpp:123
static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
Definition: ncbistr.cpp:219
static string LongToString(long value, TNumToStringFlags flags=0, int base=10)
Convert Int to string.
Definition: ncbistr.hpp:5143
#define NPOS
Definition: ncbistr.hpp:133
static int strncasecmp(const char *s1, const char *s2, size_t n)
Case-insensitive comparison of two zero-terminated strings, narrowed to the specified number of chara...
Definition: ncbistr.hpp:5249
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5086
static unsigned long StringToULong(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to unsigned long.
Definition: ncbistr.cpp:665
static long StringToLong(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to long.
Definition: ncbistr.cpp:653
static string UIntToString(unsigned int value, TNumToStringFlags flags=0, int base=10)
Convert UInt to string.
Definition: ncbistr.hpp:5111
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
static string & ToLower(string &str)
Convert string to lower case – string& version.
Definition: ncbistr.cpp:405
@ fAllowTrailingSymbols
Ignore trailing non-numerics characters.
Definition: ncbistr.hpp:298
#define NCBI_SCHED_YIELD()
Int8 TSeconds
Number of seconds.
Definition: ncbitime.hpp:77
unsigned int TFlags
Binary OR of "EFlags".
Definition: ncbitime.hpp:185
CFastLocalTime(unsigned int sec_after_hour=5)
Constructor.
Definition: ncbitime.cpp:3925
unsigned char min
Definition: ncbitime.hpp:1252
bool x_Init(const string &str, const CTimeFormat &fmt, EErrAction err_action=eErr_Throw)
Helper method to set time value from string "str" using format "fmt".
Definition: ncbitime.cpp:507
double m_Total
Accumulated elapsed time.
Definition: ncbitime.hpp:2059
int Minute(void) const
Get minute.
Definition: ncbitime.hpp:2277
static string DayOfWeekNumToName(int day, ENameFormat format=eFull)
Get name of the day of week by numerical value.
Definition: ncbitime.cpp:1259
CTime & Truncate(ERoundPrecision precision=eRound_Day)
Truncate time.
Definition: ncbitime.cpp:1970
string TimeZoneOffsetStr(void)
Get time zone offset string in format [+/-]HHMM.
Definition: ncbitime.cpp:2231
int x_Second(void) const
Get second.
Definition: ncbitime.hpp:2547
void SetMinute(int minute)
Set minute.
Definition: ncbitime.cpp:1099
ETimeZonePrecision GetTimeZonePrecision(void) const
Get time zone precision.
Definition: ncbitime.hpp:2436
CTime & ToLocalTime(void)
Convert the time into local time.
Definition: ncbitime.hpp:2464
CTime(EInitMode mode=eEmpty, ETimeZone tz=eLocal, ETimeZonePrecision tzp=eTZPrecisionDefault)
Constructor.
Definition: ncbitime.cpp:985
TSeconds TimeZoneOffset(void) const
Get difference between local timezone for current time object and UTC in seconds.
Definition: ncbitime.cpp:2218
void SetMonth(int month)
Set month.
Definition: ncbitime.cpp:1057
EInitMode
Which initial value to use for time.
Definition: ncbitime.hpp:299
unsigned int TSmartStringFlags
Binary OR of "ESmartStringFlags".
Definition: ncbitime.hpp:1499
CTimeSpan & operator=(const CTimeSpan &t)
Assignment operator.
Definition: ncbitime.hpp:2585
void SetSecond(int second)
Set second.
Definition: ncbitime.cpp:1106
EDayOfWeek
Day of week names.
Definition: ncbitime.hpp:339
int DayOfWeek(void) const
Get day of week.
Definition: ncbitime.cpp:1186
CNanoTimeout GetRemainingTime(void) const
Get time left to the expiration.
Definition: ncbitime.cpp:3859
Int4 days
days from 1/1/1900
Definition: ncbitime.hpp:115
static void SetFormat(const CTimeFormat &fmt)
Set the current time format.
Definition: ncbitime.cpp:1268
CTime & AddTimeSpan(const CTimeSpan &timespan)
Add specified time span.
Definition: ncbitime.cpp:1912
double Elapsed(void) const
Return time elapsed since first Start() or last Restart() call (in seconds).
Definition: ncbitime.hpp:2775
unsigned char month
Definition: ncbitime.hpp:1249
unsigned char sec
Definition: ncbitime.hpp:1253
static void SetFormat(const CTimeFormat &format)
Set the current time span format.
Definition: ncbitime.cpp:2659
EErrAction
Defines how to behave on error.
Definition: ncbitime.hpp:1193
CTime & x_AddHour(int hours=1, EDaylight daylight=eDaylightDefault, bool shift_time=true)
Helper method to add hour with/without shift time.
Definition: ncbitime.cpp:1820
void SetMicroSecond(long microsecond)
Set microseconds.
Definition: ncbitime.cpp:1120
TData m_Data
Packed members.
Definition: ncbitime.hpp:1263
bool operator>(const CTime &t) const
Operator to test if time is later.
Definition: ncbitime.cpp:2137
bool IsUniversalTime(void) const
Is time universal (GMT/UTC/Z)?
Definition: ncbitime.hpp:2421
ETimeZone
Which initial value to use for timezone.
Definition: ncbitime.hpp:305
CTime & SetTimeDBI(const TDBTimeI &t)
Set time using database format time, TDBTimeI.
Definition: ncbitime.cpp:1496
CTime & AddNanoSecond(long nanoseconds=1)
Add specified nanoseconds.
Definition: ncbitime.cpp:1896
void SetFormat(const char *fmt, TFlags flags=fDefault)
Set the current time format.
Definition: ncbitime.hpp:2230
CTime & Round(ERoundPrecision precision=eRound_Day, EDaylight adl=eDaylightDefault)
Round time.
Definition: ncbitime.cpp:1923
long GetCompleteMinutes(void) const
Get number of complete minutes.
Definition: ncbitime.hpp:2556
bool x_Tuneup(time_t timer, long nanosec)
Internal version of Tuneup()
Definition: ncbitime.cpp:3957
CTimeSpan GetAsTimeSpan(void) const
Convert to CTimeSpan.
Definition: ncbitime.cpp:3523
void x_Normalize(void)
Helper method to normalize stored time value.
Definition: ncbitime.cpp:2644
CTime & AddSecond(TSeconds seconds=1, EDaylight adl=eDaylightDefault)
Add specified seconds.
Definition: ncbitime.cpp:1880
unsigned char hour
Definition: ncbitime.hpp:1251
long GetCompleteDays(void) const
Get number of complete days.
Definition: ncbitime.hpp:2550
ETimeZone GetTimeZone(void) const
Get time zone.
Definition: ncbitime.hpp:2424
int m_Timezone
Cached timezone adjustment for local time.
Definition: ncbitime.hpp:1924
bool x_NeedAdjustTime(void) const
Helper method to check if there is a need adjust time in timezone.
Definition: ncbitime.hpp:2485
long GetNanoSecondsAfterSecond(void) const
Get number of nanoseconds.
Definition: ncbitime.hpp:2562
CTime & x_AdjustTime(const CTime &from, bool shift_time=true)
Helper method to adjust the time to correct timezone (across the barrier of winter & summer times) us...
Definition: ncbitime.cpp:2340
void Set(long seconds, long nanoseconds=0)
Set time span in seconds and nanoseconds.
Definition: ncbitime.hpp:2571
int DiffWholeDays(const CTime &t) const
Difference in whole days from specified time.
Definition: ncbitime.cpp:2277
EDaylight
Whether to adjust for daylight saving time.
Definition: ncbitime.hpp:367
CTime GetUniversalTime(void) const
Get the time as universal (GMT/UTC) time.
Definition: ncbitime.cpp:2061
int MonthWeekNumber(EDayOfWeek first_day_of_week=eSunday) const
Get this date's week number in the month.
Definition: ncbitime.cpp:1177
unsigned int year
Definition: ncbitime.hpp:1248
ETimeZonePrecision SetTimeZonePrecision(ETimeZonePrecision val)
Set time zone precision.
Definition: ncbitime.hpp:2456
CTime m_TunedTime
Last tuned time (changed by Tuneup())
Definition: ncbitime.hpp:1920
EType
Type of timeouts.
Definition: ncbitime.hpp:1696
CTime & AddMonth(int months=1, EDaylight adl=eDaylightDefault)
Add specified months and adjust for daylight saving time.
Definition: ncbitime.cpp:1757
CTime & Clear(void)
Make the time "empty",.
Definition: ncbitime.cpp:1999
long NanoSecond(void) const
Get nano-seconds.
Definition: ncbitime.hpp:2289
void SetYear(int year)
Set year.
Definition: ncbitime.cpp:1040
unsigned int m_SecAfterHour
Time interval in seconds after hour.
Definition: ncbitime.hpp:1917
int Year(void) const
Get year.
Definition: ncbitime.hpp:2265
void SetMilliSecond(long millisecond)
Set milliseconds.
Definition: ncbitime.cpp:1113
string AsString(const CTimeFormat &format=kEmptyStr, TSeconds out_tz=eCurrentTimeZone) const
Transform time to string.
Definition: ncbitime.cpp:1512
int YearWeekNumber(EDayOfWeek first_day_of_week=eSunday) const
Get this date's week number within the year.
Definition: ncbitime.cpp:1143
string x_AsSmartString_Precision(TSmartStringFlags flags) const
Definition: ncbitime.cpp:3009
void x_Init(const string &str, const CTimeFormat &fmt)
Helper method to set time value from string "str" using format "fmt".
Definition: ncbitime.cpp:2480
string x_AsSmartString_Smart_Small(TSmartStringFlags flags) const
Definition: ncbitime.cpp:2907
const long kMilliSecondsPerSecond
Number milliseconds in one second.
Definition: ncbitime.hpp:96
void SetHour(int hour)
Set hour.
Definition: ncbitime.cpp:1092
CTime & ToTime(ETimeZone val)
Convert the time into specified time zone time.
Definition: ncbitime.cpp:2074
bool IsInfinite() const
Definition: ncbitime.hpp:2729
time_t m_LastSysTime
Last system time.
Definition: ncbitime.hpp:1923
bool IsEmpty(void) const
Is time object empty (date and time)?
Definition: ncbitime.hpp:2377
bool operator<(const CTimeout &t) const
Operator to test if timeout is less.
Definition: ncbitime.cpp:3672
double GetAsDouble(void) const
Get as number of seconds (fractional value).
Definition: ncbitime.cpp:3512
TFlags m_Flags
Format flags.
Definition: ncbitime.hpp:274
bool operator<(const CTime &t) const
Operator to test if time is earlier.
Definition: ncbitime.cpp:2174
CStopWatch(EStart state=eStop)
Constructor.
Definition: ncbitime.hpp:2753
CTime & ToUniversalTime(void)
Convert the time into universal (GMT/UTC) time.
Definition: ncbitime.hpp:2471
bool IsValid(void) const
Is time valid?
Definition: ncbitime.cpp:2013
static CTimeFormat GetFormat(void)
Get the current time span format.
Definition: ncbitime.cpp:2668
ESign GetSign(void) const
Get sign of time span.
Definition: ncbitime.hpp:2529
string TimeZoneName(void)
Get current time zone name.
Definition: ncbitime.cpp:2248
bool operator==(const CTimeout &t) const
Operator to test equality of timeouts.
Definition: ncbitime.cpp:3654
void Invert(void)
Invert time span. Changes time span sign.
Definition: ncbitime.hpp:2637
CTime & SetCurrent(void)
Make the time current in the presently active time zone.
Definition: ncbitime.hpp:2301
bool IsZero() const
Definition: ncbitime.cpp:3476
void x_AdjustDay(void)
Helper method to adjust day number to correct value after day manipulations.
Definition: ncbitime.cpp:2331
void Tuneup(void)
Do unscheduled check.
Definition: ncbitime.cpp:3944
CTime & SetTimeDBU(const TDBTimeU &t)
Set time using database format time, TDBTimeU.
Definition: ncbitime.cpp:1481
unsigned int m_Nanoseconds
Definition: ncbitime.hpp:1874
CTimeSpan & AssignFromSmartString(const string &str)
Assign value to time span object from string representation of time in formats produced by AsSmartStr...
Definition: ncbitime.cpp:3263
EPredefined
Predefined formats.
Definition: ncbitime.hpp:190
ETimeZonePrecision
What time zone precision to use for adjusting daylight saving time.
Definition: ncbitime.hpp:357
CTime & x_SetTime(const time_t *t=0)
Helper method to set time from 'time_t' – If "t" not specified, then set to current time.
Definition: ncbitime.cpp:1710
string AsSmartString(ESmartStringPrecision precision, ERound rounding, ESmartStringZeroMode zero_mode=eSSZ_SkipZero) const
Transform time span to "smart" string.
Definition: ncbitime.hpp:2688
void SetNano(unsigned int sec, unsigned int nanosec)
Set timeout in seconds and nanoseconds.
Definition: ncbitime.cpp:3604
static CTimeFormat GetFormat(void)
Get the current stopwatch time format.
Definition: ncbitime.cpp:4136
static void SetFormat(const CTimeFormat &fmt)
Set the current stopwatch time format.
Definition: ncbitime.cpp:4127
const TSeconds kAverageSecondsPerMonth
Definition: ncbitime.hpp:102
CTimeSpan DiffTimeSpan(const CTime &t) const
Difference in nanoseconds from specified time.
Definition: ncbitime.cpp:2305
int DaysInMonth(void) const
Get number of days in the month.
Definition: ncbitime.cpp:1199
bool operator<(const CDeadline &right_hand_operand) const
Compare two CDeadline values.
Definition: ncbitime.cpp:3900
CDeadline(EType type=eNoWait)
Initialize deadline of specified type.
Definition: ncbitime.cpp:3761
time_t GetTimeT(void) const
Get time in time_t format.
Definition: ncbitime.cpp:1396
TDBTimeI GetTimeDBI(void) const
Get time in database format time, TDBTimeI.
Definition: ncbitime.cpp:1467
unsigned int m_Sec
Seconds part of the timeout.
Definition: ncbitime.hpp:1795
CTimeSpan(void)
Default constructor.
Definition: ncbitime.hpp:2496
int GetLocalTimezone(void)
Get difference in seconds between UTC and current local time (daylight information included)
Definition: ncbitime.cpp:4043
bool operator<=(const CTimeout &t) const
Operator to test if timeout is less or equal.
Definition: ncbitime.cpp:3731
void SetDay(int day)
Set day.
Definition: ncbitime.cpp:1074
ETimeZonePrecision tzprec
Definition: ncbitime.hpp:1259
int Day(void) const
Get day.
Definition: ncbitime.hpp:2271
void GetNano(unsigned int *sec, unsigned int *nanosec) const
Get timeout in seconds and nanoseconds.
Definition: ncbitime.cpp:3561
unsigned long GetAsMilliSeconds(void) const
Get as number of milliseconds.
Definition: ncbitime.cpp:3490
static double GetTimeMark()
Get current time mark.
Definition: ncbitime.cpp:4095
unsigned char day
Definition: ncbitime.hpp:1250
TSeconds DiffSecond(const CTime &t) const
Difference in seconds from specified time.
Definition: ncbitime.cpp:2282
TDBTimeU GetTimeDBU(void) const
Get time in database format time, TDBTimeU.
Definition: ncbitime.cpp:1454
unsigned int m_NanoSec
Nanoseconds part of the timeout.
Definition: ncbitime.hpp:1796
int x_Hour(void) const
Get hour.
Definition: ncbitime.hpp:2541
bool m_Infinite
Definition: ncbitime.hpp:1875
Uint2 days
Days from 1/1/1900.
Definition: ncbitime.hpp:109
static CTimeFormat GetPredefined(EPredefined fmt, TFlags flags=fDefault)
Get predefined format.
Definition: ncbitime.cpp:389
void Start(void)
Start the timer.
Definition: ncbitime.hpp:2764
static CTimeFormat GetFormat(void)
Get the current time format.
Definition: ncbitime.cpp:1277
bool IsLeap(void) const
Is time in a leap year?
Definition: ncbitime.cpp:2211
bool IsEmpty(void) const
Check that format string is empty.
Definition: ncbitime.hpp:2248
CTime & SetTimeTM(const struct tm &t)
Set time using "struct tm" time value.
Definition: ncbitime.cpp:1424
long m_NanoSec
Nanoseconds after the second.
Definition: ncbitime.hpp:1680
string AsString(const CTimeFormat &fmt=kEmptyStr) const
Transform time span to string.
Definition: ncbitime.cpp:2681
bool IsDefault() const
Definition: ncbitime.hpp:2723
static int MonthNameToNum(const string &month)
Get numerical value of the month by name.
Definition: ncbitime.cpp:1212
Uint2 time
Minutes from the beginning of current day.
Definition: ncbitime.hpp:110
Int4 time
x/300 seconds from the beginning of current day
Definition: ncbitime.hpp:116
CTime m_LocalTime
Current local time.
Definition: ncbitime.hpp:1919
string AsString(const CTimeFormat &fmt=kEmptyStr) const
Transform stopwatch time to string.
Definition: ncbitime.cpp:4149
void Set(EType type)
Set special value.
Definition: ncbitime.cpp:3577
int m_Daylight
Cached system daylight information.
Definition: ncbitime.hpp:1925
CTime GetFastLocalTime(void)
Quick and dirty getter of local time.
Definition: ncbitime.cpp:4167
int x_Minute(void) const
Get minute.
Definition: ncbitime.hpp:2544
void Get(unsigned int *sec, unsigned int *microsec) const
Get timeout in seconds and microseconds.
Definition: ncbitime.cpp:3545
ERoundPrecision
Precision for rounding time.
Definition: ncbitime.hpp:982
CTime & x_AdjustTimeImmediately(const CTime &from, bool shift_time=true)
Helper method to forcibly adjust timezone using "from" as a reference point.
Definition: ncbitime.cpp:2365
void SetNanoSecond(long nanosecond)
Set nanoseconds.
Definition: ncbitime.cpp:1127
CTime & SetTimeT(const time_t t)
Set time using time_t time value.
Definition: ncbitime.hpp:2298
virtual const char * GetErrCodeString(void) const override
Translate from the error code value to its string representation.
Definition: ncbitime.cpp:4178
CTimeFormat(void)
Default constructor.
Definition: ncbitime.cpp:327
bool operator>=(const CTimeout &t) const
Operator to test if timeout is greater or equal.
Definition: ncbitime.cpp:3708
int Hour(void) const
Get hour.
Definition: ncbitime.hpp:2274
bool IsInfinite(void) const
Check if the deadline is infinite.
Definition: ncbitime.hpp:1852
CTime & x_SetTimeMTSafe(const time_t *t=0)
Version of x_SetTime() with MT-safe locks.
Definition: ncbitime.cpp:1663
bool IsFinite() const
Check if timeout holds a numeric value.
Definition: ncbitime.hpp:2735
void TuneupFastLocalTime(void)
Definition: ncbitime.cpp:4173
double m_Start
Start time value.
Definition: ncbitime.hpp:2058
CTime GetLocalTime(void) const
Get the time as local time.
Definition: ncbitime.cpp:2048
CTime GetLocalTime(void)
Get local time.
Definition: ncbitime.cpp:3988
CTimeSpan & Clear(void)
Make the time span "empty",.
Definition: ncbitime.hpp:2522
string m_Str
String format.
Definition: ncbitime.hpp:273
void x_SetNowPlus(unsigned int seconds, unsigned int nanoseconds)
Definition: ncbitime.cpp:3797
CTime & AddDay(int days=1, EDaylight adl=eDaylightDefault)
Add specified days and adjust for daylight saving time.
Definition: ncbitime.cpp:1788
CTimeFormat & operator=(const CTimeFormat &fmt)
Assignment operator.
Definition: ncbitime.cpp:378
EType
Type of special deadlines.
Definition: ncbitime.hpp:1833
bool IsLocalTime(void) const
Is time local time?
Definition: ncbitime.hpp:2418
Int4 adjTimeDiff
Definition: ncbitime.hpp:1256
const long kMicroSecondsPerSecond
Number of microseconds in one second.
Definition: ncbitime.hpp:91
long GetCompleteSeconds(void) const
Get number of complete seconds.
Definition: ncbitime.hpp:2559
static string MonthNumToName(int month, ENameFormat format=eFull)
Get name of the month by numerical value.
Definition: ncbitime.cpp:1230
time_t m_Seconds
Definition: ncbitime.hpp:1873
EStart m_State
Stopwatch state (started/stopped)
Definition: ncbitime.hpp:2060
CTime & AddHour(int hours=1, EDaylight adl=eDaylightDefault)
Add specified hours and adjust for daylight saving time.
Definition: ncbitime.hpp:2371
bool IsDST(void) const
Is DST (daylight savings time) in effect for this time?
Definition: ncbitime.cpp:1385
const TSeconds kAverageSecondsPerYear
The average length of the year in the Gregorian (modern) calendar (in seconds)
Definition: ncbitime.hpp:101
int Second(void) const
Get second.
Definition: ncbitime.hpp:2280
int Month(void) const
Get month.
Definition: ncbitime.hpp:2268
long GetCompleteHours(void) const
Get number of complete hours.
Definition: ncbitime.hpp:2553
CTime & AddMinute(int minutes=1, EDaylight adl=eDaylightDefault)
Add specified minutes and adjust for daylight saving time.
Definition: ncbitime.cpp:1850
void *volatile m_IsTuneup
(bool) Tuneup() in progress (MT)
Definition: ncbitime.hpp:1926
static int DayOfWeekNameToNum(const string &day)
Get numerical value of the day of week by name.
Definition: ncbitime.cpp:1241
const long kNanoSecondsPerSecond
Number of nanoseconds in one second.
Definition: ncbitime.hpp:86
EType m_Type
Type of timeout.
Definition: ncbitime.hpp:1794
static void GetCurrentTimeT(time_t *sec, long *nanosec=0)
Get current UTC time in time_t format (with nanoseconds).
Definition: ncbitime.cpp:1672
static bool ValidateString(const string &str, const CTimeFormat &fmt=kEmptyStr)
Validate if string match time format.
Definition: ncbitime.cpp:1033
int YearDayNumber(void) const
Get year's day number.
Definition: ncbitime.cpp:1134
ENameFormat
Which format use to get name of month or week of day.
Definition: ncbitime.hpp:317
time_t m_LastTuneupTime
Last Tuneup() time.
Definition: ncbitime.hpp:1922
bool operator>(const CTimeout &t) const
Operator to test if timeout is greater.
Definition: ncbitime.cpp:3690
ETimeZone tz
Definition: ncbitime.hpp:1258
bool operator==(const CTime &t) const
Operator to test equality of time.
Definition: ncbitime.cpp:2120
long m_Sec
Seconds part of the time span.
Definition: ncbitime.hpp:1679
bool IsEmptyDate(void) const
Is date empty?
Definition: ncbitime.hpp:2385
void GetExpirationTime(time_t *sec, unsigned int *nanosec) const
Get the number of seconds and nanoseconds (since 1/1/1970).
Definition: ncbitime.cpp:3842
string x_AsSmartString_Smart_Big(TSmartStringFlags flags) const
Helpers for AsSmartString()
Definition: ncbitime.cpp:2805
@ eCurrent
Use current time. See also CCurrentTime.
Definition: ncbitime.hpp:300
@ eSaturday
Definition: ncbitime.hpp:346
@ eErr_Throw
Throw an exception on error.
Definition: ncbitime.hpp:1194
@ eErr_NoThrow
Return default value on error.
Definition: ncbitime.hpp:1195
@ eUTC
UTC (Universal Coordinated Time)
Definition: ncbitime.hpp:307
@ eGmt
GMT (Greenwich Mean Time)
Definition: ncbitime.hpp:308
@ eLocal
Local time.
Definition: ncbitime.hpp:306
@ eConvert
Error converting value from one format to another.
Definition: ncbitime.hpp:2080
@ eFormat
Incorrect format.
Definition: ncbitime.hpp:2082
@ eInvalid
Invalid time value.
Definition: ncbitime.hpp:2081
@ eArgument
Bad function argument.
Definition: ncbitime.hpp:2079
@ eAdjustDaylight
Adjust for daylight saving time.
Definition: ncbitime.hpp:369
@ eIgnoreDaylight
Ignore daylight saving time.
Definition: ncbitime.hpp:368
@ eDefault
Default timeout (to be interpreted by the client code)
Definition: ncbitime.hpp:1698
@ eInfinite
Infinite timeout.
Definition: ncbitime.hpp:1699
@ eFinite
A finite timeout value has been set.
Definition: ncbitime.hpp:1697
@ eZero
Zero timeout, equal to CTimeout(0,0).
Definition: ncbitime.hpp:1700
@ eMinute
Check condition - new minute.
Definition: ncbitime.hpp:359
@ eMonth
Check condition - new month.
Definition: ncbitime.hpp:362
@ eDay
Check condition - new day.
Definition: ncbitime.hpp:361
@ eHour
Check condition - new hour.
Definition: ncbitime.hpp:360
@ eStop
Do not start timer, just create it.
Definition: ncbitime.hpp:1942
@ eCurrentTimeZone
Definition: ncbitime.hpp:313
@ fSS_Precision4
Floating precision level 4.
Definition: ncbitime.hpp:1464
@ fSS_Nanosecond
Do not round at all (accurate time span)
Definition: ncbitime.hpp:1460
@ fSS_Year
Round to years.
Definition: ncbitime.hpp:1452
@ fSS_Precision6
Floating precision level 6.
Definition: ncbitime.hpp:1466
@ fSS_Millisecond
Round to milliseconds.
Definition: ncbitime.hpp:1458
@ fSS_Hour
Round to hours.
Definition: ncbitime.hpp:1455
@ fSS_Precision7
Floating precision level 7.
Definition: ncbitime.hpp:1467
@ fSS_Precision2
Floating precision level 2.
Definition: ncbitime.hpp:1462
@ fSS_Microsecond
Round to microseconds.
Definition: ncbitime.hpp:1459
@ fSS_Precision5
Floating precision level 5.
Definition: ncbitime.hpp:1465
@ fSS_Precision1
Floating precision level 1.
Definition: ncbitime.hpp:1461
@ fSS_Smart
Be as smart as possible (see above)
Definition: ncbitime.hpp:1468
@ fSS_PrecisionMask
Mask of precision flags (sum of all above)
Definition: ncbitime.hpp:1469
@ fSS_Precision3
Floating precision level 3.
Definition: ncbitime.hpp:1463
@ fSS_Month
Round to months.
Definition: ncbitime.hpp:1453
@ fSS_Day
Round to days.
Definition: ncbitime.hpp:1454
@ fSS_Minute
Round to minutes.
Definition: ncbitime.hpp:1456
@ fSS_Second
Round to seconds.
Definition: ncbitime.hpp:1457
@ fSS_NoSkipZero
Definition: ncbitime.hpp:1486
@ eRound_Minute
Round to minutes.
Definition: ncbitime.hpp:985
@ eRound_Day
Round to days.
Definition: ncbitime.hpp:983
@ eRound_Hour
Round to hours.
Definition: ncbitime.hpp:984
@ eRound_Millisecond
Round to milliseconds.
Definition: ncbitime.hpp:987
@ eRound_Second
Round to seconds.
Definition: ncbitime.hpp:986
@ eRound_Microsecond
Round to microseconds.
Definition: ncbitime.hpp:988
@ fFormat_Ncbi
Specify each format symbol with a preceding symbol '$'.
Definition: ncbitime.hpp:149
@ fMatch_Weak
Combination of both modes above.
Definition: ncbitime.hpp:165
@ fMatch_IgnoreSpaces
Ignore all white spaces in the time and format strings on the matching/parsing step (CTime only).
Definition: ncbitime.hpp:171
@ fMatch_ShortFormat
eg "Y" and "1997/07/16"
Definition: ncbitime.hpp:160
@ fConf_UTC
Prefer "UTC" over "GMT" abbreviation for universal time.
Definition: ncbitime.hpp:175
@ fMatch_ShortTime
A time/format string can have extra trailing format symbols, that do not have matching symbols in the...
Definition: ncbitime.hpp:159
@ fFormat_Simple
Use single characters as format symbols.
Definition: ncbitime.hpp:144
@ fMatch_Strict
A time string should strictly match the format string.
Definition: ncbitime.hpp:154
@ eFull
Use full name.
Definition: ncbitime.hpp:318
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
@ eEmptyGuard
Definition: guard.hpp:94
Definition of all error codes used in corelib (xncbi.lib).
char * buf
int i
yy_size_t n
int len
mdb_mode_t mode
Definition: lmdb++.h:38
const struct ncbi::grid::netcache::search::fields::SIZE size
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
#define abs(a)
Definition: ncbi_heapmgr.c:130
EIPRangeType t
Definition: ncbi_localip.c:101
Static variables safety - create on demand, destroy on application termination.
#define NCBI_CONST_UINT8(v)
Definition: ncbi_std.h:196
void * SwapPointers(void *volatile *location, void *new_value)
Definition: ncbiatomic.hpp:47
int isalpha(Uchar c)
Definition: ncbictype.hpp:61
int isspace(Uchar c)
Definition: ncbictype.hpp:69
int isdigit(Uchar c)
Definition: ncbictype.hpp:64
Multi-threading – mutexes; rw-locks; semaphore.
Multi-threading – classes, functions, and features.
#define SET_MONTH(value)
Definition: ncbitime.cpp:178
static int s_DaysInMonth[12]
Definition: ncbitime.cpp:97
#define CHECK_RANGE_MONTH(value)
Definition: ncbitime.cpp:159
#define Daylight()
Definition: ncbitime.cpp:56
const unsigned int kUnitCount
Definition: ncbitime.cpp:2750
static const char * kDefaultFormatSpan
Definition: ncbitime.cpp:122
#define CHECK_RANGE2_NSEC(value, err)
Definition: ncbitime.cpp:173
#define COMPARE_TIMEOUT_TYPES(t1, t2)
Definition: ncbitime.cpp:3651
static const char * kWeekdayAbbr[7]
Definition: ncbitime.cpp:112
static const char * kDefaultFormatSpanIn
Definition: ncbitime.cpp:123
static const char * kDefaultFormatStopWatch
Definition: ncbitime.cpp:124
#define CHECK_RANGE_DAY(value)
Definition: ncbitime.cpp:160
static const char * kMonthAbbr[12]
Definition: ncbitime.cpp:102
static CTime s_Number2Date(unsigned num, const CTime &t)
Definition: ncbitime.cpp:215
#define SET_HOUR(value)
Definition: ncbitime.cpp:180
#define CHECK_RANGE2_YEAR(value, err)
Definition: ncbitime.cpp:166
static const TSeconds kTimeSpanUnitMultipliers[kUnitCount]
Definition: ncbitime.cpp:2787
#define CHECK_RANGE2_SEC(value, err)
Definition: ncbitime.cpp:172
EUnit
Definition: ncbitime.cpp:2753
@ eHour
Definition: ncbitime.cpp:2757
@ eYear
Definition: ncbitime.cpp:2754
@ eMinute
Definition: ncbitime.cpp:2758
@ eMicrosecond
Definition: ncbitime.cpp:2761
@ eMillisecond
Definition: ncbitime.cpp:2760
@ ePrecision
Definition: ncbitime.cpp:2766
@ eNanosecond
Definition: ncbitime.cpp:2762
@ eSecond
Definition: ncbitime.cpp:2759
@ eMonth
Definition: ncbitime.cpp:2755
@ eDay
Definition: ncbitime.cpp:2756
static const char * kMonthFull[12]
Definition: ncbitime.cpp:106
static void s_AddZeroPadInt(string &str, long value, size_t len, bool ignore_trailing_zeros=false)
Definition: ncbitime.cpp:281
static const char * kWeekdayFull[7]
Definition: ncbitime.cpp:115
#define SET_DAY(value)
Definition: ncbitime.cpp:179
#define CHECK_RANGE2_HOUR24(value, err)
Definition: ncbitime.cpp:169
static CStaticTls< CTimeFormat > s_TlsFormatTime
Definition: ncbitime.cpp:86
static string s_TimeDump(const CTime &time)
Definition: ncbitime.cpp:412
#define SET_MIN(value)
Definition: ncbitime.cpp:181
#define SET_YEAR(value)
Definition: ncbitime.cpp:177
static void s_AddZeroPadInt2(string &str, long value)
Definition: ncbitime.cpp:309
#define CHECK_RANGE2_MONTH(value, err)
Definition: ncbitime.cpp:167
#define CHECK_RANGE2_HOUR12(value, err)
Definition: ncbitime.cpp:170
#define TimeZone()
Definition: ncbitime.cpp:55
static CStaticTls< CTimeFormat > s_TlsFormatStopWatch
Definition: ncbitime.cpp:88
#define CHECK_RANGE_SEC(value)
Definition: ncbitime.cpp:163
bool s_IsDST(const CTime &ct)
Definition: ncbitime.cpp:1364
#define CHECK_RANGE_MIN(value)
Definition: ncbitime.cpp:162
static CSafeStatic< CFastLocalTime > s_FastLocalTime
Definition: ncbitime.cpp:91
static unsigned s_Date2Number(const CTime &date)
Definition: ncbitime.cpp:189
static const char * kFormatSymbolsSpan
Definition: ncbitime.cpp:130
static const SUnitName kUnitNames[kUnitCount]
Definition: ncbitime.cpp:2774
static void s_Offset(long *value, Int8 offset, long bound, int *major)
Definition: ncbitime.cpp:251
static const char * kFormatSymbolsTime
Definition: ncbitime.cpp:129
static CStaticTls< CTimeFormat > s_TlsFormatSpan
Definition: ncbitime.cpp:87
#define DSTBias()
Definition: ncbitime.cpp:70
#define X_INIT_ERROR(type, msg)
Definition: ncbitime.cpp:452
static void s_AddInt(string &str, long value)
Definition: ncbitime.cpp:265
#define SKIP_SPACES(s)
Definition: ncbitime.cpp:460
#define TZName()
Definition: ncbitime.cpp:57
#define CHECK_RANGE2_DAY(value, err)
Definition: ncbitime.cpp:168
DEFINE_STATIC_MUTEX(s_TimeMutex)
const char kFormatEscapeSymbol
Definition: ncbitime.cpp:133
time_t s_GetTimeT(const CTime &ct)
Definition: ncbitime.cpp:1291
#define CHECK_RANGE_NSEC(value)
Definition: ncbitime.cpp:164
#define CHECK_RANGE_YEAR(value)
Definition: ncbitime.cpp:158
static const char * kDefaultFormatTime
Definition: ncbitime.cpp:121
#define CHECK_RANGE2_MIN(value, err)
Definition: ncbitime.cpp:171
static string s_SpecialValueName(CTimeout::EType type)
Definition: ncbitime.cpp:3462
#define CHECK_RANGE_HOUR(value)
Definition: ncbitime.cpp:161
#define SET_SEC(value)
Definition: ncbitime.cpp:182
Defines: CTimeFormat - storage class for time format.
T bound(T x_, T xlo_, T xhi_)
static Format format
Definition: njn_ioutil.cpp:53
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
bool str(const char *&s)
Definition: ncbitime.cpp:473
bool fmt(const char *&f)
Definition: ncbitime.cpp:469
void activate()
Definition: ncbitime.cpp:491
void str(string &s)
Definition: ncbitime.cpp:494
bool active() const
Definition: ncbitime.cpp:500
const char * name_short
Definition: ncbitime.cpp:2772
const char * name_full
Definition: ncbitime.cpp:2771
Database format for time where day and time is signed 32 bit.
Definition: ncbitime.hpp:114
Database format for time where day and time is unsigned 16 bit.
Definition: ncbitime.hpp:108
Definition: type.c:6
#define _TROUBLE
#define _ASSERT
else result
Definition: token2.c:20
#define const
Definition: zconf.h:232
Modified on Sun Jul 14 05:00:40 2024 by modify_doxy.py rev. 669887