00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "JTime.h"
00026 #include "XMLParser.h"
00027
00028
00029 #ifdef CYGWIN
00030
00031
00032 #endif
00033
00034
00035 #ifdef Darwin
00036
00037 #include <sys/time.h>
00038
00039 int ftime(struct timeb *tp) {
00040
00041 struct timeval tv;
00042 struct timezone tz;
00043
00044 gettimeofday(&tv, &tz);
00045
00046 tp->time = tv.tv_sec;
00047 tp->millitm = (unsigned short) (tv.tv_usec / 1000);
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 return 0;
00061 }
00062
00063 #endif
00064
00065 #if defined(WIN32_POCKETPC)
00066
00067
00068
00069 struct tm staticTM;
00070
00071 int ftime_gmt(struct timeb *tp) {
00072
00073 FILETIME ft;
00074 SYSTEMTIME st;
00075 GetLocalTime(&st);
00076 SystemTimeToFileTime(&st, &ft);
00077
00078 struct timeb t = JTime::filetime2timeb(&ft);
00079
00080
00081
00082
00083 *tp = t;
00084 return 0;
00085 }
00086
00087 int ftime(struct timeb *tp) {
00088
00089 FILETIME ft;
00090 SYSTEMTIME st;
00091 GetSystemTime(&st);
00092 SystemTimeToFileTime(&st, &ft);
00093
00094 struct timeb t = JTime::filetime2timeb(&ft);
00095
00096
00097
00098
00099 *tp = t;
00100 return 0;
00101 }
00102
00103 unsigned long time(time_t *t) {
00104 struct timeb tb;
00105 ftime(&tb);
00106 *t = tb.time;
00107 return 0;
00108 }
00109
00110 struct tm* localtime(time_t *t) {
00111
00112 SYSTEMTIME st;
00113 FILETIME ft = JTime::time_t2filetime(*t);
00114 FileTimeToSystemTime(&ft, &st);
00115
00116
00117 staticTM.tm_sec = st.wSecond;
00118 staticTM.tm_min = st.wMinute;
00119 staticTM.tm_hour = st.wHour;
00120 staticTM.tm_mday = st.wDay;
00121 staticTM.tm_mon = st.wMonth-1;
00122 staticTM.tm_year = st.wYear - 1900;
00123 staticTM.tm_wday = st.wDayOfWeek;
00124 staticTM.tm_yday = 1;
00125
00126
00127 return &staticTM;
00128 }
00129
00130 struct tm* gmtime(time_t *t) {
00131
00132 SYSTEMTIME st;
00133 FILETIME ft = JTime::time_t2filetime(*t);
00134 FileTimeToSystemTime(&ft, &st);
00135
00136 staticTM.tm_sec = st.wSecond;
00137 staticTM.tm_min = st.wMinute;
00138 staticTM.tm_hour = st.wHour;
00139 staticTM.tm_mday = st.wDay;
00140 staticTM.tm_mon = st.wMonth - 1;
00141 staticTM.tm_year = st.wYear - 1900;
00142 staticTM.tm_wday = st.wDayOfWeek;
00143 staticTM.tm_yday = 1;
00144 staticTM.tm_isdst = 0;
00145
00146 return &staticTM;
00147 }
00148
00149
00150
00151 #endif
00152
00153 namespace cmlabs {
00154
00155 JTime JTime::createInvalid() {
00156 JTime newTime;
00157 newTime.setInvalid();
00158 return newTime;
00159 }
00160
00161
00162
00163
00164
00165
00166 JTime::JTime()
00167 {
00168 ftime( &timebuffer );
00169 valid = true;
00170 atomicOffset = 0;
00171
00172
00173 #ifdef WIN32
00174 if (QueryPerformanceCounter(&perfCount) == 0) {
00175 FILETIME ft;
00176 SYSTEMTIME st;
00177 GetLocalTime(&st);
00178 SystemTimeToFileTime(&st, &ft);
00179 perfCount = *(LARGE_INTEGER*)&ft;
00180
00181
00182 }
00183 #else
00184 struct timezone tmzone;
00185 gettimeofday(&perfCount, &tmzone);
00186 #endif // WIN32
00187
00188
00189 }
00190
00191 JTime::JTime(const JTime &t) {
00192 timebuffer = t.timebuffer;
00193 perfCount = t.perfCount;
00194 valid = t.valid;
00195 atomicOffset = t.atomicOffset;
00196
00197 }
00198
00199 JTime::JTime(struct timeb tb) {
00200 timebuffer = tb;
00201 atomicOffset = 0;
00202
00203 #ifdef WIN32
00204 perfCount.QuadPart = 0;
00205 #else
00206 perfCount.tv_sec = 0;
00207 #endif // WIN32
00208 valid = true;
00209
00210 }
00211
00212 JTime::JTime(long ms) {
00213
00214 ftime( &timebuffer );
00215 valid = true;
00216 atomicOffset = 0;
00217
00218 timebuffer.time = (int)(ms/1000);
00219 if (timebuffer.time < 0) valid=false;
00220 timebuffer.millitm = (unsigned short) (ms - (timebuffer.time * 1000));
00221
00222 #ifdef WIN32
00223 perfCount.QuadPart = 0;
00224 #else
00225 perfCount.tv_sec = 0;
00226 #endif // WIN32
00227
00228 }
00229
00230
00231 JTime::JTime(const JString& text)
00232 {
00233
00234 atomicOffset = 0;
00235 valid = true;
00236 ftime( &timebuffer );
00237 if (text.looksLikeXML()) {
00238 if (!Object::fromXML(text)) {
00239 }
00240 }
00241 else if ( (text.contains(",")) && (text.contains(":")) ) {
00242 fromHTTP(text);
00243 }
00244 else if (text.length() > 0) {
00245 JString strTime;
00246 JString strMs;
00247 int pos = text.indexOf('.');
00248 if (pos > 0) {
00249 strTime = text.substring(0, pos-3);
00250 strMs = text.substring(pos-3, pos);
00251 atomicOffset = text.substring(pos+1).toInt();
00252 }
00253 else {
00254 strTime = text.substring(0, text.length()-3);
00255 strMs = text.substring(text.length()-3);
00256 }
00257
00258 ftime( &timebuffer );
00259 timebuffer.time = strTime.toLong();
00260 if (timebuffer.time < 0)
00261 timebuffer.time = timebuffer.time;
00262 timebuffer.millitm = (unsigned short) strMs.toInt();
00263 }
00264 else
00265 valid = false;
00266
00267 #ifdef WIN32
00268 perfCount.QuadPart = 0;
00269 #else
00270 perfCount.tv_sec = 0;
00271 #endif // WIN32
00272 }
00273
00274 JTime::JTime(XMLNode* node) {
00275
00276 atomicOffset = 0;
00277 valid = true;
00278 if (!fromXML(node)) {
00279 }
00280 }
00281
00282 JTime::JTime(long sec, int milli)
00283 {
00284 ftime( &timebuffer );
00285 atomicOffset = 0;
00286 if (sec < 0) sec = 0;
00287 if (timebuffer.time < 100000000) {
00288 timebuffer.timezone = 0;
00289 timebuffer.dstflag = 0;
00290 }
00291 timebuffer.time = sec;
00292 timebuffer.millitm = milli;
00293 #ifdef WIN32
00294 perfCount.QuadPart = 0;
00295 #else
00296 perfCount.tv_sec = 0;
00297 #endif // WIN32
00298 valid = true;
00299
00300 }
00301
00302
00303 JTime::~JTime()
00304 {
00305
00306 }
00307
00308
00309
00310 unsigned long JTime::getPayloadSize() const {
00311 return sizeof(struct timeb) + tzc.length() + sizeof(perfCount);
00312 }
00313
00314 JString JTime::getLocalTimeZoneInformation() const {
00315
00316 if (tzc.length() > 0)
00317 return tzc;
00318
00319 JString tzName = "";
00320 long tzOffset = 0;
00321 int tzDST = 0;
00322
00323 #ifdef WIN32
00324
00325 TIME_ZONE_INFORMATION tzinfo;
00326 DWORD res = GetTimeZoneInformation(&tzinfo);
00327
00328 tzOffset = -1 * tzinfo.StandardBias;
00329 tzDST = -1 * tzinfo.DaylightBias;
00330
00331 tzName = tzinfo.StandardName;
00332 int pos = tzName.indexOf(' ');
00333 if (pos > 0)
00334 tzinfo.StandardName[pos] = 0;
00335 tzName = tzinfo.StandardName;
00336
00337 #else
00338 #ifndef Darwin
00339 tzset();
00340 tzOffset = timezone * 60;
00341 tzDST = daylight * 60;
00342 tzName = tzname[0];
00343
00344
00345 #endif
00346 #endif
00347
00348 return JString::format("%s_%d_%d", (char*)tzName, tzOffset, tzDST);
00349 }
00350
00351
00352 bool JTime::setLocalTimeZoneInformation() {
00353 tzc = getLocalTimeZoneInformation();
00354 return true;
00355 }
00356
00357 JString JTime::getLocalTimeZoneName() const {
00358 return getLocalTimeZoneInformation().split("_").get(0);
00359 }
00360 int JTime::getLocalTimeZoneOffset() const {
00361 return getLocalTimeZoneInformation().split("_").get(1).toInt();
00362 }
00363 int JTime::getLocalTimeZoneDST() const {
00364 return getLocalTimeZoneInformation().split("_").get(2).toInt();
00365 }
00366 JString JTime::getOriginalTimeZoneName() const {
00367 return tzc.split("_").get(0);
00368 }
00369 int JTime::getOriginalTimeZoneOffset() const {
00370 return tzc.split("_").get(1).toInt();
00371 }
00372 int JTime::getOriginalTimeZoneDST() const {
00373 return tzc.split("_").get(2).toInt();
00374 }
00375
00376 int JTime::getTimeDifference() const {
00377 return getLocalTimeZoneOffset() - getOriginalTimeZoneOffset() +
00378 ( getLocalTimeZoneDST() - getOriginalTimeZoneDST() );
00379 }
00380
00381 int JTime::getTimeDifference(const JTime &t) const {
00382 return t.getOriginalTimeZoneOffset() - getOriginalTimeZoneOffset() +
00383 ( t.getOriginalTimeZoneDST() - getOriginalTimeZoneDST() );
00384 }
00385
00386 bool JTime::perfCountReset() {
00387 #ifdef WIN32
00388 perfCount.QuadPart = 0;
00389 #else
00390 perfCount.tv_sec = 0;
00391 #endif // WIN32
00392 return true;
00393 }
00394
00395 bool JTime::reset() {
00396 ftime( &timebuffer );
00397 atomicOffset = 0;
00398 valid = true;
00399
00400 #ifdef WIN32
00401 if (QueryPerformanceCounter(&perfCount) == 0) {
00402 FILETIME ft;
00403 SYSTEMTIME st;
00404 GetLocalTime(&st);
00405 SystemTimeToFileTime(&st, &ft);
00406 perfCount = *(LARGE_INTEGER*)&ft;
00407 }
00408 #else
00409 struct timezone tmzone;
00410 gettimeofday(&perfCount, &tmzone);
00411 #endif // WIN32
00412 return true;
00413 }
00414
00415 void JTime::setInvalid() {
00416 #ifdef WIN32
00417 perfCount.QuadPart = 0;
00418 #else
00419 perfCount.tv_sec = 0;
00420 #endif // WIN32
00421 valid = false;
00422 }
00423
00424 bool JTime::isValid() const {
00425 return valid;
00426 }
00427
00428
00429 Object* JTime::clone() const {
00430 JTime* t = new JTime(*this);
00431 return (Object*) t;
00432 }
00433
00434 unsigned long JTime::getHash() const {
00435 unsigned long key = (unsigned long) this->ms();
00436
00437 key += ~(key << 15);
00438 key ^= (key >> 10);
00439 key += (key << 3);
00440 key ^= (key >> 6);
00441 key += ~(key << 11);
00442 key ^= (key >> 16);
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 return key;
00453 }
00454
00455 JString JTime::printTime() const {
00456 return printTimeMS();
00457 }
00458
00459 JString JTime::printTimeSec() const {
00460 if (!valid)
00461 return "n/a";
00462 struct tm *newtime;
00463
00464 time_t tp = timebuffer.time;
00465 if (tp < 100000000)
00466 newtime = gmtime(&tp);
00467 else
00468 newtime = localtime(&tp);
00469 char result[100];
00470 sprintf(result, "%.2d:%.2d:%.2d", newtime->tm_hour, newtime->tm_min, newtime->tm_sec);
00471 return JString(result);
00472 }
00473
00474 JString JTime::printTimeMS() const {
00475 if (!valid)
00476 return "n/a";
00477 return JString::format("%s.%.3d", (char*) printTimeSec(), timebuffer.millitm);
00478 }
00479
00480 JString JTime::printDifTime() const {
00481 if (!valid)
00482 return "n/a";
00483 struct tm *newtime;
00484 time_t tp = timebuffer.time;
00485 if (tp < 100000000)
00486 newtime = gmtime(&tp);
00487 else
00488 newtime = localtime(&tp);
00489
00490 int days = (int)(timebuffer.time / (60*60*24));
00491
00492 JString timestring;
00493 if (days > 1)
00494 timestring += JString::format("%d days ", days);
00495 else if (days == 1)
00496 timestring += JString::format("%d day ", days);
00497
00498 if (newtime->tm_hour > 1)
00499 timestring += JString::format("%d hours ", newtime->tm_hour);
00500 else if (newtime->tm_hour == 1)
00501 timestring += JString::format("1 hour ");
00502 else if (days > 0)
00503 timestring += JString::format("0 hours ");
00504
00505
00506 if ((timestring.length() == 0) && (newtime->tm_min > 0))
00507 timestring += JString::format("%d min ", newtime->tm_min);
00508 else if (newtime->tm_min > 0)
00509 timestring += JString::format("%.2d min ", newtime->tm_min);
00510 else if (timestring.length() > 0)
00511 timestring += JString::format("0 min ");
00512
00513 if ((timestring.length() == 0) && (newtime->tm_sec > 0))
00514 timestring += JString::format("%d", newtime->tm_sec);
00515 else if (newtime->tm_sec > 0)
00516 timestring += JString::format("%.2d", newtime->tm_sec);
00517 else if (timestring.length() > 0)
00518 timestring += JString::format("00");
00519
00520
00521 if (timestring.length() == 0)
00522 timestring += JString::format("%d ms", timebuffer.millitm);
00523 else
00524 timestring += JString::format(".%.3d sec", timebuffer.millitm);
00525
00526 return timestring;
00527 }
00528
00529 JString JTime::printDateShort() const {
00530 if (!valid)
00531 return "n/a";
00532 struct tm *newtime;
00533 time_t tp = timebuffer.time;
00534 newtime = localtime(&tp);
00535 char result[100];
00536 sprintf(result, "%.2d-%.2d-%.4d", newtime->tm_mday, newtime->tm_mon + 1, newtime->tm_year + 1900);
00537 return JString(result);
00538 }
00539
00540 JString JTime::printDateSortable() const {
00541 if (!valid)
00542 return "n/a";
00543 struct tm *newtime;
00544 time_t tp = timebuffer.time;
00545 newtime = localtime(&tp);
00546 char result[100];
00547 sprintf(result, "%.4d-%.2d-%.2d", newtime->tm_year + 1900, newtime->tm_mon + 1, newtime->tm_mday);
00548 return JString(result);
00549 }
00550
00551 JString JTime::printDateLong() const {
00552 if (!valid)
00553 return "n/a";
00554 struct tm *newtime;
00555 time_t tp = timebuffer.time;
00556 newtime = localtime(&tp);
00557 char result[100];
00558 sprintf(result, "%.2d.%.2d.%.4d",
00559 newtime->tm_mday, newtime->tm_mon + 1, newtime->tm_year + 1900);
00560 return JString(result);
00561
00562
00563
00564
00565
00566
00567
00568 }
00569
00570
00571 JString JTime::printStamp() const {
00572 if (!valid)
00573 return "n/a";
00574 JString str = printDateSortable();
00575 str += " ";
00576 str += printTime();
00577 return (str);
00578 }
00579
00580 JString JTime::print() {
00581 if (!valid)
00582 return "n/a";
00583 JString str = printDateLong();
00584 str += " ";
00585 str += printTime();
00586 return (str);
00587 }
00588
00589 JString JTime::toHTTP() const {
00590
00591
00592 struct tm *newtime;
00593
00594 time_t tp = timebuffer.time;
00595
00596 newtime = gmtime(&tp);
00597
00598 JString str;
00599
00600 if (newtime->tm_wday == 0)
00601 str += "Sun";
00602 else if (newtime->tm_wday == 1)
00603 str += "Mon";
00604 else if (newtime->tm_wday == 2)
00605 str += "Tue";
00606 else if (newtime->tm_wday == 3)
00607 str += "Wed";
00608 else if (newtime->tm_wday == 4)
00609 str += "Thu";
00610 else if (newtime->tm_wday == 5)
00611 str += "Fri";
00612 else if (newtime->tm_wday == 6)
00613 str += "Sat";
00614
00615 str += JString(", ") + JString(newtime->tm_mday, 2) + " ";
00616
00617 if (newtime->tm_mon == 0)
00618 str += "Jan";
00619 else if (newtime->tm_mon == 1)
00620 str += "Feb";
00621 else if (newtime->tm_mon == 2)
00622 str += "Mar";
00623 else if (newtime->tm_mon == 3)
00624 str += "Apr";
00625 else if (newtime->tm_mon == 4)
00626 str += "May";
00627 else if (newtime->tm_mon == 5)
00628 str += "Jun";
00629 else if (newtime->tm_mon == 6)
00630 str += "Jul";
00631 else if (newtime->tm_mon == 7)
00632 str += "Aug";
00633 else if (newtime->tm_mon == 8)
00634 str += "Sep";
00635 else if (newtime->tm_mon == 9)
00636 str += "Oct";
00637 else if (newtime->tm_mon == 10)
00638 str += "Nov";
00639 else if (newtime->tm_mon == 11)
00640 str += "Dec";
00641
00642 str += JString(" ") + JString(newtime->tm_year+1900) + " ";
00643
00644 str += JString(newtime->tm_hour, 2) + JString(":") + JString(newtime->tm_min, 2) + JString(":") + JString(newtime->tm_sec, 2) + " GMT";
00645
00646 return str;
00647 }
00648
00649 bool JTime::fromHTTP(const JString& text) {
00650
00651 int offset = 0;
00652 if (text.contains("GMT"))
00653 offset = 0;
00654
00655 Collection col = text.splitOnWhiteSpaces();
00656 if (col.getCount() < 6) {
00657 setInvalid();
00658 return false;
00659 }
00660
00661 Collection tcol = col.get(4).split(";");
00662 if (tcol.getCount() < 3) {
00663 setInvalid();
00664 return false;
00665 }
00666 int hour = tcol.get(0).toInt();
00667 int min = tcol.get(1).toInt();
00668 int sec = tcol.get(2).toInt();
00669 int day = col.get(1).toInt();
00670 int year = col.get(3).toInt();
00671
00672 int month;
00673 JString monthName = col.get(2);
00674 if (monthName.equalsIgnoreCase("jan"))
00675 month = 1;
00676 else if (monthName.equalsIgnoreCase("feb"))
00677 month = 2;
00678 else if (monthName.equalsIgnoreCase("mar"))
00679 month = 3;
00680 else if (monthName.equalsIgnoreCase("apr"))
00681 month = 4;
00682 else if (monthName.equalsIgnoreCase("may"))
00683 month = 5;
00684 else if (monthName.equalsIgnoreCase("jun"))
00685 month = 6;
00686 else if (monthName.equalsIgnoreCase("jul"))
00687 month = 7;
00688 else if (monthName.equalsIgnoreCase("aug"))
00689 month = 8;
00690 else if (monthName.equalsIgnoreCase("sep"))
00691 month = 9;
00692 else if (monthName.equalsIgnoreCase("oct"))
00693 month = 10;
00694 else if (monthName.equalsIgnoreCase("nov"))
00695 month = 11;
00696 else if (monthName.equalsIgnoreCase("dec"))
00697 month = 12;
00698 else {
00699 setInvalid();
00700 return false;
00701 }
00702
00703 return setTime(year, month, day, hour, min, sec);
00704 }
00705
00706 bool JTime::setTime(int year, int month, int day, int hour, int min, int sec, int ms) {
00707
00708 #ifdef WIN32
00709
00710 TIME_ZONE_INFORMATION tzi;
00711 DWORD zone = GetTimeZoneInformation(&tzi);
00712 bool isDST = false;
00713
00714 if (zone == TIME_ZONE_ID_DAYLIGHT)
00715 isDST = true;
00716
00717
00718
00719
00720
00721
00722
00723 SYSTEMTIME st;
00724 st.wMilliseconds = ms;
00725 st.wSecond = sec;
00726 st.wMinute = min;
00727 st.wHour = hour;
00728 st.wDay = day;
00729 st.wMonth = month;
00730 st.wYear = year;
00731
00732 FILETIME ft;
00733 SystemTimeToFileTime(&st, &ft);
00734 if (isDST)
00735 *this = JTime(ft) + (1000*60*(tzi.Bias-60));
00736 else
00737 *this = JTime(ft) + (1000*60*tzi.Bias);
00738 this->timebuffer.millitm = ms;
00739 perfCount.QuadPart = 0;
00740 #else
00741 struct tm *newtime;
00742 ftime( &timebuffer );
00743 time_t* tp = & (timebuffer.time );
00744 newtime = localtime(tp);
00745
00746 if (year > 1900)
00747 newtime->tm_year = year - 1900;
00748 else if (year < 30)
00749 newtime->tm_year = year + 100;
00750 else
00751 newtime->tm_year = year;
00752
00753 newtime->tm_mon = month-1;
00754 newtime->tm_mday = day;
00755 newtime->tm_hour = hour;
00756 newtime->tm_min = min;
00757 newtime->tm_sec = sec;
00758
00759 time_t t = mktime(newtime);
00760 if ((int)t <= 0) {
00761 setInvalid();
00762 return false;
00763 }
00764 timebuffer.time = t;
00765 timebuffer.millitm = ms;
00766 perfCount.tv_sec = 0;
00767 #endif
00768
00769 return true;
00770 }
00771
00772 double JTime::ms() const {
00773 if (!valid)
00774 return 0;
00775 double d = (double) timebuffer.time;
00776 d = d * 1000;
00777 return(d + timebuffer.millitm);
00778 }
00779
00780 JString JTime::asText() const {
00781 if (!valid)
00782 return "";
00783 if (atomicOffset > 0)
00784 return JString::format("%d%.3d.%d", (long)timebuffer.time, (int)timebuffer.millitm, atomicOffset);
00785 else
00786 return JString::format("%d%.3d", (long)timebuffer.time, (int)timebuffer.millitm);
00787
00788
00789
00790 }
00791
00792 long JTime::seconds() const {
00793 if (!valid)
00794 return 0;
00795 return (long) timebuffer.time;
00796 }
00797
00798 int JTime::milliseconds() const {
00799 if (!valid)
00800 return 0;
00801 return timebuffer.millitm;
00802 }
00803
00804
00805 long JTime::getAge() const {
00806 return (long)(getMicroAge()/1000);
00807 }
00808
00809 long long JTime::getMicroAge() const {
00810 if (!valid)
00811 return -1;
00812
00813 struct timeb tb;
00814 ftime( &tb );
00815
00816 long long s = (long long)(tb.time - timebuffer.time);
00817 int ms = tb.millitm - timebuffer.millitm;
00818
00819 if (abs((long)s) >= 60) {
00820 return ((s*1000) + ms)*1000;
00821 }
00822
00823 #ifdef WIN32
00824 LARGE_INTEGER newPerfCount;
00825 if (QueryPerformanceCounter(&newPerfCount) == 0) {
00826 FILETIME ft;
00827 SYSTEMTIME st;
00828 GetLocalTime(&st);
00829 SystemTimeToFileTime(&st, &ft);
00830 newPerfCount = *(LARGE_INTEGER*)&ft;
00831 }
00832 #else
00833 struct timeval newPerfCount;
00834 struct timezone tmzone;
00835 gettimeofday(&newPerfCount, &tmzone);
00836 #endif // WIN32
00837
00838
00839
00840
00841 long long micro = 0;
00842
00843 #ifdef WIN32
00844 if ( (newPerfCount.QuadPart == 0) || (perfCount.QuadPart == 0) ) {
00845 return ((s*1000) + ms)*1000;
00846 }
00847 __int64 ticks = (((__int64) newPerfCount.QuadPart) - ((__int64) perfCount.QuadPart));
00848 LARGE_INTEGER perfFreq;
00849 QueryPerformanceFrequency(&perfFreq);
00850
00851 ticks = ticks * 1000000;
00852 micro = (long) (ticks / perfFreq.QuadPart);
00853 #else
00854 if ( (newPerfCount.tv_sec == 0) || (perfCount.tv_sec == 0) ) {
00855 return ((s*1000) + ms)*1000;
00856 }
00857 long long sec = newPerfCount.tv_sec - perfCount.tv_sec;
00858 micro = (sec*1000000) + (newPerfCount.tv_usec - perfCount.tv_usec);
00859
00860 #endif
00861 return micro;
00862 }
00863
00864 bool JTime::isOlderThan(long ms) const {
00865 return (getAge() > ms);
00866 }
00867
00868
00869
00870
00871 bool JTime::operator>(const JTime &t) const {
00872 return (this->compare(&t) == 1);
00873
00874
00875
00876
00877
00878
00879
00880
00881 return false;
00882 }
00883
00884 bool JTime::operator>=(const JTime &t) const {
00885 int c = this->compare(&t);
00886 return (c != -1);
00887
00888
00889
00890
00891
00892
00893
00894
00895 return false;
00896 }
00897
00898 bool JTime::operator<(const JTime &t) const {
00899 return (this->compare(&t) == -1);
00900
00901
00902
00903
00904
00905
00906
00907
00908 return false;
00909 }
00910
00911 bool JTime::operator<=(const JTime &t) const {
00912 int c = this->compare(&t);
00913 return (c != 1);
00914
00915
00916
00917
00918
00919
00920
00921
00922 return false;
00923 }
00924
00925 bool JTime::operator==(const JTime &t) const {
00926 return (this->compare(&t) == 0);
00927
00928
00929
00930
00931
00932
00933 }
00934
00935 bool JTime::operator!=(const JTime &t) const {
00936 return (this->compare(&t) != 0);
00937
00938
00939
00940
00941
00942
00943 }
00944
00945
00946 long JTime::operator-(const JTime &t) const {
00947 if ((!valid) || (!t.valid))
00948 return 0;
00949 int ms = milliseconds() - t.milliseconds();
00950 long s = seconds() - t.seconds();
00951 if (abs(s) < 120)
00952 return (long)(this->microDifference(t) * 0.001);
00953 else
00954 return (s*1000) + ms;
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967 JTime JTime::operator-(long long millis) const {
00968 JTime t = (*this);
00969 if ((!valid) || (!t.valid)) {
00970 t.setInvalid();
00971 return t;
00972 }
00973 t.addMilliseconds(0 - millis);
00974 return t;
00975 }
00976
00977
00978
00979
00980
00981
00982
00983
00984 const JTime& JTime::operator-=(long long millis) {
00985 if (!valid)
00986 return *this;
00987 addMilliseconds(0 - millis);
00988 return *this;
00989 }
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001 JTime JTime::operator+(long long millis) const {
01002 JTime t = (*this);
01003 if ((!valid) || (!t.valid)) {
01004 t.setInvalid();
01005 return t;
01006 }
01007 t.addMilliseconds(millis);
01008 return t;
01009 }
01010
01011
01012
01013
01014
01015
01016
01017
01018 const JTime& JTime::operator+=(long long millis) {
01019 if (!valid)
01020 return *this;
01021 addMilliseconds(millis);
01022 return *this;
01023 }
01024
01025 bool JTime::equals(const Object* o2) const {
01026 if (!isSameClass(o2))
01027 return false;
01028 return (compare(o2) == 0);
01029 }
01030
01031 int JTime::compare(const Object* o2) const {
01032 if (!valid)
01033 return 0;
01034 if (!isSameClass(o2))
01035 return 0;
01036
01037 try {
01038 long c = this->microDifference(*(JTime*) o2);
01039 if (c > 0)
01040 return 1;
01041 else if (c == 0) {
01042 if (this->atomicOffset > ((JTime*) o2)->atomicOffset)
01043 return 1;
01044 else if (this->atomicOffset == ((JTime*) o2)->atomicOffset)
01045 return 0;
01046 else
01047 return -1;
01048 }
01049 }
01050 catch(...) {}
01051 return -1;
01052 }
01053
01054
01055
01056 JString JTime::toXML() {
01057 return toXML("time");
01058
01059
01060 }
01061
01062 JString JTime::toXML(const JString& tagname, const JString& params) {
01063 setLocalTimeZoneInformation();
01064 if (!valid) {
01065 return JString::format("<%s %s tzc=\"%s\"/>", (char*) tagname.xmlStringEncode(), (char*) params, (char*) tzc);
01066 }
01067 if (atomicOffset > 0)
01068 return JString::format("<%s %s sec=\"%d\" msec=\"%d\" tzc=\"%s\" atomicoffset=\"%d\" />",
01069 (char*) tagname.xmlStringEncode(), (char*) params,
01070 (int)timebuffer.time, (int) timebuffer.millitm, (char*) tzc, atomicOffset);
01071 else
01072 return JString::format("<%s %s sec=\"%d\" msec=\"%d\" tzc=\"%s\" />",
01073 (char*) tagname.xmlStringEncode(), (char*) params,
01074 (int)timebuffer.time, (int) timebuffer.millitm, (char*) tzc);
01075 }
01076
01077
01078 bool JTime::fromXML(XMLNode* node) {
01079 if (node == NULL) {
01080 return false;
01081 }
01082
01083
01084
01085 if (node->hasAttribute("atomicoffset"))
01086 atomicOffset = node->getAttribute("atomicoffset").toInt();
01087 tzc = node->getAttribute("tzc");
01088
01089
01090
01091 if (!node->hasAttribute("sec")) {
01092 valid = false;
01093 #ifdef WIN32
01094 perfCount.QuadPart = 0;
01095 #else
01096 perfCount.tv_sec = 0;
01097 #endif // WIN32
01098 return true;
01099 }
01100
01101 struct timeb tb;
01102 tb.time = (time_t) node->getAttribute("sec").toInt();
01103
01104 JString msstring = node->getAttribute("msec");
01105 if (msstring.length() == 0)
01106 msstring = node->getAttribute("ms");
01107 if (msstring.length() > 0)
01108 tb.millitm = (unsigned short) msstring.toInt();
01109 else
01110 tb.millitm = 0;
01111
01112
01113
01114
01115
01116
01117
01118 timebuffer = tb;
01119
01120 #ifdef WIN32
01121 perfCount.QuadPart = 0;
01122 #else
01123 perfCount.tv_sec = 0;
01124 #endif // WIN32
01125
01126 valid = true;
01127 return true;
01128 }
01129
01130
01131
01132
01133
01134
01135
01136 bool JTime::addMilliseconds(long long millis) {
01137 if (!valid)
01138 return false;
01139
01140 long long sec = millis/1000;
01141 int ms = (int) (millis - (sec*1000));
01142
01143
01144
01145
01146
01147 if (millis > 0) {
01148 if (ms + timebuffer.millitm >= 1000) {
01149 ms -= 1000;
01150 sec++;
01151 }
01152 }
01153 else {
01154 if (timebuffer.millitm - ms < 0) {
01155 ms += 1000;
01156 sec--;
01157 }
01158
01159
01160 }
01161
01162 timebuffer.time += sec;
01163 timebuffer.millitm += ms;
01164 #ifdef WIN32
01165 perfCount.QuadPart = 0;
01166 #else
01167 perfCount.tv_sec = 0;
01168 #endif // WIN32
01169
01170 return true;
01171 }
01172
01173
01174 long JTime::microDifference(const JTime& t) const {
01175
01176 if (!valid)
01177 return 0;
01178
01179 long s = seconds() - t.seconds();
01180 int ms = milliseconds() - t.milliseconds();
01181 if (abs(s) >= 120) {
01182 return ((s*1000) + ms)*1000;
01183 }
01184
01185 long micro = 0;
01186
01187 #ifdef WIN32
01188
01189
01190
01191
01192
01193 if ( (perfCount.QuadPart == 0) || (t.perfCount.QuadPart == 0) ) {
01194
01195
01196 return ((s*1000) + ms)*1000;
01197 }
01198 __int64 ticks = (((__int64) perfCount.QuadPart) - ((__int64) t.perfCount.QuadPart));
01199 LARGE_INTEGER perfFreq;
01200 QueryPerformanceFrequency(&perfFreq);
01201
01202 ticks = ticks * 1000000;
01203 micro = (long) (ticks / perfFreq.QuadPart);
01204
01205
01206 #else
01207 if ( (perfCount.tv_sec == 0) || (t.perfCount.tv_sec == 0) ) {
01208 return ((s*1000) + ms)*1000;
01209 }
01210 long sec = perfCount.tv_sec - t.perfCount.tv_sec;
01211 micro = (sec*1000000) + (perfCount.tv_usec - t.perfCount.tv_usec);
01212
01213 #endif
01214
01215 return micro;
01216 }
01217
01218 bool JTime::unitTest() {
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236 JTime t1 = JTime();
01237 JTime t2;
01238 wait(100);
01239 t2 = JTime();
01240
01241
01242
01243 long dif = t2 - t1;
01244 if (dif <= 0) {
01245 printf("Normal diff failed: %d\n", (int)dif);
01246 return false;
01247 }
01248
01249
01250 dif = t2.microDifference(t1);
01251 if (dif <= 0) {
01252 printf("Micro diff failed: %d\n", (int)dif);
01253 return false;
01254 }
01255
01256
01257
01258 t2 = t1 + 10;
01259 if (t2-t1 != 10)
01260 return false;
01261
01262 t2 = t1 - 10;
01263 if (t2-t1 != -10)
01264 return false;
01265
01266 t2 = t1 + 100010;
01267 if (t2-t1 != 100010)
01268 return false;
01269
01270 t2 = t1 - 100010;
01271 if (t2-t1 != -100010)
01272 return false;
01273
01274 return true;
01275 }
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 #ifdef WIN32
01295
01296 JTime::JTime(FILETIME filetime) {
01297 timebuffer = JTime::filetime2timeb(&filetime);
01298 perfCount.QuadPart = 0;
01299 }
01300
01301 #ifdef CYGWIN
01302 #define FACTOR (0x19db1ded53ea710LL)
01303 #else
01304 #define FACTOR (0x19db1ded53ea710)
01305 #endif
01306 #define NSPERSEC 10000000
01307 #define NSPERMS 10000
01308
01309 long JTime::filetime2time_t(FILETIME * ptr) {
01310 struct timeb t = filetime2timeb(ptr);
01311 return (long)t.time;
01312 }
01313
01314 FILETIME JTime::time_t2filetime(time_t t)
01315 {
01316 struct timeb tb;
01317 tb.time = t;
01318 tb.millitm = 0;
01319 return timeb2filetime(tb);
01320 }
01321
01322 struct timeb JTime::filetime2timeb(FILETIME * ptr)
01323 {
01324
01325
01326
01327
01328 long rem;
01329 __int64 x = ((__int64) ptr->dwHighDateTime << 32) + ((unsigned) ptr->dwLowDateTime);
01330 x -= FACTOR;
01331 rem = (long) (x % ((__int64) NSPERMS));
01332 rem += (NSPERMS / 2);
01333 x /= (__int64) NSPERMS;
01334 x += (__int64) (rem / NSPERMS);
01335
01336
01337 struct timeb t;
01338 t.dstflag = 0;
01339 t.timezone = 0;
01340 t.millitm = (unsigned short) x % 1000;
01341 t.time = (int) (x / 1000);
01342
01343 return t;
01344 }
01345
01346 FILETIME JTime::timeb2filetime(struct timeb tb)
01347 {
01348
01349
01350
01351
01352
01353 __int64 val = (__int64)((__int64)tb.time*1000 + (__int64)tb.millitm)*10000;
01354
01355 val += FACTOR;
01356
01357 FILETIME ptr;
01358 ptr.dwHighDateTime = (unsigned long) (val >> 32);
01359 ptr.dwLowDateTime = (unsigned long) val;
01360
01361 return ptr;
01362 }
01363
01364 #endif
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382 StopWatch::StopWatch() {
01383 reset();
01384 }
01385
01386 StopWatch::~StopWatch() {
01387 }
01388
01389 Object* StopWatch::clone() const {
01390 StopWatch* sw = new StopWatch();
01391 sw->timeStarted = timeStarted;
01392 sw->timeStopped = timeStopped;
01393 sw->marks.copyAll(marks);
01394 return sw;
01395 }
01396
01397 bool StopWatch::reset() {
01398 timeStarted.setInvalid();
01399 timeStopped.setInvalid();
01400 return marks.removeAll();
01401 }
01402
01403 bool StopWatch::start() {
01404 timeStarted = JTime();
01405 return true;
01406 }
01407
01408 bool StopWatch::stop() {
01409 if (!timeStarted.isValid())
01410 return false;
01411 timeStopped = JTime();
01412 return true;
01413 }
01414
01415 bool StopWatch::setMark() {
01416 return marks.put(this->createUniqueID("NoLabel_"), new JTime());
01417 }
01418
01419 bool StopWatch::setMark(const JString& label) {
01420
01421 JString newlabel = label;
01422
01423 if (marks.contains(label)) {
01424 int count = 1;
01425 JString origlabel = label;
01426 while (marks.contains(newlabel))
01427 newlabel = JString::format("%s(%d)", (char*) origlabel, count);
01428 }
01429
01430 return marks.put(newlabel, new JTime());
01431 }
01432
01433 JString StopWatch::print() {
01434 int n, l;
01435 int maxwidth = 0;
01436 for (n=0; n<marks.getCount(); n++) {
01437 if ( (l = marks.getKey(n).length()) > maxwidth )
01438 maxwidth = l;
01439 }
01440 JString formatString = JString::format(" %%%ds: %%10.3f\n", maxwidth);
01441 JString markString;
01442
01443 StatSample statSample = getStatSample();
01444
01445 JString key;
01446 if (marks.getCount() > 0) {
01447 for (n=0; n<statSample.getCount(); n++) {
01448 key = marks.getKey(n);
01449 if (key.startsWith("NoLabel_"))
01450 key = "";
01451 else if (n == statSample.getCount()-1)
01452 key = "End";
01453 markString += JString::format(formatString, (char*) key, statSample.values.get(n).toDouble()/1000.0);
01454 }
01455 markString += JString::format(formatString, "Total", ((double)getTotalTime())/1000.0);
01456 return JString::format("Started: %s - Stopped: %s - Mean: %.3f - STD: %.3f \n%s",
01457 (char*) timeStarted.printTimeMS(), (char*) timeStopped.printTimeMS(),
01458 statSample.getMean()/1000.0, statSample.getStandardDeviation()/1000.0, (char*) markString);
01459 }
01460 else {
01461 return JString::format("Started: %s - Stopped: %s - Total: %.3f - Mean: %.3f - STD: %.3f",
01462 (char*) timeStarted.printTimeMS(), (char*) timeStopped.printTimeMS(), ((double)getTotalTime())/1000.0,
01463 statSample.getMean()/1000.0, statSample.getStandardDeviation()/1000.0);
01464 }
01465 }
01466
01467 JString StopWatch::printNoLabels() {
01468 int n, l;
01469 int maxwidth = 0;
01470 for (n=0; n<marks.getCount(); n++) {
01471 if ( (l = marks.getKey(n).length()) > maxwidth )
01472 maxwidth = l;
01473 }
01474 JString formatString = JString::format(" %%10.3f\n", maxwidth);
01475 JString markString;
01476
01477 StatSample statSample = getStatSample();
01478
01479 for (n=0; n<statSample.getCount(); n++) {
01480 markString += JString::format(formatString, statSample.values.get(n).toDouble()/1000.0);
01481 }
01482
01483 return JString::format("Started: %s - Stopped: %s - Mean: %.3f - STD: %.3f \n%s",
01484 (char*) timeStarted.printTimeMS(), (char*) timeStopped.printTimeMS(),
01485 statSample.getMean()/1000.0, statSample.getStandardDeviation()/1000.0, (char*) markString);
01486 }
01487
01488 JString StopWatch::printDetails() {
01489
01490 int n, l;
01491 int maxwidth = 0;
01492 for (n=0; n<marks.getCount(); n++) {
01493 if ( (l = marks.getKey(n).length()) > maxwidth )
01494 maxwidth = l;
01495 }
01496 JString formatString = JString::format(" %%%ds: %%10.3f\n", maxwidth);
01497 JString markString;
01498
01499 StatSample statSample = getStatSample();
01500
01501 JString key;
01502 if (marks.getCount() > 0) {
01503 for (n=0; n<statSample.getCount(); n++) {
01504 key = marks.getKey(n);
01505 if (key.startsWith("NoLabel_"))
01506 key = "";
01507 else if (n == statSample.getCount()-1)
01508 key = "End";
01509 markString += JString::format(formatString, (char*) key, statSample.values.get(n).toDouble()/1000.0);
01510 }
01511 markString += JString::format(formatString, "Total", ((double)getTotalTime())/1000.0);
01512 return JString::format("Started: %s - Stopped: %s - Mean: %.3f - STD: %.3f \n%s\nTimes:\n %s\n",
01513 (char*) timeStarted.printTimeMS(), (char*) timeStopped.printTimeMS(),
01514 statSample.getMean()/1000.0, statSample.getStandardDeviation()/1000.0, (char*) markString,
01515 (char*) marks.printListLine("\n "));
01516 }
01517 else {
01518 return JString::format("Started: %s - Stopped: %s - Total: %.3f - Mean: %.3f - STD: %.3f",
01519 (char*) timeStarted.printTimeMS(), (char*) timeStopped.printTimeMS(), ((double)getTotalTime())/1000.0,
01520 statSample.getMean()/1000.0, statSample.getStandardDeviation()/1000.0);
01521 }
01522 }
01523
01524 long StopWatch::getTotalTime() {
01525 if (!timeStarted.isValid())
01526 return -1;
01527 if (!timeStopped.isValid())
01528 return -1;
01529 return timeStopped.microDifference(timeStarted);
01530 }
01531
01532 long StopWatch::getMarkCount() {
01533 return marks.getCount();
01534 }
01535
01536 long StopWatch::getAverageDistance() {
01537 StatSample statSample = getStatSample();
01538 return (long) statSample.getMean();
01539 }
01540
01541 long StopWatch::getStandardDeviationDistance() {
01542 StatSample statSample = getStatSample();
01543 return (long) statSample.getStandardDeviation();
01544 }
01545
01546 StatSample StopWatch::getStatSample() {
01547 StatSample statSample;
01548 if (!timeStarted.isValid())
01549 return statSample;
01550 if (!timeStopped.isValid())
01551 return statSample;
01552
01553 if (marks.getCount() == 0) {
01554 statSample.add(timeStopped.microDifference(timeStarted));
01555 return statSample;
01556 }
01557
01558 statSample.add(((JTime*)marks.getFirst())->microDifference(timeStarted));
01559 for (int n=1; n<marks.getCount(); n++) {
01560 statSample.add(((JTime*)marks.get(n))->microDifference(*(JTime*)marks.get(n-1)));
01561 }
01562 statSample.add(timeStopped.microDifference(*(JTime*)marks.getLast()));
01563 return statSample;
01564 }
01565
01566
01567
01568
01569
01570
01571
01572
01573 }