📄 cimdatetime.cpp
字号:
//%2006//////////////////////////////////////////////////////////////////////////// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;// IBM Corp.; EMC Corporation, The Open Group.// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;// EMC Corporation; VERITAS Software Corporation; The Open Group.// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;// EMC Corporation; Symantec Corporation; The Open Group.//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions:// // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.////==============================================================================////%/////////////////////////////////////////////////////////////////////////////#include <cstring>#include <cassert>#include <fstream>#include "CIMDateTime.h"#include "Exception.h"#include "PegasusAssert.h"#include <time.h>#if defined(PEGASUS_OS_TYPE_UNIX) || defined(PEGASUS_OS_VMS)# include <sys/time.h>#elif defined(PEGASUS_OS_TYPE_WINDOWS)# include <sstream># include <iomanip># include <windows.h>#else# error "unsupported platform"#endifPEGASUS_USING_STD;PEGASUS_NAMESPACE_BEGIN#define PEGASUS_ARRAY_T CIMDateTime# include "ArrayImpl.h"#undef PEGASUS_ARRAY_T//==============================================================================//// CIMDateTimeRep////==============================================================================class CIMDateTimeRep{public: // Number of microseconds elapsed since January 1, 1 BCE. Uint64 usec; // UTC offset Uint32 utcOffset; // ':' for intervals. '-' or '+' for time stamps. Uint16 sign; // Number of wild characters ('*') used to initialize this object. Uint16 numWildcards;};//==============================================================================//// Local constants.////==============================================================================// Julian day of "1 BCE January 1".static const Uint32 JULIAN_ONE_BCE = 1721060;// Number of microseconds in one second.static const Uint64 SECOND = 1000000;// Number of microseconds in one minute.static const Uint64 MINUTE = 60 * SECOND;// Number of microseconds in one hour.static const Uint64 HOUR = 60 * MINUTE;// Number of microseconds in one day.static const Uint64 DAY = 24 * HOUR;// Number of microseconds in ten thousand years.static const Uint64 TEN_THOUSAND_YEARS = PEGASUS_UINT64_LITERAL(315569520000000000);// Number of microseconds in one million days.static const Uint64 HUNDRED_MILLION_DAYS = PEGASUS_UINT64_LITERAL(8640000000000000000);// Adding this to the POSIX 1970 microseconds epoch produces a 1 BCE epoch// as used by this class.static const Uint64 POSIX_1970_EPOCH_OFFSET = PEGASUS_UINT64_LITERAL(62167219200000000);//==============================================================================//// Local functions.////==============================================================================/** Returns true if argument is a leap year.*/static inline bool _isLeapYear(Uint32 year){ return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);}/** Calculates the number of days in a given month, accounting for leap year.*/static Uint32 _getDaysPerMonth(Uint32 year, Uint32 month){ static char _daysPerMonth[] = { 31, /* JAN */ 28, /* FEB */ 31, /* MAR */ 30, /* APR */ 31, /* MAY */ 30, /* JUN */ 31, /* JUL */ 31, /* AUG */ 30, /* SEP */ 31, /* OCT */ 30, /* NOV */ 31, /* DEC */ }; // If February: if (month == 2 && _isLeapYear(year)) return 29; return _daysPerMonth[month - 1];}/** Convert month, day, and year to a Julian day (in the Gregorian calendar). Return julian day.*/static inline Uint32 _toJulianDay(Uint32 year, Uint32 month, Uint32 day){ // Formula adapted from "FREQUENTLY ASKED QUESTIONS ABOUT CALENDARS" // (see http://www.tondering.dk/claus/calendar.html). int a = (14 - month)/12; int y = year+4800-a; int m = month + 12*a - 3; return day + (153*m+2)/5 + y*365 + y/4 - y/100 + y/400 - 32045;}/** Convert a Julian day number (in the Gregorian calendar) to year, month, and day.*/static inline void _fromJulianDay( Uint32 jd, Uint32& year, Uint32& month, Uint32& day){ // Formula adapted from "FREQUENTLY ASKED QUESTIONS ABOUT CALENDARS" // (see http://www.tondering.dk/claus/calendar.html). int a = jd + 32044; int b = (4*a+3)/146097; int c = a - (b*146097)/4; int d = (4*c+3)/1461; int e = c - (1461*d)/4; int m = (5*e+2)/153; day = e - (153*m+2)/5 + 1; month = m + 3 - 12*(m/10); year = b*100 + d - 4800 + m/10;}/** Optimized version of _strToUint32() for n=2 case.*/static inline bool _strToUint32_n2(const Uint16* s, Uint32& x){ Uint32 c0 = s[0] - '0'; if (c0 > 9) return false; Uint32 c1 = s[1] - '0'; if (c1 > 9) return false; x = 10 * c0 + c1; return true;}/** Powers of ten.*/static const Uint32 _tens[] ={ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,};/** Convert the next n digits to integer. Return true on success. Return false if a non-digit was encountered in the first n characters. Don't call with n > 8.*/static inline bool _strToUint32(const Uint16* s, size_t n, Uint32& x){ switch (n) { case 2: return _strToUint32_n2(s, x); default: { x = 0; const Uint32* m = _tens; for (const Uint16* p = &s[n]; n--; ) { Uint16 c = *--p - '0'; if (c > 9) return false; x += *m++ * c; } return true; } }}/** Parse the integer component pointed to by s. Return WILDCARD if s consists entirely of '*' characters. Returns the integer if it consists entirely of digits. Throw exception if digits and '*' are mixed. Also throw exception if digits are encountered when priorWildcards parameter is true.*/static inline Uint32 _parseComponent( const Uint16*& s, size_t n, bool& priorWildcards){ // Check whether all characters are '*'. if (*s == '*') { bool allWild = true; for (size_t i = 0; i < n; i++) { if (s[i] != '*') { allWild = false; break; } } if (allWild) { s += n; priorWildcards = true; return Uint32(-1); } } if (priorWildcards) throw InvalidDateTimeFormatException(); Uint32 x; if (!_strToUint32(s, n, x)) throw InvalidDateTimeFormatException(); s += n; return x;}/** Return true if all characters of the string are asterisks.*/static inline bool _allAsterisks(const Uint16* s, size_t n){ for (size_t i = 0; i < n; i++) { if (s[i] != '*') return false; } return true;}/** Parse the microseconds component of the given string (6 characters). Set numSignificantMicrosecondDigits to the number of leading significant digits (non-asterisks). Note that once an asterisk is encountered, all subsequent characters must be asterisks. Returns the number of microseconds. Throws an exception if priorWildcards is true and any digits are encountered or if digits occurs after asterisks.*/static Uint32 _parseMicroseconds( const Uint16*& s, bool priorWildcards, Uint16& numSignificantDigits){ static const Uint32 _mult[] = { 100000, 10000, 1000, 100, 10, 1, }; // If wildcards encountered in previous components, then the first // character must be an asterisk. if (priorWildcards && s[0] != '*') throw InvalidDateTimeFormatException(); // Examine characters left to right. numSignificantDigits = 0; Uint32 x = 0; for (size_t i = 0; i < 6; i++) { Uint32 c = s[i] - '0'; if (c < 10) { // A digit: x += c * _mult[i]; } else if (c == Uint32('*' - '0')) { // An asterisk: numSignificantDigits = Uint16(i); // All remaining characters must be asterisks. if (!_allAsterisks(s + i, 6 - i)) throw InvalidDateTimeFormatException(); s += 6; return x; } else { // An illegal character. throw InvalidDateTimeFormatException(); } } numSignificantDigits = 6; s += 6; return x;}/** Similar to strcmp() but accounts for wildcards. Compares the first twenty five corresponding characters of s1 and s2. Returns the first non-zero difference, unless one of the characters is an asterisk, in which case it proceeds to the next character. The return value has the following meaning: 0 : s1 is lexographically equal to s2 < 0 : s1 is lexographically less than s2 > 0 : s1 is lexographically greather than s2*/static int _matchTimeStampStrings(const char* s1, const char* s2){ for (size_t i = 0; i < 25; i++) { char c1 = s1[i]; char c2 = s2[i]; if (c1 == '*' || c2 == '*') continue; int r = c1 - c2; if (r) return r; } // Identical return 0;}/** Normalize timestamps by including the utcOffset in the usec member and then setting utcOffset to zero.*/static inline void _normalize(CIMDateTimeRep* in){ if (in->sign != ':') { // DDDDDDDDHHMMSS.MMMMMM:000 Uint64 hours = (in->utcOffset / 60) * HOUR; Uint64 minutes = (in->utcOffset % 60) * MINUTE; // If minutes not wildcarded. // Else if hours not wildcarded. if (in->numWildcards < 10) { if (in->sign == '+') in->usec -= hours + minutes; else in->usec += hours + minutes; } else if (in->numWildcards < 12) { if (in->sign == '+') in->usec -= hours; else in->usec += hours; } in->utcOffset = 0; in->sign = '+'; }}/** Converts the representation object to microseconds. For intervals, this quantity is the same as usec member. Time stamps are normalized so that the usec component contains the UTF offset.*/static Uint64 _toMicroSeconds(const CIMDateTimeRep* rep){ if (rep->sign == ':') return rep->usec; CIMDateTimeRep tmp = *rep; _normalize(&tmp); return tmp.usec;}/** Converts a CIMDateTimeRep representation to its canonical string representation as defined in the "CIM infrastructure Specification". Note that this implementation preserves any wildcard characters used to initially create the CIMDateTime object.*/static void _toCStr(const CIMDateTimeRep* rep, char buffer[26]){ if (rep->sign == ':') { // Extract components: Uint64 usec = rep->usec; Uint32 microseconds = Uint32(usec % SECOND); Uint32 seconds = Uint32((usec / SECOND) % 60); Uint32 minutes = Uint32((usec / MINUTE) % 60); Uint32 hours = Uint32((usec / HOUR) % 24); Uint32 days = Uint32((usec / DAY)); // Format the string. sprintf( buffer, "%08u%02u%02u%02u.%06u:000", Uint32(days), Uint32(hours), Uint32(minutes), Uint32(seconds), Uint32(microseconds)); } else { // Extract components: Uint64 usec = rep->usec; Uint32 microseconds = Uint32(usec % SECOND); Uint32 seconds = Uint32((usec / SECOND) % 60); Uint32 minutes = Uint32((usec / MINUTE) % 60); Uint32 hours = Uint32((usec / HOUR) % 24); Uint32 days = Uint32((usec / DAY)); Uint32 jd = Uint32(days + JULIAN_ONE_BCE); // Convert back from julian to year/month/day: Uint32 year; Uint32 month; Uint32 day; _fromJulianDay(jd, year, month, day); // Format the string. sprintf( buffer, "%04u%02u%02u%02u%02u%02u.%06u%c%03d", Uint32(year), Uint32(month), Uint32(day), Uint32(hours), Uint32(minutes), Uint32(seconds), Uint32(microseconds), rep->sign, rep->utcOffset); } // Fill buffer with '*' chars (if any). { char* first = buffer + 20; char* last = buffer + 20 - rep->numWildcards; if (rep->numWildcards > 6) last--; for (; first != last; first--) { if (*first != '.') *first = '*'; } }}/** This table is used to convert integers between 0 and 99 (inclusive) to a char16 array, with zero padding.*/static Uint16 _intToStrTable[][2] ={ { '0', '0', }, { '0', '1', }, { '0', '2', }, { '0', '3', }, { '0', '4', }, { '0', '5', }, { '0', '6', }, { '0', '7', }, { '0', '8', }, { '0', '9', }, { '1', '0', }, { '1', '1', }, { '1', '2', }, { '1', '3', }, { '1', '4', }, { '1', '5', }, { '1', '6', }, { '1', '7', }, { '1', '8', }, { '1', '9', }, { '2', '0', }, { '2', '1', }, { '2', '2', }, { '2', '3', }, { '2', '4', }, { '2', '5', }, { '2', '6', }, { '2', '7', },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -