1 karl 1.37 //%2003////////////////////////////////////////////////////////////////////////
|
2 mike 1.10 //
|
3 karl 1.37 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Development
4 // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
|
7 mike 1.10 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
9 kumpf 1.22 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
12 mike 1.10 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
|
15 kumpf 1.22 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
16 mike 1.10 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
17 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
18 kumpf 1.22 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
21 mike 1.10 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //==============================================================================
25 //
26 // Author: Mike Brasher (mbrasher@bmc.com)
27 //
|
28 kumpf 1.14 // Modified By: Sushma Fernandes, Hewlett-Packard Company
|
29 kumpf 1.17 // (sushma_fernandes@hp.com)
30 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
31 kumpf 1.26 // Carol Ann Krug Graves, Hewlett-Packard Company
32 // (carolann_graves@hp.com)
|
33 a.arora 1.38 // Amit K Arora, IBM (amita@in.ibm.com) for PEP-101
|
34 mike 1.10 //
35 //%/////////////////////////////////////////////////////////////////////////////
36
|
37 sage 1.23 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
38 #include <Pegasus/Common/Config.h>
39 #endif
40
|
41 mike 1.10 #include <cctype>
|
42 kumpf 1.17 #include <time.h>
|
43 kumpf 1.26 #include <Pegasus/Common/Destroyer.h>
|
44 mday 1.19 #include "CIMDateTime.h"
|
45 kumpf 1.25 #include "InternalException.h"
|
46 mike 1.10
|
47 kumpf 1.32 #include <errno.h>
48
|
49 kumpf 1.14 #if defined(PEGASUS_OS_TYPE_WINDOWS)
50 # include <Pegasus/Common/CIMDateTimeWindows.cpp>
51 #elif defined(PEGASUS_OS_TYPE_UNIX)
52 # include <Pegasus/Common/CIMDateTimeUnix.cpp>
53 #elif defined(PEGASUS_OS_TYPE_NSK)
54 # include <Pegasus/Common/CIMDateTimeNsk.cpp>
55 #else
56 # error "Unsupported platform"
57 #endif
58
59 PEGASUS_USING_STD;
60
|
61 mike 1.10 PEGASUS_NAMESPACE_BEGIN
62
63 #define PEGASUS_ARRAY_T CIMDateTime
64 # include "ArrayImpl.h"
65 #undef PEGASUS_ARRAY_T
66
|
67 karl 1.16 // ATTN: P3 KS 04/17/02 Need methods for determining inequalities.
|
68 mike 1.11
|
69 karl 1.16 // ATTN: P3 KS 04/17/02 Need methods for extracting components (e.g., minutes, hours)?
|
70 mike 1.11
|
71 karl 1.16 // ATTN: P3 KS 04/17/02 Needs constructor that creates from individual elements(year,...)
|
72 mike 1.10
73 static const char _NULL_INTERVAL_TYPE_STRING[] = "00000000000000.000000:000";
|
74 karl 1.12 static const char _NULL_DATE_TYPE_STRING[] = "00000000000000.000000-000";
|
75 mike 1.10
|
76 kumpf 1.21
|
77 a.arora 1.38 CIMDateTime::CIMDateTime() :
78 _rep(new CIMDateTimeRep())
|
79 mike 1.10 {
80 clear();
81 }
82
|
83 a.arora 1.38 CIMDateTime::CIMDateTime(const String & str) :
84 _rep(new CIMDateTimeRep())
|
85 mike 1.10 {
|
86 kumpf 1.21 if (!_set(str))
87 {
|
88 a.arora 1.38 _rep.reset();
|
89 kumpf 1.28 throw InvalidDateTimeFormatException();
|
90 kumpf 1.21 }
|
91 mike 1.10 }
92
|
93 a.arora 1.38
94 CIMDateTime::CIMDateTime(const CIMDateTime& x) :
95 _rep(new CIMDateTimeRep())
|
96 mike 1.10 {
|
97 kumpf 1.21 memcpy(_rep->data, x._rep->data, sizeof(_rep->data));
|
98 mike 1.10 }
99
100 CIMDateTime& CIMDateTime::operator=(const CIMDateTime& x)
101 {
102 if (&x != this)
|
103 kumpf 1.21 memcpy(_rep->data, x._rep->data, sizeof(_rep->data));
|
104 mike 1.10
105 return *this;
106 }
107
|
108 kumpf 1.26 String CIMDateTime::toString () const
|
109 mike 1.10 {
|
110 kumpf 1.26 return String (_rep->data);
|
111 mike 1.10 }
112
113 void CIMDateTime::clear()
114 {
|
115 kumpf 1.21 strcpy(_rep->data, _NULL_INTERVAL_TYPE_STRING);
|
116 mike 1.10 }
117
|
118 kumpf 1.26 Boolean CIMDateTime::_set(const String & dateTimeStr)
|
119 mike 1.10 {
120 clear();
121
|
122 kumpf 1.31 CString dtStr = dateTimeStr.getCString();
123 const char* str = dtStr;
|
124 kumpf 1.26
|
125 mike 1.10 // Be sure the incoming string is the proper length:
126
|
127 kumpf 1.21 if (strlen(str) != CIMDateTimeRep::FORMAT_LENGTH)
|
128 mike 1.10 return false;
129
130 // Determine the type (date or interval); examine the 21st character;
131 // it must be one of ':' (interval), '+' (date), or '-' (date).
132
133 const Uint32 SIGN_OFFSET = 21;
134 const Uint32 DOT_OFFSET = 14;
135
136 Boolean isInterval = strcmp(&str[SIGN_OFFSET], ":000") == 0;
137
138 if (!isInterval && str[SIGN_OFFSET] != '+' && str[SIGN_OFFSET] != '-')
139 return false;
140
141 // Check for the decimal place:
142
143 if (str[DOT_OFFSET] != '.')
144 return false;
145
146 // Check to see if other characters are digits:
147
|
148 kumpf 1.21 for (Uint32 i = 0; i < CIMDateTimeRep::FORMAT_LENGTH; i++)
|
149 mike 1.10 {
150 if (i != DOT_OFFSET && i != SIGN_OFFSET && !isdigit(str[i]))
151 return false;
152 }
153
154 // Check to see if the month and day are in range (date only):
155
156 char buffer[16];
157
158 if (!isInterval)
159 {
160 // Get the month:
161
162 sprintf(buffer, "%2.2s", str + 4);
163 long month = atoi(buffer);
164
|
165 tony 1.35 // Allow for zero month - default value processing
|
166 tony 1.36 if (month == 0 || month > 12)
|
167 mike 1.10 return false;
168
169 // Get the day:
170
171 sprintf(buffer, "%2.2s", str + 6);
172 long day = atoi(buffer);
173
|
174 tony 1.35 // Allow for zero day - default value processing
|
175 tony 1.36 if (day == 0 || day > 31)
|
176 mike 1.10 return false;
177 }
178
179 // Check the hours and minutes:
180
181 sprintf(buffer, "%2.2s", str + 8);
182 long hours = atoi(buffer);
183
|
184 kumpf 1.26 if (hours > 23)
|
185 mike 1.10 return false;
186
187 sprintf(buffer, "%2.2s", str + 10);
188 long minutes = atoi(buffer);
189
190 if (minutes > 59)
191 return false;
192
193 sprintf(buffer, "%2.2s", str + 12);
194 long seconds = atoi(buffer);
195
196 if (seconds > 59)
197 return false;
198
|
199 kumpf 1.21 memcpy(_rep->data, str, sizeof(_rep->data));
|
200 mike 1.10
201 return true;
202 }
203
|
204 kumpf 1.26 void CIMDateTime::set(const String & str)
|
205 mike 1.10 {
206 if (!_set(str))
|
207 kumpf 1.28 throw InvalidDateTimeFormatException();
|
208 mike 1.10 }
209
210 Boolean operator==(const CIMDateTime& x, const CIMDateTime& y)
211 {
|
212 kumpf 1.26 return x.equal (y);
|
213 kumpf 1.14 }
214
|
215 kumpf 1.26 void formatDateTime(char* dateTimeStr, tm* tm)
|
216 kumpf 1.14 {
217 Uint32 index = 0, index1 = 0;
218 long year = 0;
219 char buffer[16];
220
221 // Initialize the components of tm structure
222 tm->tm_year = 0;
223 tm->tm_mon = 0;
224 tm->tm_mday = 0;
225 tm->tm_hour = 0;
226 tm->tm_min = 0;
227 tm->tm_sec = 0;
228 tm->tm_isdst = 0;
229 tm->tm_wday = 0;
230 tm->tm_yday = 0;
231
232 // Extract the year.
233 sprintf(buffer, "%4.4s", dateTimeStr);
234 year = atoi(buffer);
235 year = year - 1900;
236 tm->tm_year = year;
237 kumpf 1.14
238 // Extract the Month.
239 sprintf(buffer, "%2.2s", dateTimeStr + 4);
240 tm->tm_mon = atoi(buffer);
241
242 // Extract the Day.
243 sprintf(buffer, "%2.2s", dateTimeStr + 6);
244 tm->tm_mday = atoi(buffer);
245
246 // Extract the Hour.
247 sprintf(buffer, "%2.2s", dateTimeStr + 8);
248 tm->tm_hour = atoi(buffer);
249
250 // Extract the Minutes.
251 sprintf(buffer, "%2.2s", dateTimeStr + 10);
252 tm->tm_min = atoi(buffer);
253
254 // Extract the Seconds.
255 sprintf(buffer, "%2.2s", dateTimeStr + 12);
256 tm->tm_sec = atoi(buffer);
257 }
258 kumpf 1.14
259 Boolean CIMDateTime::isInterval()
260 {
261 const Uint32 SIGN_OFFSET = 21;
262
|
263 kumpf 1.26 Boolean isInterval = strcmp(&_rep->data[SIGN_OFFSET], ":000") == 0 ;
|
264 kumpf 1.14
265 return isInterval;
266 }
267
|
268 kumpf 1.26 Boolean CIMDateTime::equal (const CIMDateTime & x) const
269 {
270 return memcmp (this->_rep->data, x._rep->data, sizeof (this->_rep->data))
271 == 0;
272 }
273
|
274 kumpf 1.20 Sint64 CIMDateTime::getDifference(CIMDateTime startTime, CIMDateTime finishTime)
|
275 kumpf 1.14 {
276 const char* startDateTimeCString;
277 const char* finishDateTimeCString;
|
278 kumpf 1.34 char dateTimeOnly[CIMDateTimeRep::FORMATTED_DATE_TIME];
|
279 kumpf 1.14 struct tm tmvalStart;
280 struct tm tmvalFinish;
|
281 kumpf 1.20 Sint64 differenceInSeconds = 0;
282 time_t timeStartInSeconds;
283 time_t timeFinishInSeconds;
284 char sign;
285 Uint32 offset;
286 char buffer[4];
|
287 kumpf 1.14
288 //
289 // Get the dates in CString form
290 //
|
291 kumpf 1.26 startDateTimeCString = startTime._rep->data;
292 finishDateTimeCString = finishTime._rep->data;
|
293 kumpf 1.14
294 //
295 // Check if the startTime or finishTime are intervals
296 //
|
297 kumpf 1.20 if (startTime.isInterval() && finishTime.isInterval())
298 {
299 char intervalBuffer[9];
|
300 kumpf 1.26 //
301 // NOTE: although a Uint64 is not required to hold the maximum
302 // value for these variables, if they are not defined as Uint64s,
303 // overflow/truncation can occur during the calculation of the
304 // number of microseconds, and the final result may be incorrect
305 //
306 Uint64 startIntervalDays;
307 Uint64 startIntervalHours;
308 Uint64 startIntervalMinutes;
309 Uint64 startIntervalSeconds;
310 Uint64 startIntervalMicroseconds;
311 Uint64 finishIntervalDays;
312 Uint64 finishIntervalHours;
313 Uint64 finishIntervalMinutes;
314 Uint64 finishIntervalSeconds;
315 Uint64 finishIntervalMicroseconds;
316 Uint64 startIntervalInMicroseconds;
317 Uint64 finishIntervalInMicroseconds;
318 Sint64 intervalDifferenceInMicroseconds;
|
319 kumpf 1.20
320 // Parse the start time interval and get the days, minutes, hours
321 // and seconds
322
323 // Extract the days.
324 sprintf(intervalBuffer, "%8.8s", startDateTimeCString);
325 startIntervalDays = atoi(intervalBuffer);
326
327 // Extract the Hour.
328 sprintf(intervalBuffer, "%2.2s", startDateTimeCString + 8);
329 startIntervalHours = atoi(intervalBuffer);
330
331 // Extract the Minutes.
332 sprintf(intervalBuffer, "%2.2s", startDateTimeCString + 10);
333 startIntervalMinutes = atoi(intervalBuffer);
334
335 // Extract the Seconds.
336 sprintf(intervalBuffer, "%2.2s", startDateTimeCString + 12);
337 startIntervalSeconds = atoi(intervalBuffer);
338
|
339 kumpf 1.26 // Extract the Microseconds
340 sprintf(intervalBuffer, "%6.6s", startDateTimeCString + 15);
341 startIntervalMicroseconds = atoi(intervalBuffer);
342
|
343 kumpf 1.20 // Parse the finish time interval and get the days, minutes, hours
344 // and seconds
345
346 // Extract the days.
347 sprintf(intervalBuffer, "%8.8s", finishDateTimeCString);
348 finishIntervalDays = atoi(intervalBuffer);
349
350 // Extract the Hour.
351 sprintf(intervalBuffer, "%2.2s", finishDateTimeCString + 8);
352 finishIntervalHours = atoi(intervalBuffer);
353
354 // Extract the Minutes.
355 sprintf(intervalBuffer, "%2.2s", finishDateTimeCString + 10);
356 finishIntervalMinutes = atoi(intervalBuffer);
357
358 // Extract the Seconds.
359 sprintf(intervalBuffer, "%2.2s", finishDateTimeCString + 12);
360 finishIntervalSeconds = atoi(intervalBuffer);
361
|
362 kumpf 1.26 // Extract the Microseconds
363 sprintf(intervalBuffer, "%6.6s", finishDateTimeCString + 15);
364 finishIntervalMicroseconds = atoi(intervalBuffer);
365
|
366 kumpf 1.20 // Convert all values to seconds and compute the start and finish
367 // intervals in seconds.
|
368 kumpf 1.26 startIntervalInMicroseconds =
|
369 kumpf 1.30 (startIntervalDays*PEGASUS_UINT64_LITERAL(86400000000)) +
370 (startIntervalHours*PEGASUS_UINT64_LITERAL(3600000000)) +
371 (startIntervalMinutes*60000000) +
372 (startIntervalSeconds*1000000) +
373 startIntervalMicroseconds;
|
374 kumpf 1.26
375 finishIntervalInMicroseconds =
|
376 kumpf 1.30 (finishIntervalDays*PEGASUS_UINT64_LITERAL(86400000000)) +
377 (finishIntervalHours*PEGASUS_UINT64_LITERAL(3600000000)) +
378 (finishIntervalMinutes*60000000) +
379 (finishIntervalSeconds*1000000) +
380 finishIntervalMicroseconds;
|
381 kumpf 1.20
382 // Get the difference.
|
383 kumpf 1.26 intervalDifferenceInMicroseconds =
384 (Sint64)(finishIntervalInMicroseconds -
385 startIntervalInMicroseconds);
|
386 kumpf 1.20
|
387 kumpf 1.26 return intervalDifferenceInMicroseconds;
|
388 kumpf 1.20 }
389 else if ( startTime.isInterval() || finishTime.isInterval() )
|
390 kumpf 1.14 {
|
391 kumpf 1.24 // ATTN-RK-20020815: Wrong exception to throw.
|
392 kumpf 1.28 throw InvalidDateTimeFormatException();
|
393 kumpf 1.14 }
394
395 //
396 // Copy only the Start date and time in to the dateTimeOnly string
397 //
|
398 kumpf 1.21 strncpy( dateTimeOnly, startDateTimeCString, CIMDateTimeRep::DATE_TIME_LENGTH );
399 dateTimeOnly[CIMDateTimeRep::DATE_TIME_LENGTH] = 0;
|
400 kumpf 1.14 formatDateTime(dateTimeOnly ,&tmvalStart);
401
402 //
403 // Copy only the Finish date and time in to the dateTimeOnly string
404 //
|
405 kumpf 1.21 strncpy( dateTimeOnly, finishDateTimeCString, CIMDateTimeRep::DATE_TIME_LENGTH );
406 dateTimeOnly[CIMDateTimeRep::DATE_TIME_LENGTH] = 0;
|
407 kumpf 1.14 formatDateTime( dateTimeOnly, &tmvalFinish );
408
|
409 kumpf 1.20 // Convert local time to seconds since the epoch
410 timeStartInSeconds = mktime(&tmvalStart);
|
411 kumpf 1.32
412 // Check if the date is within the supported range of mktime.
413 // If not return an error. Unix mktime sets errno to ERANGE.
414 // Check for both return code from mktime as well as errno.
415 // In case of Windows errno is not set, only check for return code
416 // from mktime for Windows platform.
|
417 dan 1.33 #ifdef PEGASUS_OS_HPUX
|
418 kumpf 1.32 if ( timeStartInSeconds == (time_t)-1 && errno == ERANGE)
419 #else
420 if ( timeStartInSeconds == (time_t)-1 )
421 #endif
422 {
423 throw DateTimeOutOfRangeException(startTime.toString());
424 }
425
|
426 kumpf 1.20 timeFinishInSeconds = mktime(&tmvalFinish);
|
427 kumpf 1.32
428 // Check if the date is within the supported range of mktime.
429 // If not return an error. Unix mktime sets errno to ERANGE.
430 // Check for both return code from mktime as well as errno.
431 // In case of Windows errno is not set, only check for return code
432 // from mktime for Windows platform.
|
433 dan 1.33 #ifdef PEGASUS_OS_HPUX
|
434 kumpf 1.32 if ( timeFinishInSeconds == (time_t)-1 && errno == ERANGE)
435 #else
436 if ( timeFinishInSeconds == (time_t)-1 )
437 #endif
438 {
439 throw DateTimeOutOfRangeException(finishTime.toString());
440 }
441
|
442 kumpf 1.20 // Convert start time to UTC
443 // Get the sign and UTC offset.
444 sign = startDateTimeCString[21];
445 sprintf(buffer, "%3.3s", startDateTimeCString + 22);
446 offset = atoi(buffer);
447
448 if ( sign == '+' )
449 {
450 // Convert the offset from minutes to seconds and subtract it from
451 // Start time
452 timeStartInSeconds = timeStartInSeconds - ( offset * 60 );
453 }
454 else
455 {
456 // Convert the offset from minutes to seconds and add it to
457 // Start time
458 timeStartInSeconds = timeStartInSeconds + (offset * 60);
459 }
460
461 // Convert finish time to UTC
462 // Get the sign and UTC offset.
463 kumpf 1.20 sign = finishDateTimeCString[21];
464 sprintf(buffer, "%3.3s", finishDateTimeCString + 22);
465 offset = atoi(buffer);
466
467 if ( sign == '+' )
468 {
469 // Convert the offset from minutes to seconds and subtract it from
470 // finish time
471 timeFinishInSeconds = timeFinishInSeconds - ( offset * 60 );
472 }
473 else
474 {
475 // Convert the offset from minutes to seconds and add it to
476 // finish time
477 timeFinishInSeconds = timeFinishInSeconds + (offset * 60);
478 }
479
|
480 kumpf 1.14 //
481 // Get the difference between the two times
482 //
|
483 kumpf 1.20 differenceInSeconds = (Sint64) difftime( timeFinishInSeconds, timeStartInSeconds );
|
484 kumpf 1.14
|
485 kumpf 1.26 //
486 // ATTN-CAKG-P1-20020816: struct tm and difftime don't handle microseconds
487 //
488 Sint64 differenceInMicroseconds = differenceInSeconds * 1000000;
489 startDateTimeCString = startTime._rep->data;
490 finishDateTimeCString = finishTime._rep->data;
491 char dateBuffer [9];
492 sprintf (dateBuffer, "%6.6s", startDateTimeCString + 15);
493 Uint32 startDateMicroseconds = atoi (dateBuffer);
494 sprintf (dateBuffer, "%6.6s", finishDateTimeCString + 15);
495 Uint32 finishDateMicroseconds = atoi (dateBuffer);
496 (finishDateMicroseconds > startDateMicroseconds) ?
497 differenceInMicroseconds +=
498 (finishDateMicroseconds - startDateMicroseconds) :
499 differenceInMicroseconds -=
500 (startDateMicroseconds - finishDateMicroseconds);
501
502 return differenceInMicroseconds;
|
503 mike 1.10 }
504
505 PEGASUS_NAMESPACE_END
|