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

Go to the SVN repository for this file.

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