1 | /* |
2 | * Legal Notice |
3 | * |
4 | * This document and associated source code (the "Work") is a part of a |
5 | * benchmark specification maintained by the TPC. |
6 | * |
7 | * The TPC reserves all right, title, and interest to the Work as provided |
8 | * under U.S. and international laws, including without limitation all patent |
9 | * and trademark rights therein. |
10 | * |
11 | * No Warranty |
12 | * |
13 | * 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION |
14 | * CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE |
15 | * AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER |
16 | * WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, |
17 | * INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES, |
18 | * DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR |
19 | * PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF |
20 | * WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE. |
21 | * ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT, |
22 | * QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT |
23 | * WITH REGARD TO THE WORK. |
24 | * 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO |
25 | * ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE |
26 | * COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS |
27 | * OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT, |
28 | * INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY, |
29 | * OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT |
30 | * RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD |
31 | * ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. |
32 | * |
33 | * Contributors |
34 | * - Charles Levine |
35 | */ |
36 | |
37 | #include "utilities/DateTime.h" |
38 | |
39 | #include <stdio.h> |
40 | #include <stdexcept> |
41 | #include <chrono> |
42 | |
43 | // DJ: perhaps all unixes need this so maybe we want #ifndef WIN32 or something |
44 | // like that? |
45 | #if (__unix) || (_AIX) |
46 | #include <sys/time.h> // for gettimeofday |
47 | #endif |
48 | |
49 | using namespace TPCE; |
50 | |
51 | // Initialize static const member arrays. |
52 | const INT32 CDateTime::monthArray[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
53 | const INT32 CDateTime::monthArrayLY[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
54 | const INT32 CDateTime::cumulativeMonthArray[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; |
55 | |
56 | bool CDateTime::IsLeapYear(INT32 year) { |
57 | if ((year % 4) != 0) // only years which are multiples of 4 can be leap years |
58 | { |
59 | return false; |
60 | } |
61 | |
62 | if ((year % 400) == 0) // years divisible by 400 are leap years |
63 | { |
64 | return true; |
65 | } |
66 | |
67 | if ((year % 100) == 0) // years divisible by 100 but not 400 are not leap years |
68 | { |
69 | return false; |
70 | } |
71 | |
72 | // must be a leap year if you get here |
73 | return true; |
74 | } |
75 | |
76 | // Checks whether the date/time is valid. |
77 | bool CDateTime::IsValid(INT32 year, INT32 month, INT32 day, INT32 hour, INT32 minute, INT32 second, INT32 msec) { |
78 | // check all values that have static, absolute bounds |
79 | if (hour < minValidHour || maxValidHour < hour || minute < minValidMinute || maxValidMinute < minute || |
80 | second < minValidSecond || maxValidSecond < second || msec < minValidMilliSecond || |
81 | maxValidMilliSecond < msec || year < minValidYear || maxValidYear < year || month < minValidMonth || |
82 | maxValidMonth < month || day < minValidDay) { |
83 | return false; |
84 | } |
85 | |
86 | // check the day of the month |
87 | // optimize for common case. if check passes, we're done |
88 | if (day <= monthArray[month - 1]) { |
89 | return true; |
90 | } |
91 | |
92 | // Only one possibility left -- February 29th |
93 | // Feb 29th valid only if a leap year; invalid otherwise |
94 | if ((month == 2) && (day == 29)) { |
95 | return IsLeapYear(year); |
96 | } |
97 | |
98 | // exhausted all possibilities; can't be valid |
99 | return false; |
100 | } |
101 | |
102 | // Validate the specified date/time and throw an out_of_range exception if it |
103 | // isn't valid. |
104 | void CDateTime::Validate(INT32 year, INT32 month, INT32 day, INT32 hour, INT32 minute, INT32 second, INT32 msec) { |
105 | if (!IsValid(year, month, day, hour, minute, second, msec)) { |
106 | std::ostringstream msg; |
107 | msg << "The specified Date/Time is not valid." ; |
108 | throw std::out_of_range(msg.str()); |
109 | } |
110 | } |
111 | |
112 | // Validate the specified day number and throw an out_of_range exception if it |
113 | // isn't valid. |
114 | void CDateTime::Validate(INT32 dayNumber) { |
115 | if ((dayNumber < minValidDayNumber) || (CalculateDayNumber(maxValidYear, maxValidMonth, maxValidDay) < dayNumber)) { |
116 | std::ostringstream msg; |
117 | msg << "The specified day-number is not valid." ; |
118 | throw std::out_of_range(msg.str()); |
119 | } |
120 | } |
121 | |
122 | // Validate a day-number/msec pair. |
123 | void CDateTime::Validate(INT32 dayNumber, INT32 msecSoFarToday) { |
124 | if ((msecSoFarToday < minValidMilliSecond) || (maxValidMilliSecond < msecSoFarToday) || |
125 | (dayNumber < minValidDayNumber) || (CalculateDayNumber(maxValidYear, maxValidMonth, maxValidDay) < dayNumber)) { |
126 | std::ostringstream msg; |
127 | msg << "The specified (day-number, msec) pair is not valid." ; |
128 | throw std::out_of_range(msg.str()); |
129 | } |
130 | } |
131 | |
132 | // Computes the number of days since Jan 1, 0001. (Year 1 AD) |
133 | // 1-Jan-0001 = 0 |
134 | INT32 CDateTime::CalculateDayNumber(INT32 yr, INT32 mm, INT32 dd) { |
135 | // compute day of year |
136 | INT32 jd = cumulativeMonthArray[mm - 1] + dd - 1; |
137 | |
138 | // adjust day of year if this is a leap year and it is after February |
139 | if ((mm > 2) && IsLeapYear(yr)) { |
140 | jd++; |
141 | } |
142 | |
143 | // compute number of days from 1/1/0001 to beginning of present year |
144 | yr--; // start counting from year 1 AD (1-based instead of 0-based) |
145 | jd += yr / 400 * dy400; |
146 | yr %= 400; |
147 | jd += yr / 100 * dy100; |
148 | yr %= 100; |
149 | jd += yr / 4 * dy4; |
150 | yr %= 4; |
151 | jd += yr * dy1; |
152 | |
153 | return jd; |
154 | } |
155 | |
156 | INT32 CDateTime::YMDtoDayno(INT32 yr, INT32 mm, INT32 dd) { |
157 | // Validate year, month and day (use known safe values for hours - |
158 | // milliseconds). |
159 | Validate(yr, mm, dd, minValidHour, minValidMinute, minValidSecond, minValidMilliSecond); |
160 | |
161 | return CalculateDayNumber(yr, mm, dd); |
162 | } |
163 | |
164 | // returns text representation of DateTime |
165 | // the style argument is interpreted as a two digit field, where the first digit |
166 | // (in the tens place) is the date format and the second digit (in the ones |
167 | // place) is the time format. |
168 | // |
169 | // The following formats are provided: |
170 | // STYLE DATE TIME |
171 | // ----- ---- ---- |
172 | // 0 <omit> <omit> |
173 | // 1 YYYY-MM-DD HH:MM:SS (24hr) |
174 | // 2 MM/DD/YY HH:MM:SS.mmm (24hr) |
175 | // 3 MM/DD/YYYY HH:MM (24hr) |
176 | // 4 DD-MON-YYYY HH:MM:SS [AM|PM] |
177 | // 5 DD-MON-YY HH:MM:SS.mmm [AM|PM] |
178 | // 6 MM-DD-YY HH:MM [AM|PM] |
179 | // 7 MON DD YYYY |
180 | // 8 Month DD, YYYY |
181 | // |
182 | char *CDateTime::ToStr(INT32 style = 11) { |
183 | static const char *szMonthsShort[] = {"JAN" , "FEB" , "MAR" , "APR" , "MAY" , "JUN" , |
184 | "JUL" , "AUG" , "SEP" , "OCT" , "NOV" , "DEC" }; |
185 | static const char *szMonthsFull[] = {"January" , "February" , "March" , "April" , "May" , "June" , |
186 | "July" , "August" , "September" , "October" , "November" , "December" }; |
187 | static const char *szAmPm[] = {"AM" , "PM" }; |
188 | // the following array is used to map from 24-hour to 12-hour time |
189 | static const INT32 iHr12[] = {12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; |
190 | |
191 | INT32 year, month, day, hour, minute, second, msec; |
192 | INT32 p = 0; |
193 | static const INT32 iMaxStrLen = 40; |
194 | |
195 | if (m_szText == NULL) |
196 | m_szText = new char[iMaxStrLen]; |
197 | m_szText[0] = '\0'; |
198 | |
199 | GetYMDHMS(&year, &month, &day, &hour, &minute, &second, &msec); |
200 | |
201 | size_t lengthTotal = iMaxStrLen; |
202 | char *pszText = m_szText; |
203 | |
204 | // DATE portion |
205 | switch (style / 10) { |
206 | case 1: |
207 | // YYYY-MM-DD |
208 | p = snprintf(pszText, lengthTotal, "%04d-%02d-%02d " , year, month, day); |
209 | break; |
210 | case 2: |
211 | // MM/DD/YY |
212 | p = snprintf(pszText, lengthTotal, "%02d/%02d/%02d " , month, day, year % 100); |
213 | break; |
214 | case 3: |
215 | // MM/DD/YYYY |
216 | p = snprintf(pszText, lengthTotal, "%02d/%02d/%04d " , month, day, year); |
217 | break; |
218 | case 4: |
219 | // DD-MON-YYYY |
220 | p = snprintf(pszText, lengthTotal, "%02d-%s-%04d " , day, szMonthsShort[month - 1], year); |
221 | break; |
222 | case 5: |
223 | // DD-MON-YY |
224 | p = snprintf(pszText, lengthTotal, "%02d-%s-%02d " , day, szMonthsShort[month - 1], year % 100); |
225 | break; |
226 | case 6: |
227 | // MM-DD-YY |
228 | p = snprintf(pszText, lengthTotal, "%02d-%02d-%02d " , month, day, year % 100); |
229 | break; |
230 | case 7: |
231 | // MON DD YYYY |
232 | p = snprintf(pszText, lengthTotal, "%s %02d %04d " , szMonthsShort[month - 1], day, year); |
233 | break; |
234 | case 8: |
235 | // Month DD, YYYY |
236 | p = snprintf(pszText, lengthTotal, "%s %02d, %04d " , szMonthsFull[month - 1], day, year); |
237 | break; |
238 | } |
239 | |
240 | size_t lengthRemaining = lengthTotal - p; |
241 | pszText = m_szText + (char)p; |
242 | |
243 | // TIME portion |
244 | switch (style % 10) { |
245 | case 1: |
246 | // HH:MM:SS (24hr) |
247 | p += snprintf(pszText, lengthRemaining, "%02d:%02d:%02d" , hour, minute, second); |
248 | break; |
249 | case 2: |
250 | // HH:MM:SS.mmm (24hr) |
251 | p += snprintf(pszText, lengthRemaining, "%02d:%02d:%02d.%03d" , hour, minute, second, msec); |
252 | break; |
253 | case 3: |
254 | // HH:MM (24hr) |
255 | p += snprintf(pszText, lengthRemaining, "%02d:%02d" , hour, minute); |
256 | break; |
257 | case 4: |
258 | // HH:MM:SS [AM|PM] |
259 | p += snprintf(pszText, lengthRemaining, "%02d:%02d:%02d %s" , iHr12[hour], minute, second, szAmPm[hour / 12]); |
260 | break; |
261 | case 5: |
262 | // HHH:MM:SS.mmm [AM|PM] |
263 | p += snprintf(pszText, lengthRemaining, "%02d:%02d:%02d.%03d %s" , iHr12[hour], minute, second, msec, |
264 | szAmPm[hour / 12]); |
265 | break; |
266 | case 6: |
267 | // HH:MM [AM|PM] |
268 | p += snprintf(pszText, lengthRemaining, "%02d:%02d %s" , iHr12[hour], minute, szAmPm[hour / 12]); |
269 | break; |
270 | } |
271 | |
272 | // trim trailing blank, if there is one. |
273 | if (p > 0 && m_szText[p - 1] == ' ') |
274 | m_szText[p - 1] = '\0'; |
275 | |
276 | return m_szText; |
277 | } |
278 | |
279 | // set to current local time |
280 | CDateTime::CDateTime(void) { |
281 | m_szText = NULL; |
282 | Set(); |
283 | } |
284 | |
285 | CDateTime::CDateTime(INT32 dayno) { |
286 | Validate(dayno); |
287 | m_szText = NULL; |
288 | m_dayno = dayno; |
289 | m_msec = 0; |
290 | } |
291 | |
292 | CDateTime::CDateTime(INT32 year, INT32 month, INT32 day) { |
293 | Validate(year, month, day, minValidHour, minValidMinute, minValidSecond, minValidMilliSecond); |
294 | m_dayno = CalculateDayNumber(year, month, day); |
295 | m_szText = NULL; |
296 | m_msec = 0; |
297 | } |
298 | |
299 | // Copy constructor |
300 | CDateTime::CDateTime(const CDateTime &dt) { |
301 | // Assume source is valid. |
302 | // Validate( dt.m_dayno, dt.m_msec ); |
303 | m_dayno = dt.m_dayno; |
304 | m_msec = dt.m_msec; |
305 | m_szText = NULL; |
306 | } |
307 | |
308 | CDateTime::~CDateTime(void) { |
309 | if (m_szText) |
310 | delete[] m_szText; |
311 | } |
312 | |
313 | CDateTime::CDateTime(INT32 year, INT32 month, INT32 day, INT32 hour, INT32 minute, INT32 second, INT32 msec) { |
314 | // Validate specified date/time |
315 | Validate(year, month, day, hour, minute, second, msec); |
316 | |
317 | m_szText = NULL; |
318 | m_dayno = CalculateDayNumber(year, month, day); |
319 | m_msec = ((hour * MinutesPerHour + minute) * SecondsPerMinute + second) * MsPerSecond + msec; |
320 | } |
321 | |
322 | CDateTime::CDateTime(TPCE::TIMESTAMP_STRUCT *ts) { |
323 | Validate(ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second, ts->fraction / 1000000); |
324 | |
325 | m_szText = NULL; |
326 | m_dayno = CalculateDayNumber(ts->year, ts->month, ts->day); |
327 | m_msec = ((ts->hour * MinutesPerHour + ts->minute) * SecondsPerMinute + ts->second) * MsPerSecond + |
328 | ts->fraction / 1000000; |
329 | } |
330 | |
331 | // set to current local time |
332 | void CDateTime::Set(void) { |
333 | // assert(0); // why is this necessary? |
334 | // //UNIX-specific code to get the current time with 1ms resolution |
335 | // struct timeval tv; |
336 | // struct tm ltr; |
337 | // int secs; |
338 | // gettimeofday(&tv, NULL); |
339 | // struct tm* lt = localtime_r(&tv.tv_sec, <r); //expand into |
340 | // year/month/day/... |
341 | // // NOTE: 1 is added to tm_mon because it is 0 based, but |
342 | // CalculateDayNumber expects it to |
343 | // // be 1 based. |
344 | // m_dayno = CalculateDayNumber(lt->tm_year+1900, lt->tm_mon+1, |
345 | // lt->tm_mday); // tm_year is based on 1900, not 0. |
346 | |
347 | // secs = (lt->tm_hour * MinutesPerHour + lt->tm_min)*SecondsPerMinute + |
348 | // lt->tm_sec; |
349 | // m_msec = static_cast<INT32>((long)secs * MsPerSecond + tv.tv_usec / |
350 | // 1000); |
351 | } |
352 | |
353 | void CDateTime::Set(INT32 dayno) { |
354 | Validate(dayno); |
355 | m_dayno = dayno; |
356 | m_msec = 0; |
357 | } |
358 | |
359 | void CDateTime::Set(INT32 year, INT32 month, INT32 day) { |
360 | Validate(year, month, day, minValidHour, minValidMinute, minValidSecond, minValidMilliSecond); |
361 | |
362 | m_dayno = CalculateDayNumber(year, month, day); |
363 | m_msec = 0; |
364 | } |
365 | |
366 | void CDateTime::Set(INT32 hour, INT32 minute, INT32 second, INT32 msec) { |
367 | Validate(minValidYear, minValidMonth, minValidDay, hour, minute, second, msec); |
368 | |
369 | m_msec = ((hour * MinutesPerHour + minute) * SecondsPerMinute + second) * MsPerSecond + msec; |
370 | } |
371 | |
372 | void CDateTime::Set(INT32 year, INT32 month, INT32 day, INT32 hour, INT32 minute, INT32 second, INT32 msec) { |
373 | Validate(year, month, day, hour, minute, second, msec); |
374 | |
375 | m_dayno = CalculateDayNumber(year, month, day); |
376 | m_msec = ((hour * MinutesPerHour + minute) * SecondsPerMinute + second) * MsPerSecond + msec; |
377 | } |
378 | |
379 | // DaynoToYMD converts a day index to |
380 | // its corresponding calendar value (mm/dd/yr). The valid range for days |
381 | // is { 0 .. ~3.65M } for dates from 1-Jan-0001 to 31-Dec-9999. |
382 | void CDateTime::GetYMD(INT32 *year, INT32 *month, INT32 *day) { |
383 | INT32 dayno = m_dayno; |
384 | |
385 | // local variables |
386 | INT32 y, m; |
387 | |
388 | y = 1; // based on year 1 AD |
389 | y += (dayno / dy400) * 400; |
390 | dayno %= dy400; |
391 | if (dayno == dy400 - 1) // special case for last day of 400-year leap-year |
392 | { |
393 | y += 399; |
394 | dayno -= 3 * dy100 + 24 * dy4 + 3 * dy1; |
395 | } else { |
396 | y += (dayno / dy100) * 100; |
397 | dayno %= dy100; |
398 | y += (dayno / dy4) * 4; |
399 | dayno %= dy4; |
400 | if (dayno == dy4 - 1) // special case for last day of 4-year leap-year |
401 | { |
402 | y += 3; |
403 | dayno -= 3 * dy1; |
404 | } else { |
405 | y += dayno / dy1; |
406 | dayno %= dy1; |
407 | } |
408 | } |
409 | |
410 | m = 1; |
411 | dayno++; |
412 | if (IsLeapYear(y)) { |
413 | while (dayno > monthArrayLY[m - 1]) { |
414 | dayno -= monthArrayLY[m - 1]; |
415 | m++; |
416 | } |
417 | } else { |
418 | while (dayno > monthArray[m - 1]) { |
419 | dayno -= monthArray[m - 1]; |
420 | m++; |
421 | } |
422 | } |
423 | |
424 | *year = y; |
425 | *month = m; |
426 | *day = dayno; |
427 | } |
428 | |
429 | void CDateTime::GetYMDHMS(INT32 *year, INT32 *month, INT32 *day, INT32 *hour, INT32 *minute, INT32 *second, |
430 | INT32 *msec) { |
431 | GetYMD(year, month, day); |
432 | GetHMS(hour, minute, second, msec); |
433 | } |
434 | |
435 | void CDateTime::GetHMS(INT32 *hour, INT32 *minute, INT32 *second, INT32 *msec) { |
436 | INT32 ms = m_msec; |
437 | |
438 | *msec = ms % MsPerSecond; |
439 | ms /= MsPerSecond; |
440 | *second = ms % SecondsPerMinute; |
441 | ms /= SecondsPerMinute; |
442 | *minute = ms % MinutesPerHour; |
443 | *hour = ms / MinutesPerHour; |
444 | } |
445 | |
446 | void CDateTime::GetTimeStamp(TPCE::TIMESTAMP_STRUCT *ts) { |
447 | INT32 year, month, day, hour, minute, second, msec; |
448 | |
449 | GetYMDHMS(&year, &month, &day, &hour, &minute, &second, &msec); |
450 | ts->year = (INT16)year; |
451 | ts->month = (UINT16)month; |
452 | ts->day = (UINT16)day; |
453 | ts->hour = (UINT16)hour; |
454 | ts->minute = (UINT16)minute; |
455 | ts->second = (UINT16)second; |
456 | ts->fraction = (UINT32)msec * 1000000; // because "fraction" is 1/billion'th of a second |
457 | } |
458 | |
459 | #ifdef COMPILE_ODBC_LOAD |
460 | static const INT32 dayno_1Jan1900 = CDateTime::YMDtoDayno(1900, 1, 1); |
461 | |
462 | void CDateTime::GetDBDATETIME(DBDATETIME *dt) { |
463 | dt->dtdays = m_dayno - dayno_1Jan1900; |
464 | dt->dttime = m_msec * 3 / 10; |
465 | } |
466 | #endif // COMPILE_ODBC_LOAD |
467 | |
468 | void CDateTime::Add(INT32 days, INT32 msec, bool adjust_weekend /* =false */) { |
469 | if (adjust_weekend) { |
470 | days = ((days / DaysPerWorkWeek) * DaysPerWeek) + (days % DaysPerWorkWeek); |
471 | } |
472 | |
473 | m_dayno += days; |
474 | |
475 | m_msec += msec; |
476 | m_dayno += m_msec / MsPerDay; |
477 | m_msec %= MsPerDay; |
478 | if (m_msec < 0) { |
479 | m_dayno--; |
480 | m_msec += MsPerDay; |
481 | } |
482 | } |
483 | void CDateTime::AddMinutes(INT32 Minutes) { |
484 | Add(0, Minutes * SecondsPerMinute * MsPerSecond); |
485 | } |
486 | void CDateTime::AddWorkMs(INT64 WorkMs) { |
487 | INT32 WorkDays = (INT32)(WorkMs / (INT64)MsPerWorkDay); |
488 | Add(WorkDays, (INT32)(WorkMs % MsPerWorkDay), true); |
489 | } |
490 | bool CDateTime::operator<(const CDateTime &dt) { |
491 | return (m_dayno == dt.m_dayno) ? (m_msec < dt.m_msec) : (m_dayno < dt.m_dayno); |
492 | } |
493 | |
494 | bool CDateTime::operator<=(const CDateTime &dt) { |
495 | return (m_dayno == dt.m_dayno) ? (m_msec <= dt.m_msec) : (m_dayno <= dt.m_dayno); |
496 | } |
497 | |
498 | namespace TPCE { |
499 | |
500 | // Need const reference left argument for greater<CDateTime> comparison function |
501 | bool operator>(const CDateTime &l_dt, const CDateTime &r_dt) { |
502 | return (l_dt.m_dayno == r_dt.m_dayno) ? (l_dt.m_msec > r_dt.m_msec) : (l_dt.m_dayno > r_dt.m_dayno); |
503 | } |
504 | |
505 | } // namespace TPCE |
506 | |
507 | bool CDateTime::operator>=(const CDateTime &dt) { |
508 | return (m_dayno == dt.m_dayno) ? (m_msec >= dt.m_msec) : (m_dayno >= dt.m_dayno); |
509 | } |
510 | |
511 | bool CDateTime::operator==(const CDateTime &dt) { |
512 | return m_dayno == dt.m_dayno ? m_msec == dt.m_msec : false; |
513 | } |
514 | |
515 | // compute the difference between two DateTimes; |
516 | // result in seconds |
517 | double CDateTime::operator-(const CDateTime &dt) { |
518 | double dSecs; |
519 | dSecs = (double)((m_dayno - dt.m_dayno) * SecondsPerMinute * MinutesPerHour * HoursPerDay); |
520 | dSecs += (double)(m_msec - dt.m_msec) / MsPerSecondDivisor; |
521 | return dSecs; |
522 | } |
523 | |
524 | INT32 CDateTime::DiffInMilliSeconds(const CDateTime &BaseTime) { |
525 | INT32 mSecs; |
526 | mSecs = (m_dayno - BaseTime.m_dayno) * MsPerSecond * SecondsPerMinute * MinutesPerHour * HoursPerDay; |
527 | mSecs += (m_msec - BaseTime.m_msec); |
528 | return mSecs; |
529 | } |
530 | |
531 | INT32 CDateTime::DiffInMilliSeconds(CDateTime *pBaseTime) { |
532 | INT32 mSecs; |
533 | mSecs = (m_dayno - pBaseTime->m_dayno) * MsPerSecond * SecondsPerMinute * MinutesPerHour * HoursPerDay; |
534 | mSecs += (m_msec - pBaseTime->m_msec); |
535 | return mSecs; |
536 | } |
537 | |
538 | CDateTime &CDateTime::operator=(const CDateTime &dt) { |
539 | // Assume source is valid. |
540 | // Validate( dt.m_dayno, dt.m_msec ); |
541 | m_dayno = dt.m_dayno; |
542 | m_msec = dt.m_msec; |
543 | |
544 | return *this; |
545 | } |
546 | |
547 | CDateTime &CDateTime::operator+=(const CDateTime &dt) { |
548 | Add(dt.m_dayno, dt.m_msec); |
549 | |
550 | return *this; |
551 | } |
552 | |