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
|