📄 ncbitime.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbitime.cpp,v $ * PRODUCTION Revision 1000.4 2004/06/01 19:09:28 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.49 * PRODUCTION * =========================================================================== *//* $Id: ncbitime.cpp,v 1000.4 2004/06/01 19:09:28 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors: Anton Butanayev, Denis Vakatov, Vladimir Ivanov * * */#include <ncbi_pch.hpp>#include <corelib/ncbitime.hpp>#include <corelib/ncbimtx.hpp>#include <corelib/ncbithr.hpp>#include <corelib/ncbi_safe_static.hpp>#include <stdlib.h>#if defined(NCBI_OS_MSWIN)# include <sys/timeb.h># include <windows.h>#elif defined(NCBI_OS_UNIX)# include <sys/time.h>#endif#if defined(NCBI_OS_MAC) || defined(NCBI_COMPILER_MW_MSL)# include <OSUtils.h>typedef struct MyTZDLS { long timezone; bool daylight;} MyTZDLS;static MyTZDLS MyReadLocation(){ MachineLocation loc; ReadLocation(&loc); long tz = loc.u.gmtDelta & 0x00ffffff; // Propogate sign bit from bit 23 to bit 31 if West of UTC. // (Sign-extend the GMT correction) if ((tz & 0x00800000) != 0) { tz |= 0xFF000000; } bool dls = (loc.u.dlsDelta != 0); MyTZDLS tzdls = {tz, dls}; return tzdls;}static MyTZDLS sTZDLS = MyReadLocation();# define TimeZone() sTZDLS.timezone# define Daylight() sTZDLS.daylight#elif defined(__CYGWIN__)# define TimeZone() _timezone# define Daylight() _daylight#else# define TimeZone() timezone# define Daylight() daylight#endif#if defined(NCBI_OS_DARWIN) || defined(NCBI_OS_BSD)# define TIMEZONE_IS_UNDEFINED 1#endifBEGIN_NCBI_SCOPE// Protective mutexDEFINE_STATIC_FAST_MUTEX(s_TimeMutex);DEFINE_STATIC_FAST_MUTEX(s_TimeAdjustMutex);// Store global time format in TLSstatic CSafeStaticRef< CTls<string> > s_TlsFormat;static void s_TlsFormatCleanup(string* fmt, void* /* data */){ delete fmt;}//============================================================================//// CTime////============================================================================// Number of days per monthstatic int s_DaysInMonth[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// Month namesstatic const char* kMonthAbbr[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};static const char* kMonthFull[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};// Day of week namesstatic const char* kWeekdayAbbr[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};static const char* kWeekdayFull [7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; // Default value for time formatstatic const char* kDefaultFormat = "M/D/Y h:m:s";// Set of the checked format symbols (w,W not included)static const char* kFormatSymbols = "yYMbBDhmsSzZwW";// Error messagesstatic const string kMsgInvalidTime = "CTime: invalid";// Get number of days in "date"static unsigned s_Date2Number(const CTime& date){ unsigned d = date.Day(); unsigned m = date.Month(); unsigned y = date.Year(); unsigned c, ya; if (m > 2) { m -= 3; } else { m += 9; y--; } c = y / 100; ya = y - 100 * c; return ((146097 * c) >> 2) + ((1461 * ya) >> 2) + (153 * m + 2) / 5 + d + 1721119;}// Conversion number of days in date format// timezone value compute on base <t>static CTime s_Number2Date(unsigned num, const CTime& t){ unsigned d; unsigned j = num - 1721119; unsigned year; unsigned day; unsigned month; year = (((j<<2) - 1) / 146097); j = (j<<2) - 1 - 146097 * year; d = (j>>2); j = ((d<<2) + 3) / 1461; d = (d<<2) + 3 - 1461 * j; d = (d + 4) >> 2; month = (5*d - 3) / 153; d = 5*d - 3 - 153 * month; day = (d + 5) / 5; year = 100 * year + j; if (month < 10) { month += 3; } else { month -= 9; year++; } // Construct new CTime object return CTime (year, month, day, t.Hour(), t.Minute(), t.Second(), t.NanoSecond(), t.GetTimeZoneFormat(), t.GetTimeZonePrecision());}// Calc <value> + <offset> on module <bound>. // Normalized value return in <value> and other part, which above // than <bound>, write at <major>.static void s_Offset(long *value, long offset, long bound, int *major){ *value += offset; *major += (int) (*value / bound); *value %= bound; if (*value < 0) { *major -= 1; *value += bound; }}CTime::CTime(const CTime& t){ *this = t;}CTime::CTime(int year, int yearDayNumber, ETimeZone tz, ETimeZonePrecision tzp){ Clear(); m_Tz = tz; m_TzPrecision = tzp; CTime t = CTime(year, 1, 1); t += yearDayNumber - 1; m_Year = t.Year(); m_Month = t.Month(); m_Day = t.Day();}void CTime::x_VerifyFormat(const string& fmt){ // Check for duplicated format symbols... const int kSize = 256; int count[kSize]; for (int i = 0; i < kSize; i++) { count[i] = 0; } ITERATE(string, it, fmt) { if (strchr(kFormatSymbols, *it) != 0 && ++count[(unsigned int) *it] > 1) { NCBI_THROW(CTimeException, eFormat, "CTime's format is incorrect"); } }}void CTime::x_Init(const string& str, const string& fmt){ Clear(); if ( str.empty() ) { return; } const char* fff; const char* sss = str.c_str();#if ! defined(TIMEZONE_IS_UNDEFINED) bool adjust_needed = false; long adjust_tz = 0;#endif int weekday = -1; for (fff = fmt.c_str(); *fff != '\0'; fff++) { // Non-format symbols if (strchr(kFormatSymbols, *fff) == 0) { if (*fff == *sss) { sss++; continue; // skip matching non-format symbols } break; // error: non-matching non-format symbols } // Month if (*fff == 'b' || *fff == 'B') { const char** name; if (*fff == 'b') { name = kMonthAbbr; } else { name = kMonthFull; } for (unsigned char i = 0; i < 12; i++) { size_t namelen = strlen(*name); if (strncmp(sss, *name, namelen) == 0) { sss += namelen; m_Month = i + 1; break; } name++; } continue; } // Day of week if (*fff == 'w' || *fff == 'W') { const char** day = (*fff == 'w') ? kWeekdayAbbr : kWeekdayFull; for (unsigned char i = 0; i < 7; i++) { size_t len = strlen(*day); if (strncmp(sss, *day, len) == 0) { sss += len; weekday = i; break; } day++; } continue; } // Timezone (GMT time) if (*fff == 'Z') { if (strncmp(sss, "GMT", 3) == 0) { m_Tz = eGmt; sss += 3; } else { m_Tz = eLocal; if (fff[1] == ' ') fff++; } continue; } // Timezone (local time in format GMT+HHMM) if (*fff == 'z') {#if defined(TIMEZONE_IS_UNDEFINED) ERR_POST("Format symbol 'z' is unsupported on this platform");#else m_Tz = eLocal; if (strncmp(sss, "GMT", 3) == 0) { sss += 3; } while ( isspace(*sss) ) { sss++; } int sign = (*sss == '+') ? 1 : ((*sss == '-') ? -1 : 0); if ( sign ) { sss++; } else { sign = 1; } long x_hour = 0; long x_min = 0; char value_str[3]; char* s = value_str; for (size_t len = 2; len != 0 && *sss != '\0' && isdigit(*sss); len--) { *s++ = *sss++; } *s = '\0'; try { x_hour = NStr::StringToLong(value_str); } catch (CStringException) { x_hour = 0; } try { if ( *sss != '\0' ) { s = value_str; for (size_t len = 2; len != 0 && *sss != '\0' && isdigit(*sss); len--) { *s++ = *sss++; } *s = '\0'; x_min = NStr::StringToLong(value_str, 10, NStr::eCheck_Skip); } } catch (CStringException) { x_min = 0; } adjust_needed = true; adjust_tz = sign * (x_hour * 60 + x_min) * 60;#endif continue; } // Other format symbols -- read the next data ingredient char value_str[10]; char* s = value_str; for (size_t len = (*fff == 'Y') ? 4 : ((*fff == 'S') ? 9 : 2); len != 0 && *sss != '\0' && isdigit(*sss); len--) { *s++ = *sss++; } *s = '\0'; long value = NStr::StringToLong(value_str); switch ( *fff ) { case 'Y': m_Year = (int) value; break; case 'y': if (value >= 0 && value < 50) { value += 2000; } else if (value >= 50 && value < 100) { value += 1900; } m_Year = (int) value; break; case 'M': m_Month = (unsigned char) value; break; case 'D': m_Day = (unsigned char) value; break; case 'h': m_Hour = (unsigned char) value; break; case 'm': m_Minute = (unsigned char) value; break; case 's': m_Second = (unsigned char) value; break; case 'S': m_NanoSecond = value; break; default: NCBI_THROW(CTimeException, eFormat, "CTime: format is incorrect"); } } // Check on errors if (weekday != -1 && weekday != DayOfWeek()) { NCBI_THROW(CTimeException, eInvalid, "CTime: invalid day of week"); } if (*fff != '\0' || *sss != '\0') { NCBI_THROW(CTimeException, eFormat, "CTime: format is incorrect"); } if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }#if ! defined(TIMEZONE_IS_UNDEFINED) // Adjust time for current timezone if ( adjust_needed && adjust_tz != -TimeZone() ) { AddSecond(-TimeZone() - adjust_tz); }#endif}CTime::CTime(int year, int month, int day, int hour, int minute, int second, long nanosecond, ETimeZone tz, ETimeZonePrecision tzp){ m_Year = year; m_Month = month; m_Day = day; m_Hour = hour; m_Minute = minute; m_Second = second; m_NanoSecond = nanosecond; m_Tz = tz; m_TzPrecision = tzp; m_AdjustTimeDiff = 0; if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }}CTime::CTime(EInitMode mode, ETimeZone tz, ETimeZonePrecision tzp){ m_Tz = tz; m_TzPrecision = tzp; if (mode == eCurrent) { SetCurrent(); } else { Clear(); }}CTime::CTime(time_t t, ETimeZonePrecision tzp){ m_Tz = eGmt; m_TzPrecision = tzp; SetTimeT(t);}CTime::CTime(const string& str, const string& fmt, ETimeZone tz, ETimeZonePrecision tzp){ m_Tz = tz; m_TzPrecision = tzp; if (fmt.empty()) { x_Init(str, GetFormat()); } else { x_VerifyFormat(fmt); x_Init(str, fmt); }}void CTime::SetYear(int year){ m_Year = year; int n_days = DaysInMonth(); if ( m_Day > n_days ) { m_Day = n_days; } if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }}void CTime::SetMonth(int month){ m_Month = month; int n_days = DaysInMonth(); if ( m_Day > n_days ) { m_Day = n_days; } if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }}void CTime::SetDay(int day){ m_Day = day; int n_days = DaysInMonth(); if ( m_Day > n_days ) { m_Day = n_days; } if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }}void CTime::SetHour(int hour){ m_Hour = hour; if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }}void CTime::SetMinute(int minute){ m_Minute = minute; if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }}void CTime::SetSecond(int second){ m_Second = second; if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }}void CTime::SetNanoSecond(long nanosecond){ m_NanoSecond = nanosecond; if ( !IsValid() ) { NCBI_THROW(CTimeException, eInvalid, kMsgInvalidTime); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -