ncbitime.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:44k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbitime.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 19:09:28  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.49
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbitime.cpp,v 1000.4 2004/06/01 19:09:28 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Anton Butanayev, Denis Vakatov, Vladimir Ivanov
  35.  *
  36.  *
  37.  */
  38. #include <ncbi_pch.hpp>
  39. #include <corelib/ncbitime.hpp>
  40. #include <corelib/ncbimtx.hpp>
  41. #include <corelib/ncbithr.hpp>
  42. #include <corelib/ncbi_safe_static.hpp>
  43. #include <stdlib.h>
  44. #if defined(NCBI_OS_MSWIN)
  45. #  include <sys/timeb.h>
  46. #  include <windows.h>
  47. #elif defined(NCBI_OS_UNIX)
  48. #  include <sys/time.h>
  49. #endif
  50. #if defined(NCBI_OS_MAC) || defined(NCBI_COMPILER_MW_MSL)
  51. #  include <OSUtils.h>
  52. typedef struct MyTZDLS {
  53.     long timezone;
  54.     bool daylight;
  55. } MyTZDLS;
  56. static MyTZDLS MyReadLocation()
  57. {
  58.     MachineLocation loc;
  59.     ReadLocation(&loc);
  60.     long tz = loc.u.gmtDelta & 0x00ffffff;
  61.     // Propogate sign bit from bit 23 to bit 31 if West of UTC.
  62.     // (Sign-extend the GMT correction)
  63.     if ((tz & 0x00800000) != 0) {
  64.         tz |= 0xFF000000;
  65.     }
  66.     bool dls = (loc.u.dlsDelta != 0);
  67.     MyTZDLS tzdls = {tz, dls};
  68.     return tzdls;
  69. }
  70. static MyTZDLS sTZDLS = MyReadLocation();
  71. #  define TimeZone()  sTZDLS.timezone
  72. #  define Daylight()  sTZDLS.daylight
  73. #elif defined(__CYGWIN__)
  74. #  define TimeZone() _timezone
  75. #  define Daylight() _daylight
  76. #else
  77. #  define TimeZone()  timezone
  78. #  define Daylight()  daylight
  79. #endif
  80. #if defined(NCBI_OS_DARWIN)  ||  defined(NCBI_OS_BSD)
  81. #  define TIMEZONE_IS_UNDEFINED  1
  82. #endif
  83. BEGIN_NCBI_SCOPE
  84. // Protective mutex
  85. DEFINE_STATIC_FAST_MUTEX(s_TimeMutex);
  86. DEFINE_STATIC_FAST_MUTEX(s_TimeAdjustMutex);
  87. // Store global time format in TLS
  88. static CSafeStaticRef< CTls<string> > s_TlsFormat;
  89. static void s_TlsFormatCleanup(string* fmt, void* /* data */)
  90. {
  91.     delete fmt;
  92. }
  93. //============================================================================
  94. //
  95. //  CTime
  96. //
  97. //============================================================================
  98. // Number of days per month
  99. static int s_DaysInMonth[12] = {
  100.     31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  101. };
  102. // Month names
  103. static const char* kMonthAbbr[12] = {
  104.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  105.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  106. };
  107. static const char* kMonthFull[12] = {
  108.     "January", "February", "March", "April", "May", "June",
  109.     "July", "August", "September", "October", "November", "December"
  110. };
  111. // Day of week names
  112. static const char* kWeekdayAbbr[7] = {
  113.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  114. };
  115. static const char* kWeekdayFull [7] = {
  116.     "Sunday", "Monday", "Tuesday", "Wednesday",
  117.     "Thursday", "Friday", "Saturday"
  118. };
  119.  
  120. // Default value for time format
  121. static const char* kDefaultFormat = "M/D/Y h:m:s";
  122. // Set of the checked format symbols (w,W not included)
  123. static const char* kFormatSymbols = "yYMbBDhmsSzZwW";
  124. // Error messages
  125. static const string kMsgInvalidTime = "CTime:  invalid";
  126. // Get number of days in "date"
  127. static unsigned s_Date2Number(const CTime& date)
  128. {
  129.     unsigned d = date.Day();
  130.     unsigned m = date.Month();
  131.     unsigned y = date.Year();
  132.     unsigned c, ya;
  133.     if (m > 2) {
  134.         m -= 3;
  135.     } else {
  136.         m += 9;
  137.         y--;
  138.     }
  139.     c  = y / 100;
  140.     ya = y - 100 * c;
  141.     
  142.     return ((146097 * c) >> 2) + ((1461 * ya) >> 2) +
  143.             (153 * m + 2) / 5 +  d + 1721119;
  144. }
  145. // Conversion number of days in date format
  146. // timezone value compute on base <t>
  147. static CTime s_Number2Date(unsigned num, const CTime& t)
  148. {
  149.     unsigned d;
  150.     unsigned j = num - 1721119;
  151.     unsigned year;
  152.     unsigned day;
  153.     unsigned month;
  154.     year = (((j<<2) - 1) / 146097);
  155.     j = (j<<2) - 1 - 146097 * year;
  156.     d = (j>>2);
  157.     j = ((d<<2) + 3) / 1461;
  158.     d = (d<<2) + 3 - 1461 * j;
  159.     d = (d + 4) >> 2;
  160.     month = (5*d - 3) / 153;
  161.     d = 5*d - 3 - 153 * month;
  162.     day = (d + 5) / 5;
  163.     year = 100 * year + j;
  164.     if (month < 10) {
  165.         month += 3;
  166.     } else {
  167.         month -= 9;
  168.         year++;
  169.     }
  170.     // Construct new CTime object
  171.     return 
  172.         CTime (year, month, day, t.Hour(), t.Minute(), t.Second(), 
  173.               t.NanoSecond(), t.GetTimeZoneFormat(), t.GetTimeZonePrecision());
  174. }
  175. // Calc <value> + <offset> on module <bound>. 
  176. // Normalized value return in <value> and other part, which above 
  177. // than <bound>, write at <major>.
  178. static void s_Offset(long *value, long offset, long bound, int *major)
  179. {
  180.     *value += offset;
  181.     *major += (int) (*value / bound);
  182.     *value %= bound;
  183.     if (*value < 0) {
  184.         *major -= 1;
  185.         *value += bound;
  186.     }
  187. }
  188. CTime::CTime(const CTime& t)
  189. {
  190.     *this = t;
  191. }
  192. CTime::CTime(int year, int yearDayNumber, ETimeZone tz, ETimeZonePrecision tzp)
  193. {
  194.     Clear();
  195.     m_Tz = tz;
  196.     m_TzPrecision = tzp;
  197.     CTime t = CTime(year, 1, 1);
  198.     t += yearDayNumber - 1;
  199.     m_Year  = t.Year();
  200.     m_Month = t.Month();
  201.     m_Day   = t.Day();
  202. }
  203. void CTime::x_VerifyFormat(const string& fmt)
  204. {
  205.     // Check for duplicated format symbols...
  206.     const int kSize = 256;
  207.     int count[kSize];
  208.     for (int i = 0;  i < kSize;  i++) {
  209.         count[i] = 0;
  210.     }
  211.     ITERATE(string, it, fmt) {
  212.         if (strchr(kFormatSymbols, *it) != 0  &&
  213.             ++count[(unsigned int) *it] > 1) {
  214.             NCBI_THROW(CTimeException, eFormat, "CTime's format is incorrect");
  215.         }
  216.     }
  217. }
  218. void CTime::x_Init(const string& str, const string& fmt)
  219. {
  220.     Clear();
  221.     if ( str.empty() ) {
  222.         return;
  223.     }
  224.     
  225.     const char* fff;
  226.     const char* sss = str.c_str();
  227. #if ! defined(TIMEZONE_IS_UNDEFINED)
  228.     bool  adjust_needed = false;
  229.     long  adjust_tz     = 0;
  230. #endif
  231.     int weekday = -1;
  232.     for (fff = fmt.c_str();  *fff != '';  fff++) {
  233.         // Non-format symbols
  234.         if (strchr(kFormatSymbols, *fff) == 0) {
  235.             if (*fff == *sss) {
  236.                 sss++;
  237.                 continue;  // skip matching non-format symbols
  238.             }
  239.             break;  // error: non-matching non-format symbols
  240.         }
  241.         // Month
  242.         if (*fff == 'b'  ||  *fff == 'B') {
  243.             const char** name;
  244.             if (*fff == 'b') {
  245.                 name = kMonthAbbr;
  246.             } else {
  247.                 name = kMonthFull;
  248.             }
  249.             for (unsigned char i = 0;  i < 12;  i++) {
  250.                 size_t namelen = strlen(*name);
  251.                 if (strncmp(sss, *name, namelen) == 0) {
  252.                     sss += namelen;
  253.                     m_Month = i + 1;
  254.                     break;
  255.                 }
  256.                 name++;
  257.             }
  258.             continue;
  259.         }
  260.         // Day of week
  261.         if (*fff == 'w'  ||  *fff == 'W') {
  262.             const char** day = (*fff == 'w') ? kWeekdayAbbr : kWeekdayFull;
  263.             for (unsigned char i = 0;  i < 7;  i++) {
  264.                 size_t len = strlen(*day);
  265.                 if (strncmp(sss, *day, len) == 0) {
  266.                     sss += len;
  267.                     weekday = i;
  268.                     break;
  269.                 }
  270.                 day++;
  271.             }
  272.             continue;
  273.         }
  274.         // Timezone (GMT time) 
  275.         if (*fff == 'Z') {
  276.             if (strncmp(sss, "GMT", 3) == 0) {
  277.                 m_Tz = eGmt;
  278.                 sss += 3;
  279.             } else {
  280.                 m_Tz = eLocal;
  281.                 if (fff[1] == ' ') fff++;
  282.             }
  283.             continue;
  284.         }
  285.         // Timezone (local time in format GMT+HHMM)
  286.         if (*fff == 'z') {
  287. #if defined(TIMEZONE_IS_UNDEFINED)
  288.             ERR_POST("Format symbol 'z' is unsupported on this platform");
  289. #else
  290.             m_Tz = eLocal;
  291.             if (strncmp(sss, "GMT", 3) == 0) {
  292.                 sss += 3;
  293.             }
  294.             while ( isspace(*sss) ) {
  295.                 sss++; 
  296.             }
  297.             int sign = (*sss == '+') ? 1 : ((*sss == '-') ? -1 : 0);
  298.             if ( sign ) {
  299.                 sss++;
  300.             } else {
  301.                 sign = 1;
  302.             }
  303.             long x_hour = 0;
  304.             long x_min  = 0;
  305.             char value_str[3];
  306.             char* s = value_str;
  307.             for (size_t len = 2; len != 0  &&  *sss != ''  &&  isdigit(*sss);  len--) {
  308.                 *s++ = *sss++; 
  309.             }
  310.             *s = '';
  311.             try {
  312.                 x_hour = NStr::StringToLong(value_str);
  313.             }
  314.             catch (CStringException) {
  315.                 x_hour = 0;
  316.             }
  317.             try {
  318.                 if ( *sss != '' ) {
  319.                     s = value_str;
  320.                     for (size_t len = 2; len != 0  &&  *sss != ''  &&  isdigit(*sss);  len--) {
  321.                         *s++ = *sss++; 
  322.                     }
  323.                     *s = '';
  324.                     x_min = NStr::StringToLong(value_str, 10, NStr::eCheck_Skip);
  325.                 }
  326.             }
  327.             catch (CStringException) {
  328.                 x_min = 0;
  329.             }
  330.             adjust_needed = true;
  331.             adjust_tz = sign * (x_hour * 60 + x_min) * 60;
  332. #endif
  333.             continue;
  334.         }
  335.         // Other format symbols -- read the next data ingredient
  336.         char value_str[10];
  337.         char* s = value_str;
  338.         for (size_t len = (*fff == 'Y') ? 4 : ((*fff == 'S') ? 9 : 2);
  339.              len != 0  &&  *sss != ''  &&  isdigit(*sss);  len--) {
  340.             *s++ = *sss++; 
  341.         }
  342.         *s = '';
  343.         long value = NStr::StringToLong(value_str);
  344.         switch ( *fff ) {
  345.         case 'Y':
  346.             m_Year = (int) value;
  347.             break;
  348.         case 'y':
  349.             if (value >= 0  &&  value < 50) {
  350.                 value += 2000;
  351.             } else if (value >= 50  &&  value < 100) {
  352.                 value += 1900;
  353.             }
  354.             m_Year = (int) value;
  355.             break;
  356.         case 'M':
  357.             m_Month = (unsigned char) value;
  358.             break;
  359.         case 'D':
  360.             m_Day = (unsigned char) value;
  361.             break;
  362.         case 'h':
  363.             m_Hour = (unsigned char) value;
  364.             break;
  365.         case 'm':
  366.             m_Minute = (unsigned char) value;
  367.             break;
  368.         case 's':
  369.             m_Second = (unsigned char) value;
  370.             break;
  371.         case 'S':
  372.             m_NanoSecond = value;
  373.             break;
  374.         default:
  375.             NCBI_THROW(CTimeException, eFormat, "CTime:  format is incorrect");
  376.         }
  377.     }
  378.     // Check on errors
  379.     if (weekday != -1  &&  weekday != DayOfWeek()) {
  380.         NCBI_THROW(CTimeException, eInvalid, "CTime:  invalid day of week");
  381.     }
  382.     if (*fff != ''  ||  *sss != '') {
  383.         NCBI_THROW(CTimeException, eFormat, "CTime:  format is incorrect");
  384.     }
  385.     if ( !IsValid() ) {
  386.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  387.     }
  388. #if ! defined(TIMEZONE_IS_UNDEFINED)
  389.     // Adjust time for current timezone
  390.     if ( adjust_needed  &&  adjust_tz != -TimeZone() ) {
  391.         AddSecond(-TimeZone() - adjust_tz);
  392.     }
  393. #endif
  394. }
  395. CTime::CTime(int year, int month, int day, int hour, 
  396.              int minute, int second, long nanosecond,
  397.              ETimeZone tz, ETimeZonePrecision tzp)
  398. {
  399.     m_Year           = year;
  400.     m_Month          = month;
  401.     m_Day            = day;
  402.     m_Hour           = hour;
  403.     m_Minute         = minute;
  404.     m_Second         = second;
  405.     m_NanoSecond     = nanosecond;
  406.     m_Tz             = tz;
  407.     m_TzPrecision    = tzp;
  408.     m_AdjustTimeDiff = 0;
  409.     if ( !IsValid() ) {
  410.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  411.     }
  412. }
  413. CTime::CTime(EInitMode mode, ETimeZone tz, ETimeZonePrecision tzp)
  414. {
  415.     m_Tz = tz;
  416.     m_TzPrecision = tzp;
  417.     if (mode == eCurrent) {
  418.         SetCurrent();
  419.     } else {
  420.         Clear();
  421.     }
  422. }
  423. CTime::CTime(time_t t, ETimeZonePrecision tzp)
  424. {
  425.     m_Tz = eGmt;
  426.     m_TzPrecision = tzp;
  427.     SetTimeT(t);
  428. }
  429. CTime::CTime(const string& str, const string& fmt, 
  430.              ETimeZone tz, ETimeZonePrecision tzp)
  431. {
  432.     m_Tz = tz;
  433.     m_TzPrecision = tzp;
  434.     if (fmt.empty()) {
  435.         x_Init(str, GetFormat());
  436.     } else {
  437.         x_VerifyFormat(fmt);
  438.         x_Init(str, fmt);
  439.     }
  440. }
  441. void CTime::SetYear(int year)
  442. {
  443.     m_Year = year;
  444.     int n_days = DaysInMonth();
  445.     if ( m_Day > n_days ) {
  446.         m_Day = n_days;
  447.     }
  448.     if ( !IsValid() ) {
  449.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  450.     }
  451. }
  452. void CTime::SetMonth(int month)
  453. {
  454.     m_Month = month;
  455.     int n_days = DaysInMonth();
  456.     if ( m_Day > n_days ) {
  457.         m_Day = n_days;
  458.     }
  459.     if ( !IsValid() ) {
  460.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  461.     }
  462. }
  463. void CTime::SetDay(int day)
  464. {
  465.     m_Day = day;
  466.     int n_days = DaysInMonth();
  467.     if ( m_Day > n_days ) {
  468.         m_Day = n_days;
  469.     }
  470.     if ( !IsValid() ) {
  471.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  472.     }
  473. }
  474. void CTime::SetHour(int hour)
  475. {
  476.     m_Hour = hour;
  477.     if ( !IsValid() ) {
  478.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  479.     }
  480. }
  481. void CTime::SetMinute(int minute)
  482. {
  483.     m_Minute = minute;
  484.     if ( !IsValid() ) {
  485.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  486.     }
  487. }
  488. void CTime::SetSecond(int second)
  489. {
  490.     m_Second = second;
  491.     if ( !IsValid() ) {
  492.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  493.     }
  494. }
  495. void CTime::SetNanoSecond(long nanosecond)
  496. {
  497.     m_NanoSecond = nanosecond;
  498.     if ( !IsValid() ) {
  499.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  500.     }
  501. }
  502. int CTime::YearDayNumber(void) const
  503. {
  504.     unsigned first = s_Date2Number(CTime(Year(), 1, 1));
  505.     unsigned self  = s_Date2Number(*this);
  506.     _ASSERT(first <= self  &&  self < first + (IsLeap() ? 366 : 365));
  507.     return (int) (self - first + 1);
  508. }
  509. int CTime::YearWeekNumber(EDayOfWeek first_day_of_week) const
  510. {
  511.     if (first_day_of_week > eSaturday) {
  512.         NCBI_THROW(CTimeException, eArgument,
  513.                    "CTime:  first day of week parameter is incorrect");
  514.     }
  515.     int week_num = 0;
  516.     int wday = DayOfWeek();
  517.     // Adjust day of week (from default Sunday)
  518.     wday -= first_day_of_week;
  519.     if (wday < 0) {
  520.         wday += 7;
  521.     }
  522.     // Calculate week number
  523.     int yday = YearDayNumber() - 1;  // YearDayNumber() returns 1..366
  524.     if (yday >= wday) {
  525.         week_num = yday / 7;
  526.         if ( (yday % 7) >= wday ) {
  527.             week_num++;
  528.         }
  529.     }
  530.     // Adjust range from [0..53] to [1..54]
  531.     return week_num + 1;
  532. }
  533. int CTime::MonthWeekNumber(EDayOfWeek first_day_of_week) const
  534. {
  535.     CTime first_of_month(Year(), Month(), 1);
  536.     int week_num_first   = first_of_month.YearWeekNumber(first_day_of_week);
  537.     int week_num_current = YearWeekNumber(first_day_of_week);
  538.     return week_num_current - week_num_first + 1;
  539. }
  540. int CTime::DayOfWeek(void) const 
  541. {
  542.     int y = Year();
  543.     int m = Month();
  544.     y -= int(m < 3);
  545.     return (y + y/4 - y/100 + y/400 + "-bed=pen+mad."[m] + Day()) % 7;
  546. }
  547. int CTime::DaysInMonth(void) const 
  548. {
  549.     int n_days = s_DaysInMonth[Month()-1];
  550.     if (n_days == 0) {
  551.         n_days = IsLeap() ? 29 : 28;
  552.     }
  553.     return n_days;
  554. }
  555. void CTime::SetFormat(const string& fmt)
  556. {
  557.     x_VerifyFormat(fmt);
  558.     // Here we do not need to delete a previous value stored in the TLS.
  559.     // The TLS will destroy it using s_TlsFormatCleanup().
  560.     string* format = new string(fmt);
  561.     s_TlsFormat->SetValue(format, s_TlsFormatCleanup);
  562. }
  563. string CTime::GetFormat(void)
  564. {
  565.     string* format = s_TlsFormat->GetValue();
  566.     if ( !format ) {
  567.         return kDefaultFormat;
  568.     }
  569.     return *format;
  570. }
  571. int CTime::MonthNameToNum(const string& month)
  572. {
  573.     const char** name = month.length() == 3 ? kMonthAbbr : kMonthFull; 
  574.     for (int i = 0; i < 12; i++) {
  575.         if (month == name[i]) {
  576.             return i+1;
  577.         }
  578.     }
  579.     // Always throw exceptions here. 
  580.     // Next if statements avoid compilation warnings.
  581.     if ( name ) {
  582.         NCBI_THROW(CTimeException, eInvalid, "CTime:  invalid month name");
  583.     }
  584.     return -1;
  585. }
  586. string CTime::MonthNumToName(int month, ENameFormat format)
  587. {
  588.     if (month < 1  ||  month > 12) {
  589.         NCBI_THROW(CTimeException, eInvalid, "CTime:  invalid month number");
  590.     }
  591.     month--;
  592.     return format == eFull ? kMonthFull[month] : kMonthAbbr[month];
  593. }
  594. int CTime::DayOfWeekNameToNum(const string& day)
  595. {
  596.     const char** name = day.length() == 3 ? kWeekdayAbbr : kWeekdayFull; 
  597.     for (int i = 0; i <= 6; i++) {
  598.         if (day == name[i]) {
  599.             return i;
  600.         }
  601.     }
  602.     // Always throw exceptions here. 
  603.     // Next if statements avoid compilation warnings.
  604.     if ( name ) {
  605.         NCBI_THROW(CTimeException,eInvalid,"CTime:  invalid day of week name");
  606.     }
  607.     return -1;
  608. }
  609. string CTime::DayOfWeekNumToName(int day, ENameFormat format)
  610. {
  611.     if (day < 0  ||  day > 6) {
  612.         return kEmptyStr;
  613.     }
  614.     return format == eFull ? kWeekdayFull[day] : kWeekdayAbbr[day];
  615. }
  616. static void s_AddZeroPadInt(string& str, long value, SIZE_TYPE len = 2)
  617. {
  618.     string s_value = NStr::IntToString(value);
  619.     if (s_value.length() < len) {
  620.         str.insert(str.end(), len - s_value.length(), '0');
  621.     }
  622.     str += s_value;
  623. }
  624. string CTime::AsString(const string& fmt, long out_tz) const
  625. {
  626.     if ( fmt.empty() ) {
  627.         return AsString(GetFormat());
  628.     }
  629.     x_VerifyFormat(fmt);
  630.     if ( !IsValid() ) {
  631.         NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime);
  632.     }
  633.     if ( IsEmpty() ) {
  634.         return kEmptyStr;
  635.     }
  636.     const CTime* t = this;
  637.     CTime* t_out = 0;
  638.     // Adjust time for output timezone
  639.     if (out_tz != eCurrentTimeZone) {
  640. #if defined(TIMEZONE_IS_UNDEFINED)
  641.     ERR_POST("Output timezone is unsupported on this platform");
  642. #else
  643.         if (out_tz != TimeZone()) {
  644.             t_out = new CTime(*this);
  645.             t_out->AddSecond(TimeZone() - out_tz);
  646.             t = t_out;
  647.         }
  648. #endif
  649.     }
  650.     
  651.     string str;
  652.     ITERATE(string, it, fmt) {
  653.         switch ( *it ) {
  654.         case 'y': s_AddZeroPadInt(str, t->Year() % 100);    break;
  655.         case 'Y': s_AddZeroPadInt(str, t->Year(), 4);       break;
  656.         case 'M': s_AddZeroPadInt(str, t->Month());         break;
  657.         case 'b': str += kMonthAbbr[t->Month()-1];          break;
  658.         case 'B': str += kMonthFull[t->Month()-1];          break;
  659.         case 'D': s_AddZeroPadInt(str, t->Day());           break;
  660.         case 'h': s_AddZeroPadInt(str, t->Hour());          break;
  661.         case 'm': s_AddZeroPadInt(str, t->Minute());        break;
  662.         case 's': s_AddZeroPadInt(str, t->Second());        break;
  663.         case 'S': s_AddZeroPadInt(str, t->NanoSecond(), 9); break;
  664.         case 'z': {
  665. #if defined(TIMEZONE_IS_UNDEFINED)
  666.               ERR_POST("Format symbol 'z' is unsupported on this platform");
  667. #else
  668.                       str += "GMT";
  669.                       if (IsGmtTime()) {
  670.                           break;
  671.                       }
  672.                       long tz = (out_tz == eCurrentTimeZone) ? TimeZone() : 
  673.                                                                out_tz;
  674.                       str += (tz > 0) ? '-' : '+';
  675.                       if (tz < 0) tz = -tz;
  676.                       int tzh = tz / 3600;
  677.                       s_AddZeroPadInt(str, tzh);
  678.                       s_AddZeroPadInt(str, (int)(tz - tzh * 3600) / 60);
  679. #endif
  680.                       break;
  681.                   }
  682.         case 'Z': if (IsGmtTime()) str += "GMT";            break;
  683.         case 'w': str += kWeekdayAbbr[t->DayOfWeek()];      break;
  684.         case 'W': str += kWeekdayFull[t->DayOfWeek()];      break;
  685.         default : str += *it;                               break;
  686.         }
  687.     }
  688.     // Free used memory
  689.     if ( t_out ) {
  690.         delete t_out;
  691.     }
  692.     return str;
  693. }
  694. #if defined (NCBI_OS_MAC)
  695. // Mac OS 9 does not correctly support daylight savings flag.
  696. time_t CTime::GetTimeT(void) const
  697. {
  698.     struct tm t;
  699.     t.tm_sec   = Second() + (int) (IsGmtTime() ? +TimeZone() : 0);
  700.     t.tm_min   = Minute();
  701.     t.tm_hour  = Hour();
  702.     t.tm_mday  = Day();
  703.     t.tm_mon   = Month()-1;
  704.     t.tm_year  = Year()-1900;
  705.     t.tm_isdst = -1;
  706.     return mktime(&t);
  707. }
  708. #else
  709. time_t CTime::GetTimeT(void) const
  710. {
  711.     // MT-Safe protect
  712.     CFastMutexGuard LOCK(s_TimeMutex);
  713.     struct tm t;
  714.     // Convert time to time_t value at base local time
  715. #if defined(HAVE_TIMEGM)  ||  (defined(NCBI_OS_DARWIN)  &&  ! defined(NCBI_COMPILER_MW_MSL))
  716.     t.tm_sec   = Second();
  717. #else
  718.     t.tm_sec   = Second() + (int) (IsGmtTime() ? -TimeZone() : 0);
  719. #endif
  720.     t.tm_min   = Minute();
  721.     t.tm_hour  = Hour();
  722.     t.tm_mday  = Day();
  723.     t.tm_mon   = Month()-1;
  724.     t.tm_year  = Year()-1900;
  725.     t.tm_isdst = -1;
  726. #if defined(NCBI_OS_DARWIN) && ! defined(NCBI_COMPILER_MW_MSL)
  727.     time_t tt = mktime(&t);
  728.     return IsGmtTime() ? tt+t.tm_gmtoff : tt;
  729. #elif defined(HAVE_TIMEGM)
  730.     return IsGmtTime() ? timegm(&t) : mktime(&t);
  731. #else
  732.     struct tm *ttemp;
  733.     time_t timer;
  734.     timer = mktime(&t);
  735.     // Correct timezone for GMT time
  736.     if ( IsGmtTime() ) {
  737.        // Call mktime() second time for GMT time !!!  
  738.        // 1st - to get correct value of TimeZone().
  739.        // 2nd - to get value "timer". 
  740.         t.tm_sec   = Second() - (int)TimeZone();
  741.         t.tm_min   = Minute();
  742.         t.tm_hour  = Hour();
  743.         t.tm_mday  = Day();
  744.         t.tm_mon   = Month()-1;
  745.         t.tm_year  = Year()-1900;
  746.         t.tm_isdst = -1;
  747.         timer = mktime(&t);
  748. #  if defined(HAVE_LOCALTIME_R)
  749.         struct tm temp;
  750.         localtime_r(&timer, &temp);
  751.         ttemp = &temp;
  752. #  else
  753.         ttemp = localtime(&timer);
  754. #  endif
  755.         if (ttemp == NULL)
  756.             return -1;
  757.         if (ttemp->tm_isdst > 0  &&  Daylight())
  758.             timer += 3600;
  759.     }
  760.     return timer;
  761. #endif
  762. }
  763. #endif
  764. TDBTimeU CTime::GetTimeDBU(void) const
  765. {
  766.     TDBTimeU dbt;
  767.     CTime t  = GetLocalTime();
  768.     unsigned first = s_Date2Number(CTime(1900, 1, 1));
  769.     unsigned curr  = s_Date2Number(t);
  770.     dbt.days = (Uint2)(curr - first);
  771.     dbt.time = (Uint2)(t.Hour() * 60 + t.Minute());
  772.     return dbt;
  773. }
  774. TDBTimeI CTime::GetTimeDBI(void) const
  775. {
  776.     TDBTimeI dbt;
  777.     CTime t  = GetLocalTime();
  778.     unsigned first = s_Date2Number(CTime(1900, 1, 1));
  779.     unsigned curr  = s_Date2Number(t);
  780.     dbt.days = (Int4)(curr - first);
  781.     dbt.time = (Int4)((t.Hour() * 3600 + t.Minute() * 60 + t.Second()) * 300) +
  782.         (Int4)((double)t.NanoSecond() * 300 / kNanoSecondsPerSecond);
  783.     return dbt;
  784. }
  785. CTime& CTime::SetTimeDBU(const TDBTimeU& t)
  786. {
  787.     // Local time - 1/1/1900 00:00:00.0
  788.     CTime time(1900, 1, 1, 0, 0, 0, 0, eLocal);
  789.     time.SetTimeZonePrecision(GetTimeZonePrecision());
  790.     time.AddDay(t.days);
  791.     time.AddMinute(t.time);
  792.     time.ToTime(GetTimeZoneFormat());
  793.     *this = time;
  794.     return *this;
  795. }
  796. CTime& CTime::SetTimeDBI(const TDBTimeI& t)
  797. {
  798.     // Local time - 1/1/1900 00:00:00.0
  799.     CTime time(1900, 1, 1, 0, 0, 0, 0, eLocal);
  800.     time.SetTimeZonePrecision(GetTimeZonePrecision());
  801.     time.AddDay(t.days);
  802.     time.AddSecond(t.time / 300);
  803.     time.AddNanoSecond((long)((t.time % 300) * 
  804.                               (double)kNanoSecondsPerSecond / 300));
  805.     time.ToTime(GetTimeZoneFormat());
  806.     *this = time;
  807.     return *this;
  808. }
  809. CTime& CTime::x_SetTime(const time_t* value)
  810. {
  811.     long ns = 0;
  812.     time_t timer;
  813.     // MT-Safe protect
  814.     CFastMutexGuard LOCK(s_TimeMutex);
  815.     // Get time with nanoseconds
  816. #if defined(NCBI_OS_MSWIN)
  817.     if ( value ) {
  818.         timer = *value;
  819.     } else {
  820.         struct _timeb timebuffer;
  821.         _ftime(&timebuffer);
  822.         timer = timebuffer.time;
  823.         ns = (long) timebuffer.millitm * 
  824.             (long) (kNanoSecondsPerSecond / kMilliSecondsPerSecond);
  825.     }
  826. #elif defined(NCBI_OS_UNIX)
  827.     if ( value ) {
  828.         timer = *value;
  829.     } else {
  830.         struct timeval tp;
  831.         if (gettimeofday(&tp,0) == -1) {
  832.             timer = 0;
  833.             ns = 0;
  834.         } else { 
  835.             timer = tp.tv_sec;
  836.             ns = long((double)tp.tv_usec * 
  837.                       (double)kNanoSecondsPerSecond /
  838.                       (double)kMicroSecondsPerSecond);
  839.         }
  840.     }
  841. #else // NCBI_OS_MAC
  842.     timer = value ? *value : time(0);
  843.     ns = 0;
  844. #endif
  845.     // Bind values to internal variables
  846.     struct tm *t;
  847. #ifdef HAVE_LOCALTIME_R
  848.     struct tm temp;
  849.     if (GetTimeZoneFormat() == eLocal) {
  850.         localtime_r(&timer, &temp);
  851.     } else {
  852.         gmtime_r(&timer, &temp);
  853.     }
  854.     t = &temp;
  855. #else
  856.     t = ( GetTimeZoneFormat() == eLocal ) ? localtime(&timer) : gmtime(&timer);
  857. #endif
  858.     m_AdjustTimeDiff = 0;
  859.     m_Year           = t->tm_year + 1900;
  860.     m_Month          = t->tm_mon + 1;
  861.     m_Day            = t->tm_mday;
  862.     m_Hour           = t->tm_hour;
  863.     m_Minute         = t->tm_min;
  864.     m_Second         = t->tm_sec;
  865.     m_NanoSecond     = ns;
  866.     return *this;
  867. }
  868. CTime& CTime::AddMonth(int months, EDaylight adl)
  869. {
  870.     if ( !months ) {
  871.         return *this;
  872.     }
  873.     CTime *pt = 0;
  874.     bool aflag = false; 
  875.     if ((adl == eAdjustDaylight)  &&  x_NeedAdjustTime()) {
  876.         pt = new CTime(*this);
  877.         if ( !pt ) {
  878.             NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
  879.         }
  880.         aflag = true;
  881.     }
  882.     long newMonth = Month() - 1;
  883.     int newYear = Year();
  884.     s_Offset(&newMonth, months, 12, &newYear);
  885.     m_Year = newYear;
  886.     m_Month = (int) newMonth + 1;
  887.     x_AdjustDay();
  888.     if ( aflag ) {
  889.         x_AdjustTime(*pt);
  890.         delete pt;
  891.     }
  892.     return *this;
  893. }
  894. CTime& CTime::AddDay(int days, EDaylight adl)
  895. {
  896.     if ( !days ) {
  897.         return *this;
  898.     }
  899.     CTime *pt = 0;
  900.     bool aflag = false; 
  901.     if ((adl == eAdjustDaylight)  &&  x_NeedAdjustTime()) {
  902.         pt = new CTime(*this);
  903.         if ( !pt ) {
  904.             NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
  905.         }
  906.         aflag = true;
  907.     }
  908.     // Make nesessary object
  909.     *this = s_Number2Date(s_Date2Number(*this) + days, *this);
  910.     // If need, make adjustment time specially
  911.     if ( aflag ) {
  912.         x_AdjustTime(*pt);
  913.         delete pt;
  914.     }
  915.     return *this;
  916. }
  917. // Parameter <shift_time> access or denied use time shift in process 
  918. // adjust hours.
  919. CTime& CTime::x_AddHour(int hours, EDaylight adl, bool shift_time)
  920. {
  921.     if ( !hours ) {
  922.         return *this;
  923.     }
  924.     CTime *pt = 0;
  925.     bool aflag = false; 
  926.     if ((adl == eAdjustDaylight)  &&  x_NeedAdjustTime()) {
  927.         pt = new CTime(*this);
  928.         if ( !pt ) {
  929.             NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
  930.         }
  931.         aflag = true;
  932.     }
  933.     int dayOffset = 0;
  934.     long newHour = Hour();
  935.     s_Offset(&newHour, hours, 24, &dayOffset);
  936.     m_Hour = (int) newHour;
  937.     AddDay(dayOffset, eIgnoreDaylight);
  938.     if ( aflag ) {
  939.         x_AdjustTime(*pt, shift_time);
  940.         delete pt;
  941.     }
  942.     return *this;
  943. }
  944. CTime& CTime::AddMinute(int minutes, EDaylight adl)
  945. {
  946.     if ( !minutes ) {
  947.         return *this;
  948.     }
  949.     CTime *pt = 0;
  950.     bool aflag = false; 
  951.     if ((adl == eAdjustDaylight) && x_NeedAdjustTime()) {
  952.         pt = new CTime(*this);
  953.         if ( !pt ) {
  954.             NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
  955.         }
  956.         aflag = true;
  957.     }
  958.     int hourOffset = 0;
  959.     long newMinute = Minute();
  960.     s_Offset(&newMinute, minutes, 60, &hourOffset);
  961.     m_Minute = (int) newMinute;
  962.     AddHour(hourOffset, eIgnoreDaylight);
  963.     if ( aflag ) {
  964.         x_AdjustTime(*pt);
  965.         delete pt;
  966.     }
  967.     return *this;
  968. }
  969. CTime& CTime::AddSecond(int seconds)
  970. {
  971.     if ( !seconds ) {
  972.         return *this;
  973.     }
  974.     int minuteOffset = 0;
  975.     long newSecond = Second();
  976.     s_Offset(&newSecond, seconds, 60, &minuteOffset);
  977.     m_Second = (int) newSecond;
  978.     return AddMinute(minuteOffset);
  979. }
  980. CTime& CTime::AddNanoSecond(long ns)
  981. {
  982.     if ( !ns ) {
  983.         return *this;
  984.     }
  985.     int secondOffset = 0;
  986.     long newNanoSecond = NanoSecond();
  987.     s_Offset(&newNanoSecond, ns, kNanoSecondsPerSecond, &secondOffset);
  988.     m_NanoSecond = newNanoSecond;
  989.     return AddSecond(secondOffset);
  990. }
  991. bool CTime::IsValid(void) const
  992. {
  993.     if ( IsEmpty() ) 
  994.         return true;
  995.     if (Year() < 1583) // first Gregorian date February 24, 1582
  996.         return false;
  997.     if (Month()  < 1  ||  Month()  > 12)
  998.         return false;
  999.     if (Month() == 2) {
  1000.         if (Day() < 1 ||  Day() > (IsLeap() ? 29 : 28))
  1001.             return false;
  1002.     } else {
  1003.         if (Day() < 1 ||  Day() > s_DaysInMonth[Month() - 1])
  1004.             return false;
  1005.     }
  1006.     if (Hour()   < 0  ||  Hour()   > 23)
  1007.         return false;
  1008.     if (Minute() < 0  ||  Minute() > 59)
  1009.         return false;
  1010.     if (Second() < 0  ||  Second() > 59)
  1011.         return false;
  1012.     if (NanoSecond() < 0  ||  NanoSecond() >= kNanoSecondsPerSecond)
  1013.         return false;
  1014.     return true;
  1015. }
  1016. CTime& CTime::ToTime(ETimeZone tz)
  1017. {
  1018.     if (GetTimeZoneFormat() != tz) {
  1019.         struct tm* t;
  1020.         time_t timer;
  1021.         timer = GetTimeT();
  1022.         if (timer == -1) 
  1023.             return *this;
  1024.         // MT-Safe protect
  1025.         CFastMutexGuard LOCK(s_TimeMutex);
  1026. #if defined(HAVE_LOCALTIME_R)
  1027.         struct tm temp;
  1028.         if (tz == eLocal) {
  1029.             localtime_r(&timer, &temp);
  1030.         } else {
  1031.             gmtime_r(&timer, &temp);
  1032.         }
  1033.         t = &temp;
  1034. #else
  1035.         t = ( tz == eLocal ) ? localtime(&timer) : gmtime(&timer);
  1036. #endif
  1037.         m_Year   = t->tm_year + 1900;
  1038.         m_Month  = t->tm_mon + 1;
  1039.         m_Day    = t->tm_mday;
  1040.         m_Hour   = t->tm_hour;
  1041.         m_Minute = t->tm_min;
  1042.         m_Second = t->tm_sec;
  1043.         m_Tz     = tz;
  1044.     }
  1045.     return *this;
  1046. }
  1047. bool CTime::operator == (const CTime& t) const
  1048. {
  1049.     CTime tmp(t);
  1050.     tmp.ToTime(GetTimeZoneFormat());
  1051.     return
  1052.         Year()       == tmp.Year()    &&
  1053.         Month()      == tmp.Month()   &&
  1054.         Day()        == tmp.Day()     &&
  1055.         Hour()       == tmp.Hour()    &&
  1056.         Minute()     == tmp.Minute()  &&
  1057.         Second()     == tmp.Second()  &&
  1058.         NanoSecond() == tmp.NanoSecond();
  1059. }
  1060. bool CTime::operator > (const CTime& t) const
  1061. {
  1062.     CTime tmp(t);
  1063.     tmp.ToTime(GetTimeZoneFormat());
  1064.     if (Year()   > tmp.Year())   
  1065.         return true;
  1066.     if (Year()   < tmp.Year())   
  1067.         return false;
  1068.     if (Month()  > tmp.Month())  
  1069.         return true;
  1070.     if (Month()  < tmp.Month())  
  1071.         return false;
  1072.     if (Day()    > tmp.Day())    
  1073.         return true;
  1074.     if (Day()    < tmp.Day())    
  1075.         return false;
  1076.     if (Hour()   > tmp.Hour())   
  1077.         return true;
  1078.     if (Hour()   < tmp.Hour())   
  1079.         return false;
  1080.     if (Minute() > tmp.Minute()) 
  1081.         return true;
  1082.     if (Minute() < tmp.Minute()) 
  1083.         return false;
  1084.     if (Second() > tmp.Second()) 
  1085.         return true;
  1086.     if (Second() < tmp.Second()) 
  1087.         return false;
  1088.     if (NanoSecond() > tmp.NanoSecond()) 
  1089.         return true;
  1090.     return false;
  1091. }
  1092. bool CTime::operator < (const CTime& t) const
  1093. {
  1094.     CTime tmp(t);
  1095.     tmp.ToTime(GetTimeZoneFormat());
  1096.     if (Year()   < tmp.Year())   
  1097.         return true;
  1098.     if (Year()   > tmp.Year())   
  1099.         return false;
  1100.     if (Month()  < tmp.Month())  
  1101.         return true;
  1102.     if (Month()  > tmp.Month())  
  1103.         return false;
  1104.     if (Day()    < tmp.Day())    
  1105.         return true;
  1106.     if (Day()    > tmp.Day())    
  1107.         return false;
  1108.     if (Hour()   < tmp.Hour())   
  1109.         return true;
  1110.     if (Hour()   > tmp.Hour())  
  1111.         return false;
  1112.     if (Minute() < tmp.Minute()) 
  1113.         return true;
  1114.     if (Minute() > tmp.Minute()) 
  1115.         return false;
  1116.     if (Second() < tmp.Second()) 
  1117.         return true;
  1118.     if (Second() > tmp.Second()) 
  1119.         return false;
  1120.     if (NanoSecond() > tmp.NanoSecond()) 
  1121.         return true;
  1122.     return false;
  1123. }
  1124. bool CTime::IsLeap(void) const
  1125. {
  1126.     int year = Year();
  1127.     return year % 4 == 0  &&  year % 100 != 0  ||  year % 400 == 0;
  1128. }
  1129. CTime& CTime::Truncate(void)
  1130. {
  1131.     m_Hour           = 0;
  1132.     m_Minute         = 0;
  1133.     m_Second         = 0;
  1134.     m_NanoSecond     = 0;
  1135.     m_AdjustTimeDiff = 0;
  1136.     return *this;
  1137. }
  1138. CTime& CTime::Clear()
  1139. {
  1140.     m_Year  = 0;
  1141.     m_Month = 0;
  1142.     m_Day   = 0;
  1143.     Truncate();
  1144.     return *this;
  1145. }
  1146. int CTime::DiffSecond(const CTime& t) const
  1147. {
  1148.     int dSec  = Second() - t.Second();
  1149.     int dMin  = Minute() - t.Minute();
  1150.     int dHour = Hour()   - t.Hour();
  1151.     int dDay  = (*this)  - t;
  1152.     return dSec + 60 * dMin + 60 * 60 * dHour + 60 * 60 * 24 * dDay;
  1153. }
  1154. void CTime::x_AdjustDay()
  1155. {
  1156.     int n_days = DaysInMonth();
  1157.     if (Day() > n_days) {
  1158.         m_Day = n_days;
  1159.     }
  1160. }
  1161. CTime& CTime::x_AdjustTime(const CTime& from, bool shift_time)
  1162. {
  1163.     if ( !x_NeedAdjustTime() )
  1164.         return *this; 
  1165.     switch ( GetTimeZonePrecision() ) {
  1166.     case eMinute:
  1167.         if (Minute() != from.Minute())
  1168.             return x_AdjustTimeImmediately(from, shift_time);
  1169.     case eHour:
  1170.         if (Hour() != from.Hour())
  1171.             return x_AdjustTimeImmediately(from, shift_time);
  1172.     case eDay:
  1173.         if (Day() != from.Day())
  1174.             return x_AdjustTimeImmediately(from, shift_time);
  1175.     case eMonth:
  1176.         if (Month() != from.Month())
  1177.             return x_AdjustTimeImmediately(from, shift_time);
  1178.     default:
  1179.         break;
  1180.     }
  1181.     return *this;
  1182. }
  1183.   
  1184. CTime& CTime::x_AdjustTimeImmediately(const CTime& from, bool shift_time)
  1185. {
  1186.     // Time in hours for temporary time shift.
  1187.     // Shift used for obtainment correct result at changeover daytime saving.
  1188.     // Must be > 3 (Linux distinction). On other platforms may be == 3.
  1189.     const int kShift = 4;
  1190.     // MT-Safe protect
  1191.     CFastMutexGuard LOCK(s_TimeAdjustMutex);
  1192.     // Special conversion from <const CTime> to <CTime>
  1193.     CTime tmp(from); 
  1194.     int sign = 0;
  1195.     int diff = 0;
  1196.     // Primary procedure call
  1197.     if ( shift_time ) {
  1198.         sign = ( *this > from ) ? 1 : -1;
  1199.         // !!! Run TimeZoneDiff() first for old time value 
  1200.         diff = -tmp.TimeZoneDiff() + TimeZoneDiff();
  1201.         // Correction need's if time already in identical timezone
  1202.         if (!diff  ||  diff == m_AdjustTimeDiff) {
  1203.             return *this;
  1204.         }
  1205.     } 
  1206.     // Recursive procedure call. Inside below 
  1207.     // x_AddHour(*, eAdjustDaylight, false)
  1208.     else  {
  1209.         // Correction need't if difference not found
  1210.         if (diff == m_AdjustTimeDiff) {
  1211.             return *this;
  1212.         }
  1213.     }
  1214.     // Make correction with temporary time shift
  1215.     time_t t = GetTimeT();
  1216.     CTime tn(t + diff + 3600 * kShift * sign);
  1217.     if (from.GetTimeZoneFormat() == eLocal) {
  1218.         tn.ToLocalTime();
  1219.     }
  1220.     tn.SetTimeZonePrecision(GetTimeZonePrecision());
  1221.     // Release adjust time mutex
  1222.     LOCK.Release();
  1223.     // Primary procedure call
  1224.     if ( shift_time ) {
  1225.         // Cancel temporary time shift
  1226.         tn.x_AddHour(-kShift * sign, eAdjustDaylight, false);
  1227.         tn.m_AdjustTimeDiff = diff;
  1228.     }
  1229.     *this = tn;
  1230.     return *this;
  1231. }
  1232. //=============================================================================
  1233. //
  1234. //  CStopWatch
  1235. //
  1236. //=============================================================================
  1237. double CStopWatch::GetTimeMark()
  1238. {
  1239. #if defined(NCBI_OS_MSWIN)
  1240.     // For Win32, we use QueryPerformanceCounter()
  1241.     LARGE_INTEGER bigint;
  1242.     static double freq;
  1243.     static bool first = true;
  1244.     if ( first ) {
  1245.         LARGE_INTEGER nfreq;
  1246.         QueryPerformanceFrequency(&nfreq);
  1247.         freq  = nfreq.QuadPart;
  1248.         first = false;
  1249.     }
  1250.     if ( !QueryPerformanceCounter(&bigint) ) {
  1251.         return 0.0;
  1252.     }
  1253.     return double(bigint.QuadPart) / freq;
  1254. #else
  1255.     // For Unixes, we use gettimeofday()
  1256.     struct timeval time;
  1257.     if ( gettimeofday (&time, 0) ) {
  1258.         return 0.0;
  1259.     }
  1260.     return double(time.tv_sec) + double(time.tv_usec) / 1e6;
  1261. #endif
  1262. }
  1263. //============================================================================
  1264. //
  1265. //  Extern
  1266. //
  1267. //============================================================================
  1268. // Return difference between times <t1> and <t2> as number of days
  1269. int operator - (const CTime& t1, const CTime& t2)
  1270. {
  1271.     return (int) (s_Date2Number(t1) - s_Date2Number(t2));
  1272. }
  1273. CTime AddYear(const CTime& t, int years)
  1274. {
  1275.     CTime tmp(t);
  1276.     return tmp.AddYear(years);
  1277. }
  1278.  
  1279. CTime AddMonth(const CTime& t, int months)
  1280. {
  1281.     CTime tmp(t);
  1282.     return tmp.AddMonth(months);
  1283. }
  1284.  
  1285. CTime AddDay(const CTime& t, int days)
  1286. {
  1287.     CTime tmp(t);
  1288.     return tmp.AddDay(days);
  1289. }
  1290.  
  1291. CTime AddHour(const CTime& t, int hours)
  1292. {
  1293.     CTime tmp(t);
  1294.     return tmp.AddHour(hours);
  1295. }
  1296.  
  1297. CTime AddMinute(const CTime& t, int minutes)
  1298. {
  1299.     CTime tmp(t);
  1300.     return tmp.AddMinute(minutes);
  1301. }
  1302.  
  1303. CTime AddSecond(const CTime& t, int seconds)
  1304. {
  1305.     CTime tmp(t);
  1306.     return tmp.AddSecond(seconds);
  1307. }
  1308.  
  1309. CTime AddNanoSecond(const CTime& t, long nanoseconds)
  1310. {
  1311.     CTime tmp(t);
  1312.     return tmp.AddNanoSecond(nanoseconds);
  1313. }
  1314. CTime operator + (const CTime& t, int days)
  1315. {
  1316.     CTime tmp = s_Number2Date(s_Date2Number(t) + days, t);
  1317.     tmp.x_AdjustTime(t);
  1318.     return tmp;
  1319. }
  1320.  
  1321. CTime operator + (int days, const CTime& t)
  1322. {
  1323.     CTime tmp = s_Number2Date(s_Date2Number(t) + days, t);
  1324.     tmp.x_AdjustTime(t);
  1325.     return tmp;
  1326. }
  1327.  
  1328. CTime operator - (const CTime& t, int days)
  1329. {
  1330.     CTime tmp = s_Number2Date(s_Date2Number(t) - days, t);
  1331.     tmp.x_AdjustTime(t);
  1332.     return tmp;
  1333. }
  1334.  
  1335. CTime CurrentTime(CTime::ETimeZone tz, CTime::ETimeZonePrecision tzp)
  1336. {
  1337.     return CTime(CTime::eCurrent,tz,tzp);
  1338. }
  1339.  
  1340. CTime Truncate(const CTime& t)
  1341. {
  1342.     CTime tmp(t);
  1343.     return tmp.Truncate();
  1344. }
  1345. END_NCBI_SCOPE
  1346. /*
  1347.  * ===========================================================================
  1348.  * $Log: ncbitime.cpp,v $
  1349.  * Revision 1000.4  2004/06/01 19:09:28  gouriano
  1350.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.49
  1351.  *
  1352.  * Revision 1.49  2004/05/14 13:59:27  gorelenk
  1353.  * Added include of ncbi_pch.hpp
  1354.  *
  1355.  * Revision 1.48  2004/03/26 16:05:29  ivanov
  1356.  * Format symbol 'z' and output time zone for AsString are unsupported
  1357.  * on NCBI_OS_DARWIN and NCBI_OS_BSD (problems with determinition daylight
  1358.  * flag for specified time).
  1359.  *
  1360.  * Revision 1.47  2004/03/25 13:03:31  ivanov
  1361.  * Temporary fix for NCBI_OS_DARWIN and NCBI_OS_BSD
  1362.  *
  1363.  * Revision 1.46  2004/03/24 18:47:47  ivanov
  1364.  * Replaced abs() with if-clause
  1365.  *
  1366.  * Revision 1.45  2004/03/24 15:52:08  ivanov
  1367.  * Added new format symbol support 'z' (local time in format GMT{+|-}HHMM).
  1368.  * Added second parameter to AsString() method that specify an output
  1369.  * timezone.
  1370.  *
  1371.  * Revision 1.44  2003/11/25 19:55:49  ivanov
  1372.  * Added setters for various components of time -- Set*().
  1373.  * Added YearWeekNumber(), MonthWeekNumber().
  1374.  * Reimplemented AddYear() as AddMonth(years*12).
  1375.  * Changed DayOfWeek() to use other computation method.
  1376.  *
  1377.  * Revision 1.43  2003/11/21 20:04:23  ivanov
  1378.  * + DaysInMonth()
  1379.  *
  1380.  * Revision 1.42  2003/10/06 13:59:01  ivanov
  1381.  * Some cosmetics
  1382.  *
  1383.  * Revision 1.41  2003/10/06 13:30:37  ivanov
  1384.  * Fixed cut&paste bug in the MonthNumToName()
  1385.  *
  1386.  * Revision 1.40  2003/10/03 18:27:06  ivanov
  1387.  * Added month and day of week names conversion functions
  1388.  *
  1389.  * Revision 1.39  2003/09/29 21:20:17  golikov
  1390.  * x_Init: create empty CTime obj if str.empty() true, ignore format
  1391.  *
  1392.  * Revision 1.38  2003/07/15 20:09:22  ivanov
  1393.  * Fixed some memory leaks
  1394.  *
  1395.  * Revision 1.37  2003/07/15 19:37:03  vakatov
  1396.  * CTime::x_Init() -- recognize (but then just skip, ignoring the value)
  1397.  * the weekday
  1398.  *
  1399.  * Revision 1.36  2003/04/23 21:07:31  ivanov
  1400.  * CStopWatch::GetTimeMark: removed 'f' to avoid a conversion float
  1401.  * 1e6f to double.
  1402.  *
  1403.  * Revision 1.35  2003/04/16 20:28:00  ivanov
  1404.  * Added class CStopWatch
  1405.  *
  1406.  * Revision 1.34  2003/04/04 16:02:38  lavr
  1407.  * Lines wrapped at 79th column; some minor reformatting
  1408.  *
  1409.  * Revision 1.33  2003/04/03 14:15:48  rsmith
  1410.  * combine pp symbols NCBI_COMPILER_METROWERKS & _MSL_USING_MW_C_HEADERS
  1411.  * into NCBI_COMPILER_MW_MSL
  1412.  *
  1413.  * Revision 1.32  2003/04/02 16:22:34  rsmith
  1414.  * clean up metrowerks ifdefs.
  1415.  *
  1416.  * Revision 1.31  2003/04/02 13:31:18  rsmith
  1417.  * change #ifdefs to allow compilation on MacOSX w/codewarrior
  1418.  * using MSL headers.
  1419.  *
  1420.  * Revision 1.30  2003/02/10 17:17:30  lavr
  1421.  * Fix off-by-one bug in DayOfWeek() calculation
  1422.  *
  1423.  * Revision 1.29  2002/10/24 15:16:37  ivanov
  1424.  * Fixed bug with using two obtainments of the current time in x_SetTime().
  1425.  *
  1426.  * Revision 1.28  2002/10/18 20:13:01  ivanov
  1427.  * Get rid of some Sun Workshop compilation warnings
  1428.  *
  1429.  * Revision 1.27  2002/10/17 16:55:30  ivanov
  1430.  * Added new time format symbols - 'b' and 'B' (month abbreviated and full name)
  1431.  *
  1432.  * Revision 1.26  2002/09/19 20:05:43  vasilche
  1433.  * Safe initialization of static mutexes
  1434.  *
  1435.  * Revision 1.25  2002/08/19 14:02:24  ivanov
  1436.  * MT-safe fix for ToTime()
  1437.  *
  1438.  * Revision 1.24  2002/07/23 19:51:17  lebedev
  1439.  * NCBI_OS_MAC: GetTimeT fix
  1440.  *
  1441.  * Revision 1.23  2002/07/15 18:17:25  gouriano
  1442.  * renamed CNcbiException and its descendents
  1443.  *
  1444.  * Revision 1.22  2002/07/11 14:18:28  gouriano
  1445.  * exceptions replaced by CNcbiException-type ones
  1446.  *
  1447.  * Revision 1.21  2002/06/26 20:47:45  lebedev
  1448.  * Darwin specific: ncbitime changes
  1449.  *
  1450.  * Revision 1.20  2002/06/19 17:18:05  ucko
  1451.  * Fix confusing indentation introduced by R1.19.
  1452.  *
  1453.  * Revision 1.19  2002/06/19 16:18:36  lebedev
  1454.  * Added CoreServices.h for Darwin (timezone and daylight
  1455.  *
  1456.  * Revision 1.18  2002/06/18 16:08:01  ivanov
  1457.  * Fixed all clauses "#if defined *" to "#if defined(*)"
  1458.  *
  1459.  * Revision 1.17  2002/05/13 13:56:46  ivanov
  1460.  * Added MT-Safe support
  1461.  *
  1462.  * Revision 1.16  2002/04/11 21:08:04  ivanov
  1463.  * CVS log moved to end of the file
  1464.  *
  1465.  * Revision 1.15  2002/03/25 17:08:17  ucko
  1466.  * Centralize treatment of Cygwin as Unix rather than Windows in configure.
  1467.  *
  1468.  * Revision 1.14  2002/03/22 19:59:29  ucko
  1469.  * Use timegm() when available [fixes FreeBSD build].
  1470.  * Tweak to work on Cygwin.
  1471.  *
  1472.  * Revision 1.13  2001/07/23 16:05:57  ivanov
  1473.  * Fixed bug in Get/Set DB-time formats (1 day difference)
  1474.  *
  1475.  * Revision 1.12  2001/07/06 15:11:11  ivanov
  1476.  * Added support DataBase-time's -- GetTimeDBI(), GetTimeDBU()
  1477.  *                                  SetTimeDBI(), SetTimeDBU()
  1478.  *
  1479.  * Revision 1.11  2001/06/20 14:46:17  vakatov
  1480.  * Get rid of the '^M' symbols introduced in the R1.10 log
  1481.  *
  1482.  * Revision 1.10  2001/06/19 23:03:46  juran
  1483.  * Replace timezone and daylight with macros
  1484.  * Implement for Mac OS
  1485.  * Note:  This compiles, but it may not work correctly yet.
  1486.  *
  1487.  * Revision 1.9  2001/05/29 20:14:03  ivanov
  1488.  * Added #include <sys/time.h> for UNIX platforms.
  1489.  *
  1490.  * Revision 1.8  2001/05/29 16:14:01  ivanov
  1491.  * Return to nanosecond-revision. Corrected mistake of the work with local
  1492.  * time on Linux. Polish and improvement source code.
  1493.  * Renamed AsTimeT() -> GetTimerT().
  1494.  *
  1495.  * Revision 1.7  2001/05/17 15:05:00  lavr
  1496.  * Typos corrected
  1497.  *
  1498.  * Revision 1.6  2001/04/30 22:01:30  lavr
  1499.  * Rollback to pre-nanosecond-revision due to necessity to use
  1500.  * configure to figure out names of global variables governing time zones
  1501.  *
  1502.  * Revision 1.5  2001/04/29 03:06:09  lavr
  1503.  * #include <time.h>" moved from .cpp to ncbitime.hpp
  1504.  *
  1505.  * Revision 1.4  2001/04/27 20:38:14  ivanov
  1506.  * Support for Local and UTC time added.
  1507.  * Support for work with nanoseconds added.
  1508.  *
  1509.  * Revision 1.3  2001/01/03 17:53:05  butanaev
  1510.  * Fixed bug in SetCurrent()
  1511.  *
  1512.  * Revision 1.2  2000/11/21 18:14:58  butanaev
  1513.  * Fixed bug in operator ++/-- (int)
  1514.  *
  1515.  * Revision 1.1  2000/11/20 22:17:46  vakatov
  1516.  * Added NCBI date/time class CTime ("ncbitime.[ch]pp") and
  1517.  * its test suite ("test/test_ncbitime.cpp")
  1518.  *
  1519.  * ===========================================================================
  1520.  */