00001
00017 #include "copyright.h"
00018 #include "autoconf.h"
00019 #include "config.h"
00020 #include "externs.h"
00021
00022
00023
00024 #include <time.h>
00025
00026 #include "timeutil.h"
00027 #include "stringutil.h"
00028
00029 CMuxAlarm MuxAlarm;
00030
00031 #ifdef SMALLEST_INT_GTE_NEG_QUOTIENT
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 int iMod(int x, int y)
00055 {
00056 if (y < 0)
00057 {
00058 if (x <= 0)
00059 {
00060 return x % y;
00061 }
00062 else
00063 {
00064 return ((x-1) % y) + y + 1;
00065 }
00066 }
00067 else
00068 {
00069 if (x < 0)
00070 {
00071 return ((x+1) % y) + y - 1;
00072 }
00073 else
00074 {
00075 return x % y;
00076 }
00077 }
00078 }
00079
00080 INT64 i64Mod(INT64 x, INT64 y)
00081 {
00082 if (y < 0)
00083 {
00084 if (x <= 0)
00085 {
00086 return x % y;
00087 }
00088 else
00089 {
00090 return ((x-1) % y) + y + 1;
00091 }
00092 }
00093 else
00094 {
00095 if (x < 0)
00096 {
00097 return ((x+1) % y) + y - 1;
00098 }
00099 else
00100 {
00101 return x % y;
00102 }
00103 }
00104 }
00105
00106
00107
00108 DCL_INLINE int iRemainder(int x, int y)
00109 {
00110 return x % y;
00111 }
00112
00113
00114
00115 DCL_INLINE int iDivision(int x, int y)
00116 {
00117 return x / y;
00118 }
00119
00120
00121
00122 static int iFloorDivision(int x, int y)
00123 {
00124 if (y < 0)
00125 {
00126 if (x <= 0)
00127 {
00128 return x / y;
00129 }
00130 else
00131 {
00132 return (x - y - 1) / y;
00133 }
00134 }
00135 else
00136 {
00137 if (x < 0)
00138 {
00139 return (x - y + 1) / y;
00140 }
00141 else
00142 {
00143 return x / y;
00144 }
00145 }
00146 }
00147
00148 INT64 i64FloorDivision(INT64 x, INT64 y)
00149 {
00150 if (y < 0)
00151 {
00152 if (x <= 0)
00153 {
00154 return x / y;
00155 }
00156 else
00157 {
00158 return (x - y - 1) / y;
00159 }
00160 }
00161 else
00162 {
00163 if (x < 0)
00164 {
00165 return (x - y + 1) / y;
00166 }
00167 else
00168 {
00169 return x / y;
00170 }
00171 }
00172 }
00173
00174 int iFloorDivisionMod(int x, int y, int *piMod)
00175 {
00176 if (y < 0)
00177 {
00178 if (x <= 0)
00179 {
00180 *piMod = x % y;
00181 return x / y;
00182 }
00183 else
00184 {
00185 *piMod = ((x-1) % y) + y + 1;
00186 return (x - y - 1) / y;
00187 }
00188 }
00189 else
00190 {
00191 if (x < 0)
00192 {
00193 *piMod = ((x+1) % y) + y - 1;
00194 return (x - y + 1) / y;
00195 }
00196 else
00197 {
00198 *piMod = x % y;
00199 return x / y;
00200 }
00201 }
00202 }
00203
00204 static INT64 i64FloorDivisionMod(INT64 x, INT64 y, INT64 *piMod)
00205 {
00206 if (y < 0)
00207 {
00208 if (x <= 0)
00209 {
00210 *piMod = x % y;
00211 return x / y;
00212 }
00213 else
00214 {
00215 *piMod = ((x-1) % y) + y + 1;
00216 return (x - y - 1) / y;
00217 }
00218 }
00219 else
00220 {
00221 if (x < 0)
00222 {
00223 *piMod = ((x+1) % y) + y - 1;
00224 return (x - y + 1) / y;
00225 }
00226 else
00227 {
00228 *piMod = x % y;
00229 return x / y;
00230 }
00231 }
00232 }
00233
00234 #if 0
00235 int iCeilingDivision(int x, int y)
00236 {
00237 if (x < 0)
00238 {
00239 return x / y;
00240 }
00241 else
00242 {
00243 return (x + y - 1) / y;
00244 }
00245 }
00246
00247 INT64 i64CeilingDivision(INT64 x, INT64 y)
00248 {
00249 if (x < 0)
00250 {
00251 return x / y;
00252 }
00253 else
00254 {
00255 return (x + y - 1) / y;
00256 }
00257 }
00258 #endif // 0
00259
00260 #else // LARGEST_INT_LTE_NEG_QUOTIENT
00261
00262
00263
00264 int DCL_INLINE iMod(int x, int y)
00265 {
00266 return x % y;
00267 }
00268
00269
00270
00271 int iRemainder(int x, int y)
00272 {
00273 if (y < 0)
00274 {
00275 if (x <= 0)
00276 {
00277 return x % y;
00278 }
00279 else
00280 {
00281 return ((x+1) % y) - y - 1;
00282 }
00283 }
00284 else
00285 {
00286 if (x < 0)
00287 {
00288 return ((x-1) % y) - y + 1;
00289 }
00290 else
00291 {
00292 return x % y;
00293 }
00294 }
00295 }
00296
00297 INT64 i64Remainder(INT64 x, INT64 y)
00298 {
00299 if (y < 0)
00300 {
00301 if (x <= 0)
00302 {
00303 return x % y;
00304 }
00305 else
00306 {
00307 return ((x+1) % y) - y - 1;
00308 }
00309 }
00310 else
00311 {
00312 if (x < 0)
00313 {
00314 return ((x-1) % y) - y + 1;
00315 }
00316 else
00317 {
00318 return x % y;
00319 }
00320 }
00321 }
00322
00323
00324
00325 int iDivision(int x, int y)
00326 {
00327 if (y < 0)
00328 {
00329 if (x <= 0)
00330 {
00331 return x / y;
00332 }
00333 else
00334 {
00335 return (x + y + 1) / y;
00336 }
00337 }
00338 else
00339 {
00340 if (x < 0)
00341 {
00342 return (x + y - 1) / y;
00343 }
00344 else
00345 {
00346 return x / y;
00347 }
00348 }
00349 }
00350
00351 INT64 i64Division(INT64 x, INT64 y)
00352 {
00353 if (y < 0)
00354 {
00355 if (x <= 0)
00356 {
00357 return x / y;
00358 }
00359 else
00360 {
00361 return (x + y + 1) / y;
00362 }
00363 }
00364 else
00365 {
00366 if (x < 0)
00367 {
00368 return (x + y - 1) / y;
00369 }
00370 else
00371 {
00372 return x / y;
00373 }
00374 }
00375 }
00376
00377
00378
00379 int DCL_INLINE iFloorDivision(int x, int y)
00380 {
00381 return x / y;
00382 }
00383
00384 INT64 DCL_INLINE i64FloorDivisionMod(INT64 x, INT64 y, INT64 *piMod)
00385 {
00386 *piMod = x % y;
00387 return x / y;
00388 }
00389 #endif // LARGEST_INT_LTE_NEG_QUOTIENT
00390
00391 #if 0
00392 static int iModAdjusted(int x, int y)
00393 {
00394 return iMod(x - 1, y) + 1;
00395 }
00396
00397 static INT64 i64ModAdjusted(INT64 x, INT64 y)
00398 {
00399 return i64Mod(x - 1, y) + 1;
00400 }
00401 #endif // 0
00402
00403 #ifdef WIN32
00404 const INT64 FACTOR_100NS_PER_SECOND = 10000000i64;
00405 #else // WIN32
00406 const INT64 FACTOR_100NS_PER_SECOND = 10000000ull;
00407 #endif // WIN32
00408 const INT64 FACTOR_100NS_PER_MINUTE = FACTOR_100NS_PER_SECOND*60;
00409 const INT64 FACTOR_100NS_PER_HOUR = FACTOR_100NS_PER_MINUTE*60;
00410 const INT64 FACTOR_100NS_PER_DAY = FACTOR_100NS_PER_HOUR*24;
00411 const INT64 FACTOR_100NS_PER_WEEK = FACTOR_100NS_PER_DAY*7;
00412
00413 int CLinearTimeAbsolute::m_nCount = 0;
00414 char CLinearTimeAbsolute::m_Buffer[204];
00415 char CLinearTimeDelta::m_Buffer[204];
00416
00417 static void GetUTCLinearTime(INT64 *plt);
00418
00419 bool operator<(const CLinearTimeAbsolute& lta, const CLinearTimeAbsolute& ltb)
00420 {
00421 return lta.m_tAbsolute < ltb.m_tAbsolute;
00422 }
00423
00424 bool operator>(const CLinearTimeAbsolute& lta, const CLinearTimeAbsolute& ltb)
00425 {
00426 return lta.m_tAbsolute > ltb.m_tAbsolute;
00427 }
00428
00429 bool operator==(const CLinearTimeAbsolute& lta, const CLinearTimeAbsolute& ltb)
00430 {
00431 return lta.m_tAbsolute == ltb.m_tAbsolute;
00432 }
00433
00434 bool operator==(const CLinearTimeDelta& lta, const CLinearTimeDelta& ltb)
00435 {
00436 return lta.m_tDelta == ltb.m_tDelta;
00437 }
00438
00439 bool operator!=(const CLinearTimeDelta& lta, const CLinearTimeDelta& ltb)
00440 {
00441 return lta.m_tDelta != ltb.m_tDelta;
00442 }
00443
00444 bool operator<=(const CLinearTimeDelta& lta, const CLinearTimeDelta& ltb)
00445 {
00446 return lta.m_tDelta <= ltb.m_tDelta;
00447 }
00448
00449 bool operator<=(const CLinearTimeAbsolute& lta, const CLinearTimeAbsolute& ltb)
00450 {
00451 return lta.m_tAbsolute <= ltb.m_tAbsolute;
00452 }
00453
00454 CLinearTimeAbsolute operator-(const CLinearTimeAbsolute& lta, const CLinearTimeDelta& ltd)
00455 {
00456 CLinearTimeAbsolute t;
00457 t.m_tAbsolute = lta.m_tAbsolute - ltd.m_tDelta;
00458 return t;
00459 }
00460
00461 CLinearTimeAbsolute::CLinearTimeAbsolute(const CLinearTimeAbsolute& ltaOrigin, const CLinearTimeDelta& ltdOffset)
00462 {
00463 m_tAbsolute = ltaOrigin.m_tAbsolute + ltdOffset.m_tDelta;
00464 }
00465
00466 static bool ParseFractionalSecondsString(INT64 &i64, char *str)
00467 {
00468 bool bMinus = false;
00469
00470 i64 = 0;
00471
00472 bool bGotOne;
00473
00474
00475
00476 while (mux_isspace(*str))
00477 {
00478 str++;
00479 }
00480
00481
00482
00483 if (*str == '-')
00484 {
00485 bMinus = true;
00486 str++;
00487
00488
00489
00490 if (!*str)
00491 {
00492 return false;
00493 }
00494 }
00495
00496
00497
00498 bGotOne = false;
00499 char *pIntegerStart = str;
00500 if (mux_isdigit(*str))
00501 {
00502 bGotOne = true;
00503 str++;
00504 }
00505
00506
00507
00508 while (mux_isdigit(*str))
00509 {
00510 str++;
00511 }
00512 char *pIntegerEnd = str;
00513
00514
00515
00516 if (*str == '.')
00517 {
00518 str++;
00519 }
00520
00521
00522
00523 char *pFractionalStart = str;
00524 if (mux_isdigit(*str))
00525 {
00526 bGotOne = true;
00527 str++;
00528 }
00529
00530
00531
00532 while (mux_isdigit(*str))
00533 {
00534 str++;
00535 }
00536 char *pFractionalEnd = str;
00537
00538
00539
00540 while (mux_isspace(*str))
00541 {
00542 str++;
00543 }
00544
00545 if (*str || !bGotOne)
00546 {
00547 return false;
00548 }
00549
00550 #define PFSS_PRECISION 7
00551 char aBuffer[64];
00552 size_t nBufferAvailable = sizeof(aBuffer) - PFSS_PRECISION - 1;
00553 char *p = aBuffer;
00554
00555
00556
00557 if (bMinus)
00558 {
00559 *p++ = '-';
00560 nBufferAvailable--;
00561 }
00562
00563
00564
00565 bool bOverUnderflow = false;
00566 size_t n = pIntegerEnd - pIntegerStart;
00567 if (n > 0)
00568 {
00569 if (n > nBufferAvailable)
00570 {
00571 bOverUnderflow = true;
00572 n = nBufferAvailable;
00573 }
00574 memcpy(p, pIntegerStart, n);
00575 p += n;
00576 nBufferAvailable -= n;
00577 }
00578
00579
00580
00581 n = pFractionalEnd - pFractionalStart;
00582 if (n > 0)
00583 {
00584 if (n > PFSS_PRECISION)
00585 {
00586 n = PFSS_PRECISION;
00587 }
00588 memcpy(p, pFractionalStart, n);
00589 p += n;
00590 nBufferAvailable -= n;
00591 }
00592
00593
00594
00595 n = PFSS_PRECISION - n;
00596 if (n > 0)
00597 {
00598 memset(p, '0', n);
00599 p += n;
00600 }
00601 *p++ = '\0';
00602
00603 if (bOverUnderflow)
00604 {
00605 if (bMinus)
00606 {
00607 i64 = INT64_MIN_VALUE;
00608 }
00609 else
00610 {
00611 i64 = INT64_MAX_VALUE;
00612 }
00613 }
00614 else
00615 {
00616 i64 = mux_atoi64(aBuffer);
00617 }
00618 return true;
00619 }
00620
00621 static void ConvertToSecondsString(char *buffer, INT64 n64, int nFracDigits)
00622 {
00623 INT64 Leftover;
00624 INT64 lt = i64FloorDivisionMod(n64, FACTOR_100NS_PER_SECOND, &Leftover);
00625
00626 size_t n = mux_i64toa(lt, buffer);
00627 if (Leftover == 0)
00628 {
00629 return;
00630 }
00631
00632
00633
00634 const int maxFracDigits = 7;
00635 const int minFracDigits = 0;
00636 if (nFracDigits < minFracDigits)
00637 {
00638 nFracDigits = minFracDigits;
00639 }
00640 else if (maxFracDigits < nFracDigits)
00641 {
00642 nFracDigits = maxFracDigits;
00643 }
00644 if (0 < nFracDigits)
00645 {
00646 char *p = buffer + n;
00647 *p++ = '.';
00648 char *q = p;
00649
00650 char buf[maxFracDigits+1];
00651 size_t m = mux_i64toa(Leftover, buf);
00652 memset(p, '0', maxFracDigits - m);
00653 p += maxFracDigits - m;
00654 memcpy(p, buf, m);
00655 p = q + nFracDigits - 1;
00656 while (*p == '0')
00657 {
00658 p--;
00659 }
00660 p++;
00661 *p = '\0';
00662 }
00663 }
00664
00665 char *CLinearTimeDelta::ReturnSecondsString(int nFracDigits)
00666 {
00667 ConvertToSecondsString(m_Buffer, m_tDelta, nFracDigits);
00668 return m_Buffer;
00669 }
00670
00671 char *CLinearTimeAbsolute::ReturnSecondsString(int nFracDigits)
00672 {
00673 ConvertToSecondsString(m_Buffer, m_tAbsolute - EPOCH_OFFSET, nFracDigits);
00674 return m_Buffer;
00675 }
00676
00677 CLinearTimeAbsolute::CLinearTimeAbsolute(const CLinearTimeAbsolute <a)
00678 {
00679 m_tAbsolute = lta.m_tAbsolute;
00680 }
00681
00682 CLinearTimeAbsolute::CLinearTimeAbsolute(void)
00683 {
00684 m_tAbsolute = 0;
00685 }
00686
00687 CLinearTimeDelta::CLinearTimeDelta(void)
00688 {
00689 m_tDelta = 0;
00690 }
00691
00692 CLinearTimeDelta::CLinearTimeDelta(INT64 arg_t100ns)
00693 {
00694 m_tDelta = arg_t100ns;
00695 }
00696
00697 void CLinearTimeDelta::ReturnTimeValueStruct(struct timeval *tv)
00698 {
00699 INT64 Leftover;
00700 tv->tv_sec = (long)i64FloorDivisionMod(m_tDelta, FACTOR_100NS_PER_SECOND, &Leftover);
00701 tv->tv_usec = (long)i64FloorDivision(Leftover, FACTOR_100NS_PER_MICROSECOND);
00702 }
00703
00704 #ifdef HAVE_NANOSLEEP
00705 void CLinearTimeDelta::ReturnTimeSpecStruct(struct timespec *ts)
00706 {
00707 INT64 Leftover;
00708 ts->tv_sec = (long)i64FloorDivisionMod(m_tDelta, FACTOR_100NS_PER_SECOND, &Leftover);
00709 ts->tv_nsec = (long)Leftover*FACTOR_NANOSECONDS_PER_100NS;
00710 }
00711 #endif // HAVE_NANOSLEEP
00712
00713 void CLinearTimeDelta::SetTimeValueStruct(struct timeval *tv)
00714 {
00715 m_tDelta = FACTOR_100NS_PER_SECOND * tv->tv_sec
00716 + FACTOR_100NS_PER_MICROSECOND * tv->tv_usec;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725 char *DayOfWeekString[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
00726 static const char daystab[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00727 const char *monthtab[] =
00728 {
00729 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00730 };
00731
00732 void CLinearTimeDelta::SetMilliseconds(unsigned long arg_dwMilliseconds)
00733 {
00734 m_tDelta = arg_dwMilliseconds * FACTOR_100NS_PER_MILLISECOND;
00735 }
00736
00737 long CLinearTimeDelta::ReturnMilliseconds(void)
00738 {
00739 return (long)(m_tDelta/FACTOR_100NS_PER_MILLISECOND);
00740 }
00741
00742 INT64 CLinearTimeDelta::ReturnMicroseconds(void)
00743 {
00744 return m_tDelta/FACTOR_100NS_PER_MICROSECOND;
00745 }
00746
00747 void CLinearTimeDelta::SetSecondsString(char *arg_szSeconds)
00748 {
00749 ParseFractionalSecondsString(m_tDelta, arg_szSeconds);
00750 }
00751
00752 void CLinearTimeDelta::SetSeconds(INT64 arg_tSeconds)
00753 {
00754 m_tDelta = arg_tSeconds * FACTOR_100NS_PER_SECOND;
00755 }
00756
00757 void CLinearTimeDelta::Set100ns(INT64 arg_t100ns)
00758 {
00759 m_tDelta = arg_t100ns;
00760 }
00761
00762 INT64 CLinearTimeDelta::Return100ns(void)
00763 {
00764 return m_tDelta;
00765 }
00766
00767 void CLinearTimeAbsolute::Set100ns(INT64 arg_t100ns)
00768 {
00769 m_tAbsolute = arg_t100ns;
00770 }
00771
00772 INT64 CLinearTimeAbsolute::Return100ns(void)
00773 {
00774 return m_tAbsolute;
00775 }
00776
00777 void CLinearTimeAbsolute::SetSeconds(INT64 arg_tSeconds)
00778 {
00779 m_tAbsolute = arg_tSeconds;
00780 m_tAbsolute *= FACTOR_100NS_PER_SECOND;
00781
00782
00783
00784
00785 m_tAbsolute += EPOCH_OFFSET;
00786 }
00787
00788 INT64 CLinearTimeAbsolute::ReturnSeconds(void)
00789 {
00790
00791
00792
00793 return i64FloorDivision(m_tAbsolute - EPOCH_OFFSET, FACTOR_100NS_PER_SECOND);
00794 }
00795
00796 bool isLeapYear(long iYear)
00797 {
00798 if (iMod(iYear, 4) != 0)
00799 {
00800
00801
00802 return false;
00803 }
00804 unsigned long wMod = iMod(iYear, 400);
00805 if ((wMod == 100) || (wMod == 200) || (wMod == 300))
00806 {
00807
00808
00809 return false;
00810 }
00811 return true;
00812 }
00813
00814 static bool isValidDate(int iYear, int iMonth, int iDay)
00815 {
00816 if (iYear < -27256 || 30826 < iYear)
00817 {
00818 return false;
00819 }
00820 if (iMonth < 1 || 12 < iMonth)
00821 {
00822 return false;
00823 }
00824 if (iDay < 1 || daystab[iMonth-1] < iDay)
00825 {
00826 return false;
00827 }
00828 if (iMonth == 2 && iDay == 29 && !isLeapYear(iYear))
00829 {
00830 return false;
00831 }
00832 return true;
00833 }
00834
00835 static int FixedFromGregorian(int iYear, int iMonth, int iDay)
00836 {
00837 iYear = iYear - 1;
00838 int iFixedDay = 365 * iYear;
00839 iFixedDay += iFloorDivision(iYear, 4);
00840 iFixedDay -= iFloorDivision(iYear, 100);
00841 iFixedDay += iFloorDivision(iYear, 400);
00842 iFixedDay += iFloorDivision(367 * iMonth - 362, 12);
00843 iFixedDay += iDay;
00844
00845 if (iMonth > 2)
00846 {
00847 if (isLeapYear(iYear+1))
00848 {
00849 iFixedDay -= 1;
00850 }
00851 else
00852 {
00853 iFixedDay -= 2;
00854 }
00855 }
00856
00857
00858
00859 return iFixedDay;
00860 }
00861
00862 static int FixedFromGregorian_Adjusted(int iYear, int iMonth, int iDay)
00863 {
00864 int iFixedDay = FixedFromGregorian(iYear, iMonth, iDay);
00865
00866
00867
00868
00869 return iFixedDay - 584389;
00870 }
00871
00872
00873
00874
00875 static void GregorianFromFixed(int iFixedDay, int &iYear, int &iMonth, int &iDayOfYear, int &iDayOfMonth, int &iDayOfWeek)
00876 {
00877 int d0 = iFixedDay - 1;
00878 int d1, n400 = iFloorDivisionMod(d0, 146097, &d1);
00879 int d2, n100 = iFloorDivisionMod(d1, 36524, &d2);
00880 int d3, n4 = iFloorDivisionMod(d2, 1461, &d3);
00881 int d4, n1 = iFloorDivisionMod(d3, 365, &d4);
00882 d4 = d4 + 1;
00883
00884 iYear = 400*n400 + 100*n100 + 4*n4 + n1;
00885
00886 if (n100 != 4 && n1 != 4)
00887 {
00888 iYear = iYear + 1;
00889 }
00890
00891 static int cache_iYear = 99999;
00892 static int cache_iJan1st = 0;
00893 static int cache_iMar1st = 0;
00894 int iFixedDayOfJanuary1st;
00895 int iFixedDayOfMarch1st;
00896 if (iYear == cache_iYear)
00897 {
00898 iFixedDayOfJanuary1st = cache_iJan1st;
00899 iFixedDayOfMarch1st = cache_iMar1st;
00900 }
00901 else
00902 {
00903 cache_iYear = iYear;
00904 cache_iJan1st = iFixedDayOfJanuary1st = FixedFromGregorian(iYear, 1, 1);
00905 cache_iMar1st = iFixedDayOfMarch1st = FixedFromGregorian(iYear, 3, 1);
00906 }
00907
00908
00909 int iPriorDays = iFixedDay - iFixedDayOfJanuary1st;
00910 int iCorrection;
00911 if (iFixedDay < iFixedDayOfMarch1st)
00912 {
00913 iCorrection = 0;
00914 }
00915 else if (isLeapYear(iYear))
00916 {
00917 iCorrection = 1;
00918 }
00919 else
00920 {
00921 iCorrection = 2;
00922 }
00923
00924 iMonth = (12*(iPriorDays+iCorrection)+373)/367;
00925 iDayOfMonth = iFixedDay - FixedFromGregorian(iYear, iMonth, 1) + 1;
00926 iDayOfYear = iPriorDays + 1;
00927
00928
00929
00930 iDayOfWeek = iMod(iFixedDay, 7);
00931 }
00932
00933 static void GregorianFromFixed_Adjusted(int iFixedDay, int &iYear, int &iMonth, int &iDayOfYear, int &iDayOfMonth, int &iDayOfWeek)
00934 {
00935
00936
00937
00938 GregorianFromFixed(iFixedDay + 584389, iYear, iMonth, iDayOfYear, iDayOfMonth, iDayOfWeek);
00939 }
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 static int MonthTabHash[12] =
00951 {
00952 0x004a414e, 0x00464542, 0x004d4152, 0x00415052,
00953 0x004d4159, 0x004a554e, 0x004a554c, 0x00415547,
00954 0x00534550, 0x004f4354, 0x004e4f56, 0x00444543
00955 };
00956
00957 static bool ParseThreeLetters(const char **pp, int *piHash)
00958 {
00959 *piHash = 0;
00960
00961
00962
00963 const char *p = *pp;
00964 while (*p == ' ')
00965 {
00966 p++;
00967 }
00968
00969
00970
00971 const char *q = p;
00972 int iHash = 0;
00973 while (*q && *q != ' ')
00974 {
00975 if (!mux_isalpha(*q))
00976 {
00977 return false;
00978 }
00979 iHash = (iHash << 8) | mux_toupper(*q);
00980 q++;
00981 }
00982
00983
00984
00985 if (q - p != 3)
00986 {
00987 return false;
00988 }
00989 p = q;
00990
00991
00992
00993 while (*p == ' ')
00994 {
00995 p++;
00996 }
00997
00998 *pp = p;
00999 *piHash = iHash;
01000 return true;
01001 }
01002
01003 static void ParseDecimalSeconds(size_t n, const char *p, unsigned short *iMilli,
01004 unsigned short *iMicro, unsigned short *iNano)
01005 {
01006 char aBuffer[10];
01007 if (n > sizeof(aBuffer) - 1)
01008 {
01009 n = sizeof(aBuffer) - 1;
01010 }
01011 memcpy(aBuffer, p, n);
01012 memset(aBuffer + n, '0', sizeof(aBuffer) - n - 1);
01013 aBuffer[sizeof(aBuffer) - 1] = '\0';
01014 int ns = mux_atol(aBuffer);
01015 *iNano = ns % 1000;
01016 ns /= 1000;
01017 *iMicro = ns % 1000;
01018 *iMilli = ns / 1000;
01019 }
01020
01021 static bool do_convtime(const char *str, FIELDEDTIME *ft)
01022 {
01023 memset(ft, 0, sizeof(FIELDEDTIME));
01024 if (!str || !ft)
01025 {
01026 return false;
01027 }
01028
01029
01030
01031 const char *p = str;
01032 int i, iHash;
01033 if (!ParseThreeLetters(&p, &iHash))
01034 {
01035 return false;
01036 }
01037 for (i = 0; (i < 12) && iHash != MonthTabHash[i]; i++) ;
01038 if (i == 12)
01039 {
01040
01041
01042
01043 if (!ParseThreeLetters(&p, &iHash))
01044 {
01045 return false;
01046 }
01047 for (i = 0; (i < 12) && iHash != MonthTabHash[i]; i++) ;
01048 if (i == 12)
01049 {
01050 return false;
01051 }
01052 }
01053 ft->iMonth = i + 1;
01054
01055
01056
01057 ft->iDayOfMonth = (unsigned short)mux_atol(p);
01058 if (ft->iDayOfMonth < 1 || daystab[i] < ft->iDayOfMonth)
01059 {
01060 return false;
01061 }
01062 while (*p && *p != ' ') p++;
01063 while (*p == ' ') p++;
01064
01065
01066
01067 ft->iHour = (unsigned short)mux_atol(p);
01068 if (ft->iHour > 23 || (ft->iHour == 0 && *p != '0'))
01069 {
01070 return false;
01071 }
01072 while (*p && *p != ':') p++;
01073 if (*p == ':') p++;
01074 while (*p == ' ') p++;
01075
01076
01077
01078 ft->iMinute = (unsigned short)mux_atol(p);
01079 if (ft->iMinute > 59 || (ft->iMinute == 0 && *p != '0'))
01080 {
01081 return false;
01082 }
01083 while (*p && *p != ':') p++;
01084 if (*p == ':') p++;
01085 while (*p == ' ') p++;
01086
01087
01088
01089 ft->iSecond = (unsigned short)mux_atol(p);
01090 if (ft->iSecond > 59 || (ft->iSecond == 0 && *p != '0'))
01091 {
01092 return false;
01093 }
01094 while (mux_isdigit(*p))
01095 {
01096 p++;
01097 }
01098
01099
01100
01101 if (*p == '.')
01102 {
01103 p++;
01104 size_t n;
01105 const char *q = strchr(p, ' ');
01106 if (q)
01107 {
01108 n = q - p;
01109 }
01110 else
01111 {
01112 n = strlen(p);
01113 }
01114
01115 ParseDecimalSeconds(n, p, &ft->iMillisecond, &ft->iMicrosecond,
01116 &ft->iNanosecond);
01117 }
01118 while (*p && *p != ' ') p++;
01119 while (*p == ' ') p++;
01120
01121
01122
01123 ft->iYear = (short)mux_atol(p);
01124 while (mux_isdigit(*p))
01125 {
01126 p++;
01127 }
01128 while (*p == ' ') p++;
01129 if (*p != '\0')
01130 {
01131 return false;
01132 }
01133
01134
01135
01136 ft->iDayOfYear = 0;
01137 ft->iDayOfWeek = 0;
01138
01139 return isValidDate(ft->iYear, ft->iMonth, ft->iDayOfMonth);
01140 }
01141
01142 CLinearTimeDelta::CLinearTimeDelta(CLinearTimeAbsolute t0, CLinearTimeAbsolute t1)
01143 {
01144 m_tDelta = t1.m_tAbsolute - t0.m_tAbsolute;
01145 }
01146
01147 long CLinearTimeDelta::ReturnDays(void)
01148 {
01149 return (long)(m_tDelta/FACTOR_100NS_PER_DAY);
01150 }
01151
01152 long CLinearTimeDelta::ReturnSeconds(void)
01153 {
01154 return (long)(m_tDelta/FACTOR_100NS_PER_SECOND);
01155 }
01156
01157 bool CLinearTimeAbsolute::ReturnFields(FIELDEDTIME *arg_tStruct)
01158 {
01159 return LinearTimeToFieldedTime(m_tAbsolute, arg_tStruct);
01160 }
01161
01162 bool CLinearTimeAbsolute::SetString(const char *arg_tBuffer)
01163 {
01164 FIELDEDTIME ft;
01165 if (do_convtime(arg_tBuffer, &ft))
01166 {
01167 if (FieldedTimeToLinearTime(&ft, &m_tAbsolute))
01168 {
01169 return true;
01170 }
01171 }
01172 m_tAbsolute = 0;
01173 return false;
01174 }
01175
01176 void CLinearTimeDelta::operator+=(const CLinearTimeDelta& ltd)
01177 {
01178 m_tDelta += ltd.m_tDelta;
01179 }
01180
01181 CLinearTimeDelta operator-(const CLinearTimeAbsolute& ltaA, const CLinearTimeAbsolute& ltaB)
01182 {
01183 CLinearTimeDelta ltd;
01184 ltd.m_tDelta = ltaA.m_tAbsolute - ltaB.m_tAbsolute;
01185 return ltd;
01186 }
01187
01188 CLinearTimeDelta operator-(const CLinearTimeDelta& lta, const CLinearTimeDelta& ltb)
01189 {
01190 CLinearTimeDelta ltd;
01191 ltd.m_tDelta = lta.m_tDelta - ltb.m_tDelta;
01192 return ltd;
01193 }
01194
01195 CLinearTimeAbsolute operator+(const CLinearTimeAbsolute& ltaA, const CLinearTimeDelta& ltdB)
01196 {
01197 CLinearTimeAbsolute lta;
01198 lta.m_tAbsolute = ltaA.m_tAbsolute + ltdB.m_tDelta;
01199 return lta;
01200 }
01201
01202 void CLinearTimeAbsolute::operator=(const CLinearTimeAbsolute& lta)
01203 {
01204 m_tAbsolute = lta.m_tAbsolute;
01205 }
01206
01207 CLinearTimeDelta operator*(const CLinearTimeDelta& ltd, int Scale)
01208 {
01209 CLinearTimeDelta ltdResult;
01210 ltdResult.m_tDelta = ltd.m_tDelta * Scale;
01211 return ltdResult;
01212 }
01213
01214 int operator/(const CLinearTimeDelta& ltdA, const CLinearTimeDelta& ltdB)
01215 {
01216 int iResult = (int)(ltdA.m_tDelta / ltdB.m_tDelta);
01217 return iResult;
01218 }
01219
01220 bool operator<(const CLinearTimeDelta& ltdA, const CLinearTimeDelta& ltdB)
01221 {
01222 return ltdA.m_tDelta < ltdB.m_tDelta;
01223 }
01224
01225 bool operator>(const CLinearTimeDelta& ltdA, const CLinearTimeDelta& ltdB)
01226 {
01227 return ltdA.m_tDelta > ltdB.m_tDelta;
01228 }
01229
01230 void CLinearTimeAbsolute::operator-=(const CLinearTimeDelta& ltd)
01231 {
01232 m_tAbsolute -= ltd.m_tDelta;
01233 }
01234
01235 void CLinearTimeAbsolute::operator+=(const CLinearTimeDelta& ltd)
01236 {
01237 m_tAbsolute += ltd.m_tDelta;
01238 }
01239
01240 bool CLinearTimeAbsolute::SetFields(FIELDEDTIME *arg_tStruct)
01241 {
01242 m_tAbsolute = 0;
01243 return FieldedTimeToLinearTime(arg_tStruct, &m_tAbsolute);
01244 }
01245
01246 static void SetStructTm(FIELDEDTIME *ft, struct tm *ptm)
01247 {
01248 ft->iYear = ptm->tm_year + 1900;
01249 ft->iMonth = ptm->tm_mon + 1;
01250 ft->iDayOfMonth = ptm->tm_mday;
01251 ft->iDayOfWeek = ptm->tm_wday;
01252 ft->iDayOfYear = 0;
01253 ft->iHour = ptm->tm_hour;
01254 ft->iMinute = ptm->tm_min;
01255 ft->iSecond = ptm->tm_sec;
01256 }
01257
01258 void CLinearTimeAbsolute::ReturnUniqueString(char *buffer)
01259 {
01260 FIELDEDTIME ft;
01261 if (LinearTimeToFieldedTime(m_tAbsolute, &ft))
01262 {
01263 sprintf(buffer, "%04d%02d%02d-%02d%02d%02d", ft.iYear, ft.iMonth,
01264 ft.iDayOfMonth, ft.iHour, ft.iMinute, ft.iSecond);
01265 }
01266 else
01267 {
01268 sprintf(buffer, "%03d", m_nCount++);
01269 }
01270 }
01271
01272 char *CLinearTimeAbsolute::ReturnDateString(int nFracDigits)
01273 {
01274 FIELDEDTIME ft;
01275 if (LinearTimeToFieldedTime(m_tAbsolute, &ft))
01276 {
01277
01278
01279 const int maxFracDigits = 7;
01280 const int minFracDigits = 0;
01281 if (nFracDigits < minFracDigits)
01282 {
01283 nFracDigits = minFracDigits;
01284 }
01285 else if (maxFracDigits < nFracDigits)
01286 {
01287 nFracDigits = maxFracDigits;
01288 }
01289
01290 char buffer[11];
01291 buffer[0] = '\0';
01292 if ( 0 < nFracDigits
01293 && ( ft.iMillisecond != 0
01294 || ft.iMicrosecond != 0
01295 || ft.iNanosecond != 0))
01296 {
01297 sprintf(buffer, ".%03d%03d%03d", ft.iMillisecond, ft.iMicrosecond,
01298 ft.iNanosecond);
01299
01300
01301
01302 char *p = (buffer + 1) + (nFracDigits - 1);
01303 while (*p == '0')
01304 {
01305 p--;
01306 }
01307 p++;
01308 *p = '\0';
01309 }
01310 sprintf(m_Buffer, "%s %s %02d %02d:%02d:%02d%s %04d",
01311 DayOfWeekString[ft.iDayOfWeek], monthtab[ft.iMonth-1],
01312 ft.iDayOfMonth, ft.iHour, ft.iMinute, ft.iSecond, buffer,
01313 ft.iYear);
01314 }
01315 else
01316 {
01317 m_Buffer[0] = '\0';
01318 }
01319 return m_Buffer;
01320 }
01321
01322 void CLinearTimeAbsolute::GetUTC(void)
01323 {
01324 GetUTCLinearTime(&m_tAbsolute);
01325 }
01326
01327 void CLinearTimeAbsolute::GetLocal(void)
01328 {
01329 GetUTCLinearTime(&m_tAbsolute);
01330 UTC2Local();
01331 }
01332
01333 bool FieldedTimeToLinearTime(FIELDEDTIME *ft, INT64 *plt)
01334 {
01335 if (!isValidDate(ft->iYear, ft->iMonth, ft->iDayOfMonth))
01336 {
01337 *plt = 0;
01338 return false;
01339 }
01340
01341 int iFixedDay = FixedFromGregorian_Adjusted(ft->iYear, ft->iMonth, ft->iDayOfMonth);
01342 ft->iDayOfWeek = iMod(iFixedDay+1, 7);
01343
01344 INT64 lt;
01345 lt = iFixedDay * FACTOR_100NS_PER_DAY;
01346 lt += ft->iHour * FACTOR_100NS_PER_HOUR;
01347 lt += ft->iMinute * FACTOR_100NS_PER_MINUTE;
01348 lt += ft->iSecond * FACTOR_100NS_PER_SECOND;
01349 lt += ft->iMicrosecond * FACTOR_100NS_PER_MICROSECOND;
01350 lt += ft->iMillisecond * FACTOR_100NS_PER_MILLISECOND;
01351 lt += ft->