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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2