(file) Return to CIMDateTime.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

   1 karl  1.66 //%2006////////////////////////////////////////////////////////////////////////
   2 mike  1.10 //
   3 karl  1.42 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
   4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   6 karl  1.37 // IBM Corp.; EMC Corporation, The Open Group.
   7 karl  1.42 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   9 karl  1.50 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
  11 karl  1.66 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  12            // EMC Corporation; Symantec Corporation; The Open Group.
  13 mike  1.10 //
  14            // Permission is hereby granted, free of charge, to any person obtaining a copy
  15 kumpf 1.22 // of this software and associated documentation files (the "Software"), to
  16            // deal in the Software without restriction, including without limitation the
  17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  18 mike  1.10 // sell copies of the Software, and to permit persons to whom the Software is
  19            // furnished to do so, subject to the following conditions:
  20 karl  1.66 // 
  21 kumpf 1.22 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
  22 mike  1.10 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  24 kumpf 1.22 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  27 mike  1.10 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29            //
  30            //==============================================================================
  31            //
  32            //%/////////////////////////////////////////////////////////////////////////////
  33            
  34 mike  1.71 #include <cstring>
  35            #include <cassert>
  36            #include <fstream>
  37 david.dillard 1.54 #include "CIMDateTime.h"
  38 mike          1.71 #include "Exception.h"
  39                    #include "PegasusAssert.h"
  40 kumpf         1.72 #include <time.h>
  41 mike          1.10 
  42 mike          1.77.16.1 #if defined(PEGASUS_OS_TYPE_UNIX) || \
  43                             defined(PEGASUS_OS_VMS) || \
  44                             defined(PEGASUS_OS_VXWORKS)
  45 mike          1.71      # include <sys/time.h>
  46                         #elif defined(PEGASUS_OS_TYPE_WINDOWS)
  47                         # include <sstream>
  48                         # include <iomanip>
  49                         # include <windows.h>
  50 kumpf         1.14      #else
  51 mike          1.71      # error "unsupported platform"
  52 kumpf         1.14      #endif
  53                         
  54                         PEGASUS_USING_STD;
  55                         
  56 mike          1.10      PEGASUS_NAMESPACE_BEGIN
  57                         
  58                         #define PEGASUS_ARRAY_T CIMDateTime
  59                         # include "ArrayImpl.h"
  60                         #undef PEGASUS_ARRAY_T
  61                         
  62 mike          1.71      //==============================================================================
  63                         //
  64                         // CIMDateTimeRep
  65                         //
  66                         //==============================================================================
  67                         
  68                         class CIMDateTimeRep
  69                         {
  70                         public:
  71 mike          1.11      
  72 mike          1.71          // Number of microseconds elapsed since January 1, 1 BCE.
  73                             Uint64 usec;
  74 mike          1.11      
  75 mike          1.71          // UTC offset
  76                             Uint32 utcOffset;
  77 mike          1.10      
  78 mike          1.71          // ':' for intervals. '-' or '+' for time stamps.
  79                             Uint16 sign;
  80 w.white       1.43      
  81 mike          1.71          // Number of wild characters ('*') used to initialize this object.
  82                             Uint16 numWildcards;
  83                         };
  84 kumpf         1.67      
  85 mike          1.71      //==============================================================================
  86                         //
  87                         // Local constants.
  88                         //
  89                         //==============================================================================
  90 kumpf         1.67      
  91 mike          1.71      // Julian day of "1 BCE January 1".
  92                         static const Uint32 JULIAN_ONE_BCE = 1721060;
  93 mike          1.10      
  94 mike          1.71      // Number of microseconds in one second.
  95                         static const Uint64 SECOND = 1000000;
  96 david.dillard 1.54      
  97 mike          1.71      // Number of microseconds in one minute.
  98                         static const Uint64 MINUTE = 60 * SECOND;
  99 w.white       1.43      
 100 mike          1.71      // Number of microseconds in one hour.
 101                         static const Uint64 HOUR = 60 * MINUTE;
 102 w.white       1.43      
 103 mike          1.71      // Number of microseconds in one day.
 104                         static const Uint64 DAY = 24 * HOUR;
 105 w.white       1.43      
 106 mike          1.71      // Number of microseconds in ten thousand years.
 107 kumpf         1.76      static const Uint64 TEN_THOUSAND_YEARS =
 108 mike          1.71          PEGASUS_UINT64_LITERAL(315569520000000000);
 109 david.dillard 1.54      
 110 mike          1.71      // Number of microseconds in one million days.
 111 kumpf         1.76      static const Uint64 HUNDRED_MILLION_DAYS =
 112 mike          1.71          PEGASUS_UINT64_LITERAL(8640000000000000000);
 113 david.dillard 1.54      
 114 mike          1.71      // Adding this to the POSIX 1970 microseconds epoch produces a 1 BCE epoch
 115                         // as used by this class.
 116 kumpf         1.76      static const Uint64 POSIX_1970_EPOCH_OFFSET  =
 117 kumpf         1.77          PEGASUS_UINT64_LITERAL(62167219200000000);
 118 a.arora       1.40      
 119 mike          1.71      //==============================================================================
 120                         //
 121                         // Local functions.
 122                         //
 123                         //==============================================================================
 124 a.arora       1.40      
 125 mike          1.71      /** Returns true if argument is a leap year.
 126 w.white       1.43      */
 127 mike          1.71      static inline bool _isLeapYear(Uint32 year)
 128 w.white       1.43      {
 129 mike          1.71          return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
 130 w.white       1.43      }
 131                         
 132 mike          1.71      /** Calculates the number of days in a given month, accounting for leap year.
 133 w.white       1.43      */
 134 mike          1.71      static Uint32 _getDaysPerMonth(Uint32 year, Uint32 month)
 135 w.white       1.43      {
 136 mike          1.71          static char _daysPerMonth[] =
 137                             {
 138                                 31, /* JAN */
 139                                 28, /* FEB */
 140                                 31, /* MAR */
 141                                 30, /* APR */
 142                                 31, /* MAY */
 143                                 30, /* JUN */
 144                                 31, /* JUL */
 145                                 31, /* AUG */
 146                                 30, /* SEP */
 147                                 31, /* OCT */
 148                                 30, /* NOV */
 149                                 31, /* DEC */
 150                             };
 151                         
 152                             // If February:
 153                         
 154                             if (month == 2 && _isLeapYear(year))
 155                                 return 29;
 156 david.dillard 1.54      
 157 mike          1.71          return _daysPerMonth[month - 1];
 158 w.white       1.43      }
 159 david.dillard 1.54      
 160 mike          1.71      /** Convert month, day, and year to a Julian day (in the Gregorian calendar).
 161                             Return julian day.
 162                         */
 163                         static inline Uint32 _toJulianDay(Uint32 year, Uint32 month, Uint32 day)
 164 w.white       1.43      {
 165 mike          1.71          // Formula adapted from "FREQUENTLY ASKED QUESTIONS ABOUT CALENDARS"
 166                             // (see http://www.tondering.dk/claus/calendar.html).
 167 david.dillard 1.54      
 168 mike          1.71          int a = (14 - month)/12;
 169                             int y = year+4800-a;
 170                             int m = month + 12*a - 3;
 171                             return day + (153*m+2)/5 + y*365 + y/4 - y/100 + y/400 - 32045;
 172 w.white       1.43      }
 173                         
 174 mike          1.71      /** Convert a Julian day number (in the Gregorian calendar) to year, month,
 175                             and day.
 176                         */
 177                         static inline void _fromJulianDay(
 178                             Uint32 jd, Uint32& year, Uint32& month, Uint32& day)
 179 w.white       1.43      {
 180 mike          1.71          // Formula adapted from "FREQUENTLY ASKED QUESTIONS ABOUT CALENDARS"
 181                             // (see http://www.tondering.dk/claus/calendar.html).
 182 david.dillard 1.54      
 183 mike          1.71          int a = jd + 32044;
 184                             int b = (4*a+3)/146097;
 185                             int c = a - (b*146097)/4;
 186                             int d = (4*c+3)/1461;
 187                             int e = c - (1461*d)/4;
 188                             int m = (5*e+2)/153;
 189                             day   = e - (153*m+2)/5 + 1;
 190                             month = m + 3 - 12*(m/10);
 191                             year  = b*100 + d - 4800 + m/10;
 192 w.white       1.43      }
 193                         
 194 mike          1.71      /** Optimized version of _strToUint32() for n=2 case.
 195 w.white       1.43      */
 196 mike          1.71      static inline bool _strToUint32_n2(const Uint16* s, Uint32& x)
 197 w.white       1.43      {
 198 mike          1.71          Uint32 c0 = s[0] - '0';
 199 w.white       1.43      
 200 mike          1.71          if (c0 > 9)
 201 w.white       1.43              return false;
 202 david.dillard 1.54      
 203 mike          1.71          Uint32 c1 = s[1] - '0';
 204 w.white       1.43      
 205 mike          1.71          if (c1 > 9)
 206 w.white       1.43              return false;
 207                         
 208 mike          1.71          x = 10 * c0 + c1;
 209 w.white       1.43      
 210                             return true;
 211                         }
 212                         
 213 mike          1.71      /** Powers of ten.
 214 w.white       1.43      */
 215 mike          1.71      static const Uint32 _tens[] =
 216 mike          1.10      {
 217 mike          1.71          1,
 218                             10,
 219                             100,
 220                             1000,
 221                             10000,
 222                             100000,
 223                             1000000,
 224                             10000000,
 225                         };
 226 kumpf         1.53      
 227 mike          1.71      /** Convert the next n digits to integer. Return true on success. Return
 228                             false if a non-digit was encountered in the first n characters. Don't
 229                             call with n > 8.
 230 w.white       1.43      */
 231 mike          1.71      static inline bool _strToUint32(const Uint16* s, size_t n, Uint32& x)
 232 mike          1.10      {
 233 mike          1.71          switch (n)
 234 kumpf         1.21          {
 235 mike          1.71              case 2:
 236                                     return _strToUint32_n2(s, x);
 237 kumpf         1.53      
 238 mike          1.71              default:
 239                                 {
 240                                     x = 0;
 241 mike          1.10      
 242 mike          1.71                  const Uint32* m = _tens;
 243 kumpf         1.53      
 244 mike          1.71                  for (const Uint16* p = &s[n]; n--; )
 245                                     {
 246                                         Uint16 c = *--p - '0';
 247 kumpf         1.53      
 248 mike          1.71                      if (c > 9)
 249                                             return false;
 250 w.white       1.43      
 251 mike          1.71                      x += *m++ * c;
 252                                     }
 253 david.dillard 1.54      
 254 mike          1.71                  return true;
 255                                 }
 256 kumpf         1.67          }
 257 mike          1.71      }
 258 kumpf         1.67      
 259 mike          1.71      /** Parse the integer component pointed to by s. Return WILDCARD if s consists
 260                             entirely of '*' characters. Returns the integer if it consists entirely
 261 kumpf         1.76          of digits. Throw exception if digits and '*' are mixed. Also throw
 262 mike          1.71          exception if digits are encountered when priorWildcards parameter is true.
 263                         */
 264                         static inline Uint32 _parseComponent(
 265                             const Uint16*& s, size_t n, bool& priorWildcards)
 266                         {
 267                             // Check whether all characters are '*'.
 268 david.dillard 1.54      
 269 mike          1.71          if (*s == '*')
 270 kumpf         1.67          {
 271 mike          1.71              bool allWild = true;
 272 w.white       1.43      
 273 mike          1.71              for (size_t i = 0; i < n; i++)
 274 kumpf         1.67              {
 275 mike          1.71                  if (s[i] != '*')
 276 kumpf         1.67                  {
 277 mike          1.71                      allWild = false;
 278 kumpf         1.67                      break;
 279                                     }
 280 w.white       1.43              }
 281                         
 282 mike          1.71              if (allWild)
 283                                 {
 284                                     s += n;
 285                                     priorWildcards = true;
 286                                     return Uint32(-1);
 287                                 }
 288                             }
 289 w.white       1.43      
 290 mike          1.71          if (priorWildcards)
 291                                 throw InvalidDateTimeFormatException();
 292 w.white       1.43      
 293 mike          1.71          Uint32 x;
 294 kumpf         1.53      
 295 mike          1.71          if (!_strToUint32(s, n, x))
 296                                 throw InvalidDateTimeFormatException();
 297 david.dillard 1.54      
 298 mike          1.71          s += n;
 299                             return x;
 300 mike          1.10      }
 301                         
 302 mike          1.71      /** Return true if all characters of the string are asterisks.
 303 w.white       1.43      */
 304 mike          1.71      static inline bool _allAsterisks(const Uint16* s, size_t n)
 305 mike          1.10      {
 306 mike          1.71          for (size_t i = 0; i < n; i++)
 307                             {
 308                                 if (s[i] != '*')
 309                                     return false;
 310 w.white       1.43          }
 311 mike          1.10      
 312 mike          1.71          return true;
 313 mike          1.10      }
 314                         
 315 mike          1.71      /** Parse the microseconds component of the given string (6 characters).
 316 kumpf         1.76          Set numSignificantMicrosecondDigits to the number of leading significant
 317                             digits (non-asterisks). Note that once an asterisk is encountered, all
 318                             subsequent characters must be asterisks. Returns the number of
 319                             microseconds. Throws an exception if priorWildcards is true and any digits
 320 mike          1.71          are encountered or if digits occurs after asterisks.
 321                         */
 322                         static Uint32 _parseMicroseconds(
 323                             const Uint16*& s,
 324                             bool priorWildcards,
 325                             Uint16& numSignificantDigits)
 326 a.arora       1.40      {
 327 mike          1.71          static const Uint32 _mult[] = { 100000, 10000, 1000, 100, 10, 1, };
 328 a.arora       1.40      
 329 mike          1.71          // If wildcards encountered in previous components, then the first
 330                             // character must be an asterisk.
 331 mike          1.10      
 332 mike          1.71          if (priorWildcards && s[0] != '*')
 333                                 throw InvalidDateTimeFormatException();
 334 w.white       1.43      
 335 mike          1.71          // Examine characters left to right.
 336 mike          1.10      
 337 mike          1.71          numSignificantDigits = 0;
 338                             Uint32 x = 0;
 339 w.white       1.43      
 340 mike          1.71          for (size_t i = 0; i < 6; i++)
 341                             {
 342                                 Uint32 c = s[i] - '0';
 343 kumpf         1.26      
 344 mike          1.71              if (c < 10)
 345                                 {
 346                                     // A digit:
 347                                     x += c * _mult[i];
 348                                 }
 349                                 else if (c == Uint32('*' - '0'))
 350                                 {
 351                                     // An asterisk:
 352                                     numSignificantDigits = Uint16(i);
 353 w.white       1.43      
 354 mike          1.71                  // All remaining characters must be asterisks.
 355 mike          1.10      
 356 mike          1.71                  if (!_allAsterisks(s + i, 6 - i))
 357                                         throw InvalidDateTimeFormatException();
 358 mike          1.10      
 359 mike          1.71                  s += 6;
 360                                     return x;
 361                                 }
 362                                 else
 363                                 {
 364                                     // An illegal character.
 365                                     throw InvalidDateTimeFormatException();
 366                                 }
 367 w.white       1.43          }
 368 mike          1.10      
 369 mike          1.71          numSignificantDigits = 6;
 370                             s += 6;
 371                             return x;
 372                         }
 373 mike          1.10      
 374 mike          1.71      /** Similar to strcmp() but accounts for wildcards. Compares the first twenty
 375                             five corresponding characters of s1 and s2. Returns the first non-zero
 376                             difference, unless one of the characters is an asterisk, in which case
 377                             it proceeds to the next character. The return value has the following
 378                             meaning:
 379 david.dillard 1.54      
 380 mike          1.71                0 : s1 is lexographically equal to s2
 381                                 < 0 : s1 is lexographically less than s2
 382                                 > 0 : s1 is lexographically greather than s2
 383                         */
 384                         static int _matchTimeStampStrings(const char* s1, const char* s2)
 385                         {
 386                             for (size_t i = 0; i < 25; i++)
 387                             {
 388                                 char c1 = s1[i];
 389                                 char c2 = s2[i];
 390 w.white       1.43      
 391 mike          1.71              if (c1 == '*' || c2 == '*')
 392                                     continue;
 393 mike          1.10      
 394 mike          1.71              int r = c1 - c2;
 395 mike          1.10      
 396 mike          1.71              if (r)
 397                                     return r;
 398 mike          1.10          }
 399 david.dillard 1.54      
 400 mike          1.71          // Identical
 401                             return 0;
 402                         }
 403 mike          1.10      
 404 mike          1.71      /** Normalize timestamps by including the utcOffset in the usec member and
 405                             then setting utcOffset to zero.
 406                         */
 407                         static inline void _normalize(CIMDateTimeRep* in)
 408                         {
 409                             if (in->sign != ':')
 410                             {
 411                                 // DDDDDDDDHHMMSS.MMMMMM:000
 412 mike          1.10      
 413 mike          1.71              Uint64 hours = (in->utcOffset / 60) * HOUR;
 414                                 Uint64 minutes = (in->utcOffset % 60) * MINUTE;
 415 w.white       1.43      
 416 mike          1.71              // If minutes not wildcarded.
 417                                 // Else if hours not wildcarded.
 418 w.white       1.43      
 419 mike          1.71              if (in->numWildcards < 10)
 420                                 {
 421                                     if (in->sign == '+')
 422                                         in->usec -= hours + minutes;
 423                                     else
 424                                         in->usec += hours + minutes;
 425 w.white       1.43              }
 426 mike          1.71              else if (in->numWildcards < 12)
 427                                 {
 428                                     if (in->sign == '+')
 429                                         in->usec -= hours;
 430                                     else
 431                                         in->usec += hours;
 432 w.white       1.43              }
 433                         
 434 mike          1.71              in->utcOffset = 0;
 435                                 in->sign = '+';
 436                             }
 437                         }
 438 david.dillard 1.54      
 439 mike          1.71      /** Converts the representation object to microseconds. For intervals, this
 440                             quantity is the same as usec member. Time stamps are normalized so that
 441                             the usec component contains the UTF offset.
 442                         */
 443                         static Uint64 _toMicroSeconds(const CIMDateTimeRep* rep)
 444                         {
 445                             if (rep->sign == ':')
 446                                 return rep->usec;
 447 w.white       1.43      
 448 mike          1.71          CIMDateTimeRep tmp = *rep;
 449                             _normalize(&tmp);
 450                             return tmp.usec;
 451                         }
 452 w.white       1.43      
 453 mike          1.71      /** Converts a CIMDateTimeRep representation to its canonical string
 454                             representation as defined in the "CIM infrastructure Specification".
 455                             Note that this implementation preserves any wildcard characters used
 456                             to initially create the CIMDateTime object.
 457                         */
 458                         static void _toCStr(const CIMDateTimeRep* rep, char buffer[26])
 459                         {
 460                             if (rep->sign == ':')
 461                             {
 462                                 // Extract components:
 463 david.dillard 1.54      
 464 mike          1.71              Uint64 usec = rep->usec;
 465                                 Uint32 microseconds = Uint32(usec % SECOND);
 466                                 Uint32 seconds = Uint32((usec / SECOND) % 60);
 467                                 Uint32 minutes = Uint32((usec / MINUTE) % 60);
 468                                 Uint32 hours = Uint32((usec / HOUR) % 24);
 469                                 Uint32 days = Uint32((usec / DAY));
 470 w.white       1.43      
 471 mike          1.71              // Format the string.
 472 w.white       1.43      
 473 mike          1.71              sprintf(
 474 kumpf         1.76                  buffer,
 475 mike          1.71                  "%08u%02u%02u%02u.%06u:000",
 476                                     Uint32(days),
 477                                     Uint32(hours),
 478                                     Uint32(minutes),
 479                                     Uint32(seconds),
 480                                     Uint32(microseconds));
 481                             }
 482                             else
 483                             {
 484                                 // Extract components:
 485 w.white       1.43      
 486 mike          1.71              Uint64 usec = rep->usec;
 487                                 Uint32 microseconds = Uint32(usec % SECOND);
 488                                 Uint32 seconds = Uint32((usec / SECOND) % 60);
 489                                 Uint32 minutes = Uint32((usec / MINUTE) % 60);
 490                                 Uint32 hours = Uint32((usec / HOUR) % 24);
 491                                 Uint32 days = Uint32((usec / DAY));
 492                                 Uint32 jd = Uint32(days + JULIAN_ONE_BCE);
 493                         
 494                                 // Convert back from julian to year/month/day:
 495                         
 496                                 Uint32 year;
 497                                 Uint32 month;
 498                                 Uint32 day;
 499                                 _fromJulianDay(jd, year, month, day);
 500 w.white       1.43      
 501 mike          1.71              // Format the string.
 502 w.white       1.43      
 503 mike          1.71              sprintf(
 504 kumpf         1.76                  buffer,
 505 mike          1.71                  "%04u%02u%02u%02u%02u%02u.%06u%c%03d",
 506                                     Uint32(year),
 507                                     Uint32(month),
 508                                     Uint32(day),
 509                                     Uint32(hours),
 510                                     Uint32(minutes),
 511                                     Uint32(seconds),
 512                                     Uint32(microseconds),
 513                                     rep->sign,
 514                                     rep->utcOffset);
 515                             }
 516                         
 517                             // Fill buffer with '*' chars (if any).
 518                             {
 519                                 char* first = buffer + 20;
 520                                 char* last = buffer + 20 - rep->numWildcards;
 521 w.white       1.43      
 522 mike          1.71              if (rep->numWildcards > 6)
 523                                     last--;
 524 w.white       1.43      
 525 mike          1.71              for (; first != last; first--)
 526 kumpf         1.62              {
 527 mike          1.71                  if (*first != '.')
 528                                         *first = '*';
 529 w.white       1.43              }
 530 mike          1.71          }
 531                         }
 532 mike          1.10      
 533 mike          1.71      /** This table is used to convert integers between 0 and 99 (inclusive) to
 534                             a char16 array, with zero padding.
 535                         */
 536                         static Uint16 _intToStrTable[][2] =
 537                         {
 538                             { '0', '0', },
 539                             { '0', '1', },
 540                             { '0', '2', },
 541                             { '0', '3', },
 542                             { '0', '4', },
 543                             { '0', '5', },
 544                             { '0', '6', },
 545                             { '0', '7', },
 546                             { '0', '8', },
 547                             { '0', '9', },
 548                             { '1', '0', },
 549                             { '1', '1', },
 550                             { '1', '2', },
 551                             { '1', '3', },
 552                             { '1', '4', },
 553                             { '1', '5', },
 554 mike          1.71          { '1', '6', },
 555                             { '1', '7', },
 556                             { '1', '8', },
 557                             { '1', '9', },
 558                             { '2', '0', },
 559                             { '2', '1', },
 560                             { '2', '2', },
 561                             { '2', '3', },
 562                             { '2', '4', },
 563                             { '2', '5', },
 564                             { '2', '6', },
 565                             { '2', '7', },
 566                             { '2', '8', },
 567                             { '2', '9', },
 568                             { '3', '0', },
 569                             { '3', '1', },
 570                             { '3', '2', },
 571                             { '3', '3', },
 572                             { '3', '4', },
 573                             { '3', '5', },
 574                             { '3', '6', },
 575 mike          1.71          { '3', '7', },
 576                             { '3', '8', },
 577                             { '3', '9', },
 578                             { '4', '0', },
 579                             { '4', '1', },
 580                             { '4', '2', },
 581                             { '4', '3', },
 582                             { '4', '4', },
 583                             { '4', '5', },
 584                             { '4', '6', },
 585                             { '4', '7', },
 586                             { '4', '8', },
 587                             { '4', '9', },
 588                             { '5', '0', },
 589                             { '5', '1', },
 590                             { '5', '2', },
 591                             { '5', '3', },
 592                             { '5', '4', },
 593                             { '5', '5', },
 594                             { '5', '6', },
 595                             { '5', '7', },
 596 mike          1.71          { '5', '8', },
 597                             { '5', '9', },
 598                             { '6', '0', },
 599                             { '6', '1', },
 600                             { '6', '2', },
 601                             { '6', '3', },
 602                             { '6', '4', },
 603                             { '6', '5', },
 604                             { '6', '6', },
 605                             { '6', '7', },
 606                             { '6', '8', },
 607                             { '6', '9', },
 608                             { '7', '0', },
 609                             { '7', '1', },
 610                             { '7', '2', },
 611                             { '7', '3', },
 612                             { '7', '4', },
 613                             { '7', '5', },
 614                             { '7', '6', },
 615                             { '7', '7', },
 616                             { '7', '8', },
 617 mike          1.71          { '7', '9', },
 618                             { '8', '0', },
 619                             { '8', '1', },
 620                             { '8', '2', },
 621                             { '8', '3', },
 622                             { '8', '4', },
 623                             { '8', '5', },
 624                             { '8', '6', },
 625                             { '8', '7', },
 626                             { '8', '8', },
 627                             { '8', '9', },
 628                             { '9', '0', },
 629                             { '9', '1', },
 630                             { '9', '2', },
 631                             { '9', '3', },
 632                             { '9', '4', },
 633                             { '9', '5', },
 634                             { '9', '6', },
 635                             { '9', '7', },
 636                             { '9', '8', },
 637                             { '9', '9', },
 638 mike          1.71      };
 639                         
 640                         /** Convert integer x to a zero-padded char16 string. Legal for x less than
 641                             100000000.
 642                         */
 643                         static inline void _intToChar16String(Uint32 x, Uint16*& str, size_t numDigits)
 644                         {
 645                             if (numDigits == 2)
 646                             {
 647                                 str[0] = _intToStrTable[x][0];
 648                                 str[1] = _intToStrTable[x][1];
 649                                 str += 2;
 650                                 return;
 651                             }
 652 mike          1.10      
 653 mike          1.71          while (numDigits--)
 654                             {
 655                                 Uint32 d = _tens[numDigits];
 656                                 Uint32 n = x / d;
 657                                 x %= d;
 658                                 *str++ = n + '0';
 659 w.white       1.43          }
 660 mike          1.71      }
 661                         
 662                         static void _toChar16Str(const CIMDateTimeRep* rep, Char16* data_)
 663                         {
 664                             Uint16* data = (Uint16*)data_;
 665 mike          1.10      
 666 mike          1.71          if (rep->sign == ':')
 667                             {
 668                                 // DDDDDDDDHHMMSS.MMMMMM:000
 669 mike          1.10      
 670 mike          1.71              Uint64 usec = rep->usec;
 671                                 Uint32 microseconds = Uint32(usec % SECOND);
 672                                 Uint32 seconds = Uint32((usec / SECOND) % 60);
 673                                 Uint32 minutes = Uint32((usec / MINUTE) % 60);
 674                                 Uint32 hours = Uint32((usec / HOUR) % 24);
 675                                 Uint32 days = Uint32((usec / DAY));
 676 david.dillard 1.54      
 677 mike          1.71              _intToChar16String(days, data, 8);
 678                                 _intToChar16String(hours, data, 2);
 679                                 _intToChar16String(minutes, data, 2);
 680                                 _intToChar16String(seconds, data, 2);
 681                                 *data++ = '.';
 682                                 _intToChar16String(microseconds, data, 6);
 683                                 data[0] = ':';
 684                                 data[1] = '0';
 685                                 data[2] = '0';
 686                                 data[3] = '0';
 687 w.white       1.43          }
 688 mike          1.71          else
 689                             {
 690                                 // YYYYMMDDHHMMSS.MMMMMMSUTC
 691                         
 692                                 Uint64 usec = rep->usec;
 693                                 Uint32 microseconds = Uint32(usec % SECOND);
 694                                 Uint32 seconds = Uint32((usec / SECOND) % 60);
 695                                 Uint32 minutes = Uint32((usec / MINUTE) % 60);
 696                                 Uint32 hours = Uint32((usec / HOUR) % 24);
 697                                 Uint32 days = Uint32((usec / DAY));
 698                                 Uint32 jd = Uint32(days + JULIAN_ONE_BCE);
 699                                 Uint32 year;
 700                                 Uint32 month;
 701                                 Uint32 day;
 702                                 _fromJulianDay(jd, year, month, day);
 703                         
 704                                 _intToChar16String(year, data, 4);
 705                                 _intToChar16String(month, data, 2);
 706                                 _intToChar16String(day, data, 2);
 707                                 _intToChar16String(hours, data, 2);
 708                                 _intToChar16String(minutes, data, 2);
 709 mike          1.71              _intToChar16String(seconds, data, 2);
 710                                 *data++ = '.';
 711                                 _intToChar16String(microseconds, data, 6);
 712                                 *data++ = rep->sign;
 713                                 _intToChar16String(rep->utcOffset, data, 3);
 714                             }
 715                         
 716                             // Fill buffer with '*' chars (if any).
 717                             {
 718                                 Uint16* first = (Uint16*)data_ + 20;
 719                                 Uint16* last = (Uint16*)data_ + 20 - rep->numWildcards;
 720 mike          1.10      
 721 mike          1.71              if (rep->numWildcards > 6)
 722                                     last--;
 723 w.white       1.43      
 724 mike          1.71              for (; first != last; first--)
 725                                 {
 726                                     if (*first != '.')
 727                                         *first = '*';
 728 w.white       1.43              }
 729 kumpf         1.63          }
 730 mike          1.71      }
 731                         
 732                         /** Compares the two CIMDateTime representations. The return value is one of
 733                             the following.
 734 w.white       1.43      
 735 mike          1.71              0   : x is equal to y
 736                                 < 0 : x is less than y
 737                                 > 0 : x is greater than y
 738 w.white       1.43      
 739 mike          1.71          This function throws TypeMismatchException if x and y are not of the
 740                             same type (time stamps or intervals).
 741 w.white       1.43      
 742 mike          1.71          Algorithm: If both representations have zero numWildcards members, then
 743                             the comparison is simply _toMicroSeconds(x) - _toMicroSeconds(y). If either
 744                             has a non-zero numWildcards member, then they are converted to to canonical
 745                             string format and compared lexographically with _matchTimeStampStrings().
 746                             If so, then time stamps must be normalized (usec must be adjusted for the
 747                             sign and utcOffset).
 748                         */
 749                         static int _compare(const CIMDateTimeRep* x, const CIMDateTimeRep* y)
 750                         {
 751                             bool xIsInterval = x->sign == ':';
 752                             bool yIsInterval = y->sign == ':';
 753 w.white       1.45      
 754 mike          1.71          if (xIsInterval != yIsInterval)
 755                             {
 756                                 MessageLoaderParms parms(
 757                                     "Common.CIMDateTime.INVALID_OPERATION_COMP_DIF",
 758                                     "Trying to compare CIMDateTime objects of differing types");
 759                                 throw TypeMismatchException(parms);
 760 w.white       1.43          }
 761 mike          1.10      
 762 mike          1.71          if (x->numWildcards == 0 && y->numWildcards == 0)
 763                             {
 764                                 Uint64 xm = _toMicroSeconds(x);
 765                                 Uint64 ym = _toMicroSeconds(y);
 766 w.white       1.47      
 767 mike          1.71              if (xm < ym)
 768                                     return -1;
 769                                 else if (xm > ym)
 770                                     return 1;
 771 david.dillard 1.54      
 772 mike          1.71              return 0;
 773 w.white       1.43          }
 774 mike          1.71          else
 775                             {
 776                                 if (!xIsInterval)
 777                                 {
 778                                     // Normalize before comparing.
 779 david.dillard 1.54      
 780 mike          1.71                  CIMDateTimeRep x1 = *x;
 781                                     _normalize(&x1);
 782 mike          1.10      
 783 mike          1.71                  CIMDateTimeRep y1 = *y;
 784                                     _normalize(&y1);
 785 mike          1.10      
 786 mike          1.71                  char s1[26];
 787                                     char s2[26];
 788                                     _toCStr(&x1, s1);
 789                                     _toCStr(&y1, s2);
 790                                     return _matchTimeStampStrings(s1, s2);
 791                                 }
 792                                 else
 793                                 {
 794                                     char s1[26];
 795                                     char s2[26];
 796                                     _toCStr(x, s1);
 797                                     _toCStr(y, s2);
 798                                     return _matchTimeStampStrings(s1, s2);
 799                                 }
 800                             }
 801 w.white       1.43      }
 802 mike          1.10      
 803 mike          1.71      //==============================================================================
 804                         //
 805                         // CIMDateTime
 806                         //
 807                         //==============================================================================
 808 mike          1.10      
 809 mike          1.71      const Uint32 CIMDateTime::WILDCARD = Uint32(-1);
 810 mike          1.10      
 811 mike          1.71      CIMDateTime::CIMDateTime()
 812 w.white       1.43      {
 813 mike          1.71          _rep = new CIMDateTimeRep;
 814                             memset(_rep, 0, sizeof(CIMDateTimeRep));
 815                             _rep->sign = ':';
 816 mike          1.10      }
 817                         
 818 mike          1.71      CIMDateTime::CIMDateTime(const CIMDateTime& x)
 819 mike          1.10      {
 820 mike          1.71          _rep = new CIMDateTimeRep;
 821                             memcpy(_rep, x._rep, sizeof(CIMDateTimeRep));
 822 w.white       1.43      }
 823                         
 824 mike          1.71      CIMDateTime::CIMDateTime(const String& str)
 825 david.dillard 1.54      {
 826 mike          1.71          _rep = new CIMDateTimeRep;
 827                             set(str);
 828 w.white       1.43      }
 829                         
 830 mike          1.71      CIMDateTime::CIMDateTime(Uint64 usec, Boolean isInterval)
 831 w.white       1.43      {
 832 mike          1.71          if (!isInterval && usec >= TEN_THOUSAND_YEARS)
 833 kumpf         1.67          {
 834 mike          1.71              MessageLoaderParms parms(
 835                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
 836                                     "Cannot create a CIMDateTime time stamp beyond the year 10,000");
 837                                 throw DateTimeOutOfRangeException(parms);
 838 w.white       1.43          }
 839 mike          1.71      
 840                             if (isInterval && usec >= HUNDRED_MILLION_DAYS)
 841 kumpf         1.67          {
 842 mike          1.71              MessageLoaderParms parms(
 843                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
 844                                     "Cannot create a CIMDateTime interval greater than 100 million "
 845                                     "days");
 846                                 throw DateTimeOutOfRangeException(parms);
 847 w.white       1.43          }
 848 david.dillard 1.54      
 849 mike          1.71          _rep = new CIMDateTimeRep;
 850                             _rep->usec = usec;
 851                             _rep->utcOffset = 0;
 852                             _rep->sign = isInterval ? ':' : '+';
 853                             _rep->numWildcards = 0;
 854                         }
 855                         
 856                         CIMDateTime::CIMDateTime(
 857                             Uint32 year,
 858                             Uint32 month,
 859                             Uint32 day,
 860                             Uint32 hours,
 861                             Uint32 minutes,
 862                             Uint32 seconds,
 863                             Uint32 microseconds,
 864                             Uint32 numSignificantMicrosecondDigits,
 865                             Sint32 utcOffset)
 866                         {
 867                             _rep = new CIMDateTimeRep;
 868                             setTimeStamp(year, month, day, hours, minutes, seconds, microseconds,
 869                                 numSignificantMicrosecondDigits, utcOffset);
 870 mike          1.71      }
 871                         
 872                         CIMDateTime::CIMDateTime(
 873                             Uint32 days,
 874                             Uint32 hours,
 875                             Uint32 minutes,
 876                             Uint32 seconds,
 877                             Uint32 microseconds,
 878                             Uint32 numSignificantMicrosecondDigits)
 879                         {
 880                             _rep = new CIMDateTimeRep;
 881                             setInterval(days, hours, minutes, seconds, microseconds,
 882                                 numSignificantMicrosecondDigits);
 883                         }
 884 w.white       1.43      
 885 mike          1.71      CIMDateTime::CIMDateTime(CIMDateTimeRep* rep) : _rep(rep)
 886                         {
 887                         }
 888 w.white       1.43      
 889 mike          1.71      CIMDateTime::~CIMDateTime()
 890                         {
 891                             delete _rep;
 892                         }
 893 david.dillard 1.54      
 894 mike          1.71      CIMDateTime& CIMDateTime::operator=(const CIMDateTime& x)
 895                         {
 896                             if (this != &x)
 897                                 memcpy(_rep, x._rep, sizeof(CIMDateTimeRep));
 898 david.dillard 1.54      
 899 mike          1.71          return *this;
 900                         }
 901 w.white       1.43      
 902 mike          1.71      void CIMDateTime::clear()
 903                         {
 904                             memset(_rep, 0, sizeof(CIMDateTimeRep));
 905                             _rep->sign = ':';
 906                         }
 907 kumpf         1.67      
 908 mike          1.71      void CIMDateTime::set(const String& str)
 909                         {
 910                             clear();
 911 w.white       1.43      
 912 mike          1.71          if (str.size() != 25)
 913                                 throw InvalidDateTimeFormatException();
 914 david.dillard 1.54      
 915 mike          1.71          const Uint16* s = (const Uint16*)str.getChar16Data();
 916                             Uint16 sign = s[21];
 917 w.white       1.43      
 918 mike          1.71          if (sign == ':')
 919                             {
 920                                 bool priorWildcards = false;
 921 mike          1.10      
 922 mike          1.71              // It's an interval of the form "DDDDDDDDHHMMSS.MMMMMM:000"
 923 w.white       1.43      
 924 mike          1.71              // Parse days:
 925 kumpf         1.14      
 926 mike          1.71              Uint32 days = _parseComponent(s, 8, priorWildcards);
 927                                 Uint32 hours = _parseComponent(s, 2, priorWildcards);
 928                                 Uint32 minutes = _parseComponent(s, 2, priorWildcards);
 929                                 Uint32 seconds = _parseComponent(s, 2, priorWildcards);
 930 w.white       1.43      
 931 mike          1.71              // Skip over dot:
 932 david.dillard 1.54      
 933 mike          1.71              if (*s++ != '.')
 934                                     throw InvalidDateTimeFormatException();
 935 w.white       1.43      
 936 mike          1.71              // Parse microseconds:
 937 w.white       1.43      
 938 mike          1.71              Uint16 numSignificantMicrosecondDigits;
 939                                 Uint32 microseconds = _parseMicroseconds(
 940                                     s, priorWildcards, numSignificantMicrosecondDigits);
 941 w.white       1.43      
 942 mike          1.71              // Skip over ':'.
 943 david.dillard 1.54      
 944 mike          1.71              s++;
 945 w.white       1.43      
 946 mike          1.71              // Expect "000".
 947 w.white       1.43      
 948 mike          1.71              if (!(s[0] == '0' && s[1] == '0' && s[2] == '0'))
 949                                     throw InvalidDateTimeFormatException();
 950 w.white       1.43      
 951 mike          1.71              // Set representation:
 952 w.white       1.43      
 953 mike          1.71              setInterval(
 954                                     days,
 955                                     hours,
 956                                     minutes,
 957                                     seconds,
 958                                     microseconds,
 959                                     numSignificantMicrosecondDigits);
 960 w.white       1.43          }
 961 mike          1.71          else if (sign == '-' || sign == '+')
 962                             {
 963                                 bool priorWildcards = false;
 964 w.white       1.43      
 965 mike          1.71              // It's a time stamp of the form "YYYYMMDDHHMMSS.MMMMMMSUTC"
 966 w.white       1.43      
 967 mike          1.71              // Parse year, month, day, hours, minutes, seconds:
 968 w.white       1.43      
 969 mike          1.71              Uint32 year = _parseComponent(s, 4, priorWildcards);
 970                                 Uint32 month = _parseComponent(s, 2, priorWildcards);
 971                                 Uint32 day = _parseComponent(s, 2, priorWildcards);
 972                                 Uint32 hours = _parseComponent(s, 2, priorWildcards);
 973                                 Uint32 minutes = _parseComponent(s, 2, priorWildcards);
 974                                 Uint32 seconds = _parseComponent(s, 2, priorWildcards);
 975 w.white       1.43      
 976 mike          1.71              // Skip over dot:
 977 kumpf         1.14      
 978 mike          1.71              if (*s++ != '.')
 979                                     throw InvalidDateTimeFormatException();
 980 w.white       1.43      
 981 mike          1.71              // Parse microseconds:
 982 w.white       1.43      
 983 mike          1.71              Uint16 numSignificantMicrosecondDigits;
 984                                 Uint32 microseconds = _parseMicroseconds(
 985                                     s, priorWildcards, numSignificantMicrosecondDigits);
 986 kumpf         1.14      
 987 mike          1.71              // Skip over sign:
 988 kumpf         1.14      
 989 mike          1.71              s++;
 990 w.white       1.43      
 991 mike          1.71              // Parse UTF offset.
 992 david.dillard 1.54      
 993 mike          1.71              Uint32 utcOffset;
 994 kumpf         1.76      
 995 mike          1.71              if (!_strToUint32(s, 3, utcOffset))
 996                                     throw InvalidDateTimeFormatException();
 997 w.white       1.43      
 998 mike          1.71              // Set representation:
 999 david.dillard 1.54      
1000 mike          1.71              setTimeStamp(
1001                                     year,
1002                                     month,
1003                                     day,
1004                                     hours,
1005                                     minutes,
1006                                     seconds,
1007                                     microseconds,
1008                                     numSignificantMicrosecondDigits,
1009                                     sign == '+' ? utcOffset : -Sint16(utcOffset));
1010 w.white       1.43          }
1011 david.dillard 1.54          else
1012 mike          1.71          {
1013                                 throw InvalidDateTimeFormatException();
1014                             }
1015                         }
1016 david.dillard 1.54      
1017 mike          1.71      void CIMDateTime::setTimeStamp(
1018                             Uint32 year,
1019                             Uint32 month,
1020                             Uint32 day,
1021                             Uint32 hours,
1022                             Uint32 minutes,
1023                             Uint32 seconds,
1024                             Uint32 microseconds,
1025                             Uint32 numSignificantMicrosecondDigits,
1026                             Sint32 utcOffset)
1027                         {
1028                             clear();
1029 kumpf         1.26      
1030 mike          1.71          Uint32 numWildcards = 0;
1031 w.white       1.43      
1032 mike          1.71          // Check Year:
1033 w.white       1.43      
1034 david.dillard 1.54      
1035 mike          1.71          if (year == WILDCARD)
1036                             {
1037                                 year = 0;
1038                                 numWildcards = 20;
1039                             }
1040                             else if (year > 9999)
1041                             {
1042                                 MessageLoaderParms parms(
1043                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1044                                     "year is greater than 9999");
1045                                 throw DateTimeOutOfRangeException(parms);
1046 w.white       1.43          }
1047                         
1048 mike          1.71          // Check Month:
1049 david.dillard 1.54      
1050 mike          1.71          if (month == WILDCARD)
1051                             {
1052                                 month = 1;
1053 david.dillard 1.54      
1054 mike          1.71              if (!numWildcards)
1055                                     numWildcards = 16;
1056                             }
1057                             else if (month < 1 || month > 12)
1058                             {
1059                                 MessageLoaderParms parms(
1060                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1061                                     "illegal month number");
1062                                 throw DateTimeOutOfRangeException(parms);
1063                             }
1064 w.white       1.43      
1065 mike          1.71          // Check day:
1066 w.white       1.43      
1067 mike          1.71          if (day == WILDCARD)
1068                             {
1069                                 day = 1;
1070 w.white       1.43      
1071 mike          1.71              if (!numWildcards)
1072                                     numWildcards = 14;
1073                             }
1074                             else if (day < 1 || day > _getDaysPerMonth(year, month))
1075                             {
1076                                 MessageLoaderParms parms(
1077                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1078                                     "illegal day number");
1079                                 throw DateTimeOutOfRangeException(parms);
1080                             }
1081 w.white       1.43      
1082 mike          1.71          // Check hours:
1083 w.white       1.43      
1084 mike          1.71          if (hours == WILDCARD)
1085                             {
1086                                 hours = 0;
1087 david.dillard 1.54      
1088 mike          1.71              if (!numWildcards)
1089                                     numWildcards = 12;
1090 w.white       1.43          }
1091 mike          1.71          else if (hours > 23)
1092                             {
1093                                 MessageLoaderParms parms(
1094                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1095                                     "illegal hours number ");
1096                                 throw DateTimeOutOfRangeException(parms);
1097 w.white       1.43          }
1098                         
1099 mike          1.71          // Check minutes:
1100 w.white       1.43      
1101 mike          1.71          if (minutes == WILDCARD)
1102                             {
1103                                 minutes = 0;
1104 w.white       1.43      
1105 mike          1.71              if (!numWildcards)
1106                                     numWildcards = 10;
1107                             }
1108                             else if (minutes > 59)
1109                             {
1110                                 MessageLoaderParms parms(
1111                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1112                                     "illegal minutes number ");
1113                                 throw DateTimeOutOfRangeException(parms);
1114                             }
1115 w.white       1.43      
1116 mike          1.71          // Check seconds:
1117 w.white       1.43      
1118 mike          1.71          if (seconds == WILDCARD)
1119                             {
1120                                 seconds = 0;
1121 kumpf         1.14      
1122 mike          1.71              if (!numWildcards)
1123                                     numWildcards = 8;
1124                             }
1125                             else if (seconds > 59)
1126                             {
1127                                 MessageLoaderParms parms(
1128                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1129                                     "illegal seconds number ");
1130                                 throw DateTimeOutOfRangeException(parms);
1131                             }
1132 w.white       1.43      
1133 mike          1.71          // Check microseconds:
1134 kumpf         1.68      
1135 mike          1.71          if (numSignificantMicrosecondDigits > 6)
1136 kumpf         1.68          {
1137 mike          1.71              MessageLoaderParms parms(
1138                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1139                                     "bad numSignificantMicrosecondDigits (must fall between 0 and 6)");
1140                                 throw DateTimeOutOfRangeException(parms);
1141 w.white       1.43          }
1142 mike          1.71      
1143                             if (microseconds > 999999)
1144 kumpf         1.68          {
1145 mike          1.71              MessageLoaderParms parms(
1146                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1147                                     "microseconds number must be less than 999999");
1148                                 throw DateTimeOutOfRangeException(parms);
1149 w.white       1.43          }
1150 kumpf         1.20      
1151 mike          1.71          if (!numWildcards)
1152                                 numWildcards = 6 - numSignificantMicrosecondDigits;
1153 david.dillard 1.54      
1154 mike          1.71          // Check UTC offset:
1155                         
1156                             if (utcOffset < -999 || utcOffset > 999)
1157 kumpf         1.68          {
1158 mike          1.71              MessageLoaderParms parms(
1159                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1160                                     "illegal utcOffset");
1161                                 throw DateTimeOutOfRangeException(parms);
1162 kumpf         1.14          }
1163 kumpf         1.68      
1164 mike          1.71          // Set the representation.
1165 w.white       1.43      
1166 mike          1.71          Uint32 days = _toJulianDay(year, month, day) - JULIAN_ONE_BCE;
1167 w.white       1.43      
1168 mike          1.71          // Multiply in 64-bit to prevent overflow.
1169                             _rep->usec =
1170                                 Uint64(microseconds) +
1171                                 Uint64((seconds * SECOND)) +
1172                                 Uint64((minutes * MINUTE)) +
1173                                 Uint64((hours * HOUR)) +
1174                                 Uint64((days * DAY));
1175                             _rep->sign = utcOffset < 0 ? '-' : '+';
1176                             _rep->utcOffset = utcOffset < 0 ? -utcOffset : utcOffset;
1177                             _rep->numWildcards = numWildcards;
1178                         }
1179                         
1180                         void CIMDateTime::setInterval(
1181                             Uint32 days,
1182                             Uint32 hours,
1183                             Uint32 minutes,
1184                             Uint32 seconds,
1185                             Uint32 microseconds,
1186                             Uint32 numSignificantMicrosecondDigits)
1187                         {
1188                             clear();
1189 w.white       1.43      
1190 mike          1.71          Uint32 numWildcards = 0;
1191 david.dillard 1.54      
1192 mike          1.71          // Check days:
1193 w.white       1.43      
1194 mike          1.71          if (days == WILDCARD)
1195                             {
1196                                 days = 1;
1197 david.dillard 1.54      
1198 mike          1.71              if (!numWildcards)
1199                                     numWildcards = 20;
1200 w.white       1.43          }
1201 mike          1.71          else if (days > 99999999)
1202                             {
1203                                 MessageLoaderParms parms(
1204                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1205                                     "illegal days number (must be less than 100000000");
1206                                 throw DateTimeOutOfRangeException(parms);
1207 w.white       1.43          }
1208 mike          1.71      
1209                             // Check hours:
1210                         
1211                             if (hours == WILDCARD)
1212                             {
1213                                 hours = 0;
1214                         
1215                                 if (!numWildcards)
1216                                     numWildcards = 12;
1217 david.dillard 1.54          }
1218 mike          1.71          else if (hours > 23)
1219                             {
1220                                 MessageLoaderParms parms(
1221                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1222                                     "illegal hours number ");
1223                                 throw DateTimeOutOfRangeException(parms);
1224 w.white       1.43          }
1225                         
1226 mike          1.71          // Check minutes:
1227                         
1228                             if (minutes == WILDCARD)
1229                             {
1230                                 minutes = 0;
1231 w.white       1.43      
1232 mike          1.71              if (!numWildcards)
1233                                     numWildcards = 10;
1234                             }
1235                             else if (minutes > 59)
1236                             {
1237                                 MessageLoaderParms parms(
1238                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1239                                     "illegal minutes number ");
1240                                 throw DateTimeOutOfRangeException(parms);
1241                             }
1242 w.white       1.43      
1243 mike          1.71          // Check seconds:
1244 w.white       1.43      
1245 mike          1.71          if (seconds == WILDCARD)
1246                             {
1247                                 seconds = 0;
1248 david.dillard 1.54      
1249 mike          1.71              if (!numWildcards)
1250                                     numWildcards = 8;
1251 w.white       1.43          }
1252 mike          1.71          else if (seconds > 59)
1253                             {
1254                                 MessageLoaderParms parms(
1255                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1256                                     "illegal seconds number ");
1257                                 throw DateTimeOutOfRangeException(parms);
1258                             }
1259                         
1260                             // Check microseconds:
1261 w.white       1.43      
1262 mike          1.71          if (numSignificantMicrosecondDigits > 6)
1263                             {
1264                                 MessageLoaderParms parms(
1265                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1266                                     "bad numSignificantMicrosecondDigits (must fall between 0 and 6)");
1267                                 throw DateTimeOutOfRangeException(parms);
1268 w.white       1.43          }
1269 david.dillard 1.54      
1270 mike          1.71          if (microseconds > 999999)
1271                             {
1272                                 MessageLoaderParms parms(
1273                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1274                                     "microseconds number must be less than 999999");
1275                                 throw DateTimeOutOfRangeException(parms);
1276                             }
1277 david.dillard 1.54      
1278 mike          1.71          if (!numWildcards)
1279                                 numWildcards = 6 - numSignificantMicrosecondDigits;
1280 w.white       1.43      
1281 mike          1.71          // Set the representation.
1282 w.white       1.43      
1283 mike          1.71          _rep->usec =
1284                                 microseconds +
1285                                 (seconds * SECOND) +
1286                                 (minutes * MINUTE) +
1287                                 (hours * HOUR) +
1288                                 (days * DAY);
1289                             _rep->sign = ':';
1290                             _rep->utcOffset = 0;
1291                             _rep->numWildcards = numWildcards;
1292                         }
1293 david.dillard 1.54      
1294 mike          1.71      String CIMDateTime::toString() const
1295                         {
1296                             Char16 str[26];
1297                             _toChar16Str(_rep, str);
1298                             return String(str, 25);
1299 w.white       1.43      }
1300                         
1301 mike          1.71      Sint64 CIMDateTime::getDifference(CIMDateTime x, CIMDateTime y)
1302                         {
1303                             if (x.isInterval() != y.isInterval())
1304                                 throw InvalidDateTimeFormatException();
1305 w.white       1.43      
1306 mike          1.71          return y.toMicroSeconds() - x.toMicroSeconds();
1307                         }
1308 w.white       1.43      
1309 mike          1.71      Boolean CIMDateTime::isInterval() const
1310 w.white       1.43      {
1311 mike          1.71          return _rep->sign == ':';
1312                         }
1313 w.white       1.43      
1314 mike          1.71      Boolean CIMDateTime::isInterval()
1315                         {
1316                             return _rep->sign == ':';
1317                         }
1318 w.white       1.43      
1319 mike          1.71      Boolean CIMDateTime::isTimeStamp() const
1320                         {
1321                             return _rep->sign != ':';
1322                         }
1323 david.dillard 1.54      
1324 mike          1.71      Uint64 CIMDateTime::toMicroSeconds() const
1325                         {
1326                             return _toMicroSeconds(_rep);
1327                         }
1328 w.white       1.43      
1329 mike          1.71      Boolean CIMDateTime::equal(const CIMDateTime& x) const
1330                         {
1331                             return _compare(_rep, x._rep) == 0;
1332                         }
1333 w.white       1.43      
1334 mike          1.71      CIMDateTime CIMDateTime::operator+(const CIMDateTime& x) const
1335                         {
1336                             CIMDateTime result(*this);
1337                             return result+=(x);
1338 w.white       1.43      }
1339                         
1340 mike          1.71      CIMDateTime& CIMDateTime::operator+=(const CIMDateTime& x)
1341 w.white       1.43      {
1342 mike          1.71          // ATTN: check for overflow?
1343 w.white       1.43      
1344 mike          1.71          if (!x.isInterval())
1345                                 throw TypeMismatchException();
1346 david.dillard 1.54      
1347 mike          1.71          if (isInterval())
1348                                 _rep->usec += x._rep->usec;
1349                             else
1350                                 _rep->usec += x.toMicroSeconds();
1351 david.dillard 1.54      
1352 mike          1.71          return *this;
1353 w.white       1.43      }
1354                         
1355 mike          1.71      CIMDateTime CIMDateTime::operator-(const CIMDateTime& dt) const
1356 w.white       1.43      {
1357 mike          1.71          // ATTN: check for overflow?
1358                             // ATTN: use operator-=()?
1359 w.white       1.43      
1360 mike          1.71          if (isInterval() && !dt.isInterval())
1361 david.dillard 1.54              throw TypeMismatchException();
1362 w.white       1.43      
1363 mike          1.71          Uint64 x = toMicroSeconds();
1364                             Uint64 y = dt.toMicroSeconds();
1365 w.white       1.43      
1366 mike          1.71          if (x < y)
1367                             {
1368                                 MessageLoaderParms parms(
1369                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1370                                     "Result of subtracting two CIMDateTimes would be negative.");
1371                                 throw DateTimeOutOfRangeException(parms);
1372 w.white       1.43          }
1373                         
1374 mike          1.71          if (isInterval() == dt.isInterval())
1375                             {
1376 kumpf         1.76              // TIMESTAMP - TIMESTAMP
1377 mike          1.71              // OR
1378                                 // INTERVAL - INTERVAL
1379                                 return CIMDateTime(x - y, true);
1380 w.white       1.43          }
1381 mike          1.71          else
1382                             {
1383                                 // TIMESTAMP - INTERVAL (INTERVAL - TIMESTAMP eliminated above).
1384                                 CIMDateTime tmp(x - y, false);
1385                                 tmp._rep->sign = _rep->sign;
1386                                 tmp._rep->utcOffset = _rep->utcOffset;
1387                                 tmp._rep->numWildcards = _rep->numWildcards;
1388                                 return tmp;
1389 w.white       1.43          }
1390 mike          1.71      }
1391 w.white       1.43      
1392 mike          1.71      CIMDateTime& CIMDateTime::operator-=(const CIMDateTime& x)
1393                         {
1394                             // ATTN: check for overflow?
1395 david.dillard 1.54      
1396 mike          1.71          if (!x.isInterval())
1397                                 throw TypeMismatchException();
1398 w.white       1.43      
1399 mike          1.71          if (_rep->usec < x._rep->usec)
1400                             {
1401                                 MessageLoaderParms parms(
1402                                     "Common.Exception.DATETIME_OUT_OF_RANGE_EXCEPTION",
1403                                     "Result of subtracting two CIMDateTimes would be negative.");
1404                                 throw DateTimeOutOfRangeException(parms);
1405                             }
1406 w.white       1.43      
1407 mike          1.71          if (isInterval())
1408                                 _rep->usec -= x._rep->usec;
1409                             else
1410                                 _rep->usec -= x.toMicroSeconds();
1411 w.white       1.43      
1412 mike          1.71          return *this;
1413                         }
1414 w.white       1.43      
1415 mike          1.71      CIMDateTime CIMDateTime::operator*(Uint64 x) const
1416 w.white       1.43      {
1417 mike          1.71          CIMDateTime result(*this);
1418                             return result*=(x);
1419                         }
1420 w.white       1.43      
1421 marek         1.73      CIMDateTime& CIMDateTime::operator*=(Uint64 x)
1422 mike          1.71      {
1423                             if (!isInterval())
1424                                 throw TypeMismatchException();
1425 w.white       1.43      
1426 mike          1.71          _rep->usec *= x;
1427                             return *this;
1428                         }
1429 w.white       1.43      
1430 mike          1.71      CIMDateTime CIMDateTime::operator/(Uint64 x) const
1431                         {
1432                             CIMDateTime result(*this);
1433                             return result/=(x);
1434 w.white       1.43      }
1435                         
1436 marek         1.73      CIMDateTime& CIMDateTime::operator/=(Uint64 x)
1437 mike          1.71      {
1438                             if (!isInterval())
1439                             {
1440                                 MessageLoaderParms parms(
1441                                     "Common.CIMDateTime.INVALID_OPERATION_DIV_INT",
1442                                     "Can not divide a TimeStamp by an integer");
1443                                 throw TypeMismatchException(parms);
1444                             }
1445 w.white       1.43      
1446 kumpf         1.76          if (x == 0)
1447 mike          1.71          {
1448                                 MessageLoaderParms parms(
1449                                     "Common.CIMDateTime.INVALID_OPERATION_DIV_ZERO",
1450                                     "Can not divide CIMDateTime by zero");
1451                                 throw Exception(parms);
1452                             }
1453 w.white       1.43      
1454 mike          1.71          _rep->usec /= x;
1455                             return *this;
1456                         }
1457 w.white       1.43      
1458 mike          1.71      Uint64 CIMDateTime::operator/(const CIMDateTime& x) const
1459 w.white       1.43      {
1460 mike          1.71          if (!isInterval() || !x.isInterval())
1461                             {
1462                                 MessageLoaderParms parms(
1463                                     "Common.CIMDateTime.INVALID_OPERATION_DIV_TS",
1464                                     "Can not divide two CIMDateTime objects if one of them is "
1465                                     "a TimeStamp");
1466                                 throw TypeMismatchException(parms);
1467                             }
1468 david.dillard 1.54      
1469 kumpf         1.76          if (x._rep->usec == 0)
1470 mike          1.71          {
1471                                 MessageLoaderParms parms(
1472                                     "Common.CIMDateTime.INVALID_OPERATION_DIV_ZERO",
1473                                     "Can not divide CIMDateTime by zero");
1474                                 throw Exception(parms);
1475 w.white       1.43          }
1476 kumpf         1.14      
1477 mike          1.71          return _rep->usec / x._rep->usec;
1478                         }
1479 w.white       1.43      
1480 mike          1.71      Boolean CIMDateTime::operator<(const CIMDateTime& x) const
1481                         {
1482                             return _compare(_rep, x._rep) < 0;
1483                         }
1484 w.white       1.43      
1485 mike          1.71      Boolean CIMDateTime::operator<=(const CIMDateTime& x) const
1486                         {
1487                             return _compare(_rep, x._rep) <= 0;
1488                         }
1489 david.dillard 1.54      
1490 mike          1.71      Boolean CIMDateTime::operator>(const CIMDateTime& x) const
1491                         {
1492                             return _compare(_rep, x._rep) > 0;
1493                         }
1494 w.white       1.43      
1495 mike          1.71      Boolean CIMDateTime::operator>=(const CIMDateTime& x) const
1496                         {
1497                             return _compare(_rep, x._rep) >= 0;
1498 w.white       1.43      }
1499                         
1500 mike          1.71      Boolean CIMDateTime::operator!=(const CIMDateTime& x) const
1501                         {
1502                             return _compare(_rep, x._rep) != 0;
1503                         }
1504 w.white       1.43      
1505 mike          1.71      Boolean operator==(const CIMDateTime& x, const CIMDateTime& y)
1506 w.white       1.43      {
1507 mike          1.71          return x.equal(y);
1508 w.white       1.43      }
1509                         
1510 mike          1.71      //==============================================================================
1511                         //
1512                         // PEGASUS_OS_TYPE_UNIX
1513                         //
1514                         //==============================================================================
1515 w.white       1.43      
1516 mike          1.77.16.1 #if defined(PEGASUS_OS_TYPE_UNIX) || \
1517                             defined(PEGASUS_OS_VMS) || \
1518                             defined(PEGASUS_OS_VXWORKS)
1519 w.white       1.43      
1520 mike          1.71      CIMDateTime CIMDateTime::getCurrentDateTime()
1521 w.white       1.43      {
1522 mike          1.71          // Get sec and usec:
1523 w.white       1.43      
1524 mike          1.71          time_t sec;
1525                             Uint64 usec;
1526 marek         1.74          // ATTN: if this fails on your platform, use time() to obtain the
1527                             // sec element and set usec to zero.
1528                             struct timeval tv;
1529 carson.hovey  1.75      #if defined(PEGASUS_OS_VMS)
1530                             void *tz = NULL;
1531                         #else
1532 marek         1.74          struct timezone tz;
1533 carson.hovey  1.75      #endif
1534 marek         1.74          gettimeofday(&tv, &tz);
1535 mike          1.77.16.2 
1536 marek         1.74          sec = tv.tv_sec;
1537                             usec = Uint64(tv.tv_usec);
1538 kumpf         1.14      
1539 mike          1.71          // Get the localtime
1540 david.dillard 1.54      
1541 mike          1.71          struct tm* tmval;
1542                             struct tm tmvalBuffer;
1543                             tmval = localtime_r(&sec, &tmvalBuffer);
1544                             PEGASUS_ASSERT(tmval != 0);
1545 w.white       1.43      
1546 mike          1.71          // Calculate minutes East of GMT.
1547 w.white       1.43      
1548 mike          1.71          int tzMinutesEast;
1549                             {
1550 mike          1.77.16.4 # if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_SOLARIS)
1551 mike          1.71              tzMinutesEast = - (int) timezone / 60;
1552                                 if ((tmval->tm_isdst > 0) && daylight)
1553                                 {
1554 kumpf         1.76                  // ATTN: It is unclear how to determine the DST offset.
1555 mike          1.71                  // Assume 1 hour.
1556                                     tzMinutesEast += 60;
1557                                 }
1558 carson.hovey  1.75      # elif defined(PEGASUS_OS_LINUX) || defined(PEGASUS_OS_VMS)
1559 mike          1.71              tzMinutesEast = (int) tmval->tm_gmtoff/60;
1560                         # else
1561 kumpf         1.77              tzMinutesEast = -tz.tz_minuteswest;
1562 marek         1.74              if (tz.tz_dsttime > 0)
1563 kumpf         1.77              {
1564 kumpf         1.76                  // ATTN: It is unclear how to determine the DST offset.
1565 marek         1.74                  // Assume 1 hour.
1566 kumpf         1.77                  tzMinutesEast += 60;
1567                                 }
1568 mike          1.71      # endif
1569                             }
1570 w.white       1.43      
1571 mike          1.71          // Create the representation object.
1572 w.white       1.43      
1573 mike          1.71          CIMDateTimeRep* rep = new CIMDateTimeRep;
1574 kumpf         1.76          rep->usec =
1575 kumpf         1.77              POSIX_1970_EPOCH_OFFSET +
1576                                 Uint64(sec + tzMinutesEast * 60) * Uint64(1000000) +
1577                                 Uint64(usec);
1578 mike          1.71          rep->sign = tzMinutesEast < 0 ? '-' : '+';
1579                             rep->utcOffset = tzMinutesEast < 0 ? -tzMinutesEast : tzMinutesEast;
1580                             rep->numWildcards = 0;
1581 w.white       1.43      
1582 mike          1.71          return CIMDateTime(rep);
1583                         }
1584 w.white       1.43      
1585 mike          1.71      #endif /* PEGASUS_OS_TYPE_UNIX */
1586 w.white       1.43      
1587 mike          1.71      //==============================================================================
1588                         //
1589                         // PEGASUS_OS_TYPE_WINDOWS
1590                         //
1591                         //==============================================================================
1592 w.white       1.43      
1593 mike          1.71      #if defined(PEGASUS_OS_TYPE_WINDOWS)
1594 w.white       1.43      
1595 mike          1.71      Boolean getCurrentTimeZone(Sint16& currentTimeZone)
1596 w.white       1.43      {
1597 mike          1.71          currentTimeZone = 0;
1598                             TIME_ZONE_INFORMATION timezone;
1599                             ::memset(&timezone, 0, sizeof(timezone));
1600 david.dillard 1.54      
1601 kumpf         1.76          switch(::GetTimeZoneInformation(&timezone))
1602 mike          1.71          {
1603                                 case TIME_ZONE_ID_UNKNOWN:
1604                                 {
1605                                     currentTimeZone = static_cast<Sint16>(timezone.Bias);
1606                                     break;
1607                                 }
1608 w.white       1.43      
1609 mike          1.71              case TIME_ZONE_ID_STANDARD:
1610                                 {
1611 kumpf         1.76                  currentTimeZone =
1612 mike          1.71                      static_cast<Sint16>(timezone.Bias + timezone.StandardBias);
1613                                     break;
1614                                 }
1615 w.white       1.43      
1616 mike          1.71              case TIME_ZONE_ID_DAYLIGHT:
1617                                 {
1618 kumpf         1.76                  currentTimeZone =
1619 mike          1.71                      static_cast<Sint16>(timezone.Bias + timezone.DaylightBias);
1620                                     break;
1621                                 }
1622 w.white       1.43      
1623 mike          1.71              default:
1624                                     break;
1625 kumpf         1.20          }
1626 w.white       1.43      
1627 kumpf         1.76          // the bias used to calculate the time zone is a factor that is used to
1628                             // determine the UTC time from the local time. to get the UTC offset from
1629 mike          1.71          // the local time, use the inverse.
1630 w.white       1.43      
1631 kumpf         1.76          if (currentTimeZone != 0)
1632 mike          1.71          {
1633                                 currentTimeZone *= -1;
1634                             }
1635 w.white       1.43      
1636 mike          1.71          return true;
1637                         }
1638 w.white       1.43      
1639 mike          1.71      CIMDateTime CIMDateTime::getCurrentDateTime()
1640 w.white       1.43      {
1641 mike          1.71          // Get system time.
1642 w.white       1.43      
1643 mike          1.71          SYSTEMTIME time;
1644                             memset(&time, 0, sizeof(time));
1645                             GetLocalTime(&time);
1646 david.dillard 1.54      
1647 mike          1.71          // Get UTC offset.
1648 kumpf         1.20      
1649 mike          1.71          Sint32 utcOffset = 0;
1650                             Sint16 currentTimeZone;
1651 kumpf         1.20      
1652 mike          1.71          if (getCurrentTimeZone(currentTimeZone))
1653                                 utcOffset = currentTimeZone;
1654 w.white       1.43      
1655 mike          1.71          // Create the CIMDateTime object.
1656 w.white       1.43      
1657 mike          1.71          return CIMDateTime(
1658                                 time.wYear,
1659                                 time.wMonth,
1660                                 time.wDay,
1661                                 time.wHour,
1662                                 time.wMinute,
1663                                 time.wSecond,
1664                                 time.wMilliseconds * 1000,
1665                                 6,
1666                                 utcOffset);
1667 w.white       1.43      }
1668                         
1669 mike          1.71      #endif /* PEGASUS_OS_TYPE_WINDOWS */
1670 w.white       1.43      
1671 mike          1.71      /*
1672                         ================================================================================
1673 w.white       1.43      
1674 mike          1.71      Notes:
1675 w.white       1.43      
1676 mike          1.71          (1) The legacy implementation added the UTC offset when it was negative and
1677 kumpf         1.76              substracted it when it was positive. I preserved this behavior but
1678 mike          1.71              suspect it may be wrong.
1679 kumpf         1.20      
1680 mike          1.71          (2) Evenetually change getCurrentDateTime() to use constructor that takes
1681                                 a single microseconds component.
1682 kumpf         1.14      
1683 mike          1.71          (4) Add overflow checking for adds and multiplies.
1684 david.dillard 1.54      
1685 mike          1.71      ================================================================================
1686                         */
1687 w.white       1.43      
1688 mike          1.10      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2