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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "TTimeStamp.h"
00040 #include "TString.h"
00041 #include "TError.h"
00042 #include "Riostream.h"
00043 #ifdef R__WIN32
00044 #include "Windows4Root.h"
00045 #else
00046 #include <unistd.h>
00047 #include <sys/time.h>
00048 #endif
00049 #include "TVirtualMutex.h"
00050
00051 ClassImp(TTimeStamp);
00052
00053
00054 TVirtualMutex *gTimeMutex = 0;
00055
00056
00057 ostream& operator<<(ostream& os, const TTimeStamp& ts)
00058 {
00059
00060
00061 if (os.good()) {
00062 if (os.tie()) os.tie()->flush();
00063 os << ts.AsString("c");
00064 }
00065
00066 if (os.flags() & ios::unitbuf) os.flush();
00067 return os;
00068 }
00069
00070
00071 TBuffer &operator>>(TBuffer &buf, TTimeStamp &ts)
00072 {
00073
00074
00075 ts.Streamer(buf);
00076 return buf;
00077 }
00078
00079
00080 TBuffer &operator<<(TBuffer &buf, const TTimeStamp &ts)
00081 {
00082
00083
00084 ((TTimeStamp&)ts).Streamer(buf);
00085 return buf;
00086 }
00087
00088
00089 TTimeStamp::TTimeStamp()
00090 {
00091
00092
00093
00094
00095
00096 Set();
00097 }
00098
00099
00100 TTimeStamp::TTimeStamp(UInt_t year, UInt_t month,
00101 UInt_t day, UInt_t hour,
00102 UInt_t min, UInt_t sec,
00103 UInt_t nsec,
00104 Bool_t isUTC, Int_t secOffset)
00105 {
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
00117 }
00118
00119
00120 TTimeStamp::TTimeStamp(UInt_t date, UInt_t time,
00121 UInt_t nsec,
00122 Bool_t isUTC, Int_t secOffset)
00123 {
00124
00125
00126
00127 Set(date, time, nsec, isUTC, secOffset);
00128 }
00129
00130
00131 TTimeStamp::TTimeStamp(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate)
00132 {
00133
00134
00135
00136
00137
00138 Set(tloc, isUTC, secOffset, dosDate);
00139 }
00140
00141
00142 const Char_t *TTimeStamp::AsString(Option_t *option) const
00143 {
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 const Int_t nbuffers = 8;
00176
00177 static Char_t formatted[nbuffers][64];
00178 static Char_t formatted2[nbuffers][64];
00179
00180 static Int_t ibuffer = nbuffers;
00181
00182 R__LOCKGUARD2(gTimeMutex);
00183
00184 ibuffer = (ibuffer+1)%nbuffers;
00185
00186 TString opt = option;
00187 opt.ToLower();
00188
00189 if (opt.Contains("2")) {
00190
00191 sprintf(formatted[ibuffer], "{%d,%d}", fSec, fNanoSec);
00192 return formatted[ibuffer];
00193 }
00194
00195 #ifdef R__LINUX
00196
00197 const Char_t *kRFC822 = "%a, %d %b %Y %H:%M:%S %z (%Z) +#9ld nsec";
00198 const Char_t *kISO8601 = "%Y-%m-%d %H:%M:%S.#9.9ld%z";
00199 const Char_t *kISO8601Z = "%Y-%m-%d %H:%M:%S.#9.9ldZ";
00200 #else
00201
00202 const Char_t *kRFC822 = "%a, %d %b %Y %H:%M:%S %Z +#9ld nsec";
00203 const Char_t *kISO8601 = "%Y-%m-%d %H:%M:%S.#9.9ld%Z";
00204 const Char_t *kISO8601Z = "%Y-%m-%d %H:%M:%S.#9.9ldZ";
00205 #endif
00206 const Char_t *kSQL = "%Y-%m-%d %H:%M:%S";
00207
00208 Bool_t asLocal = opt.Contains("l");
00209 Bool_t asSQL = opt.Contains("s");
00210 if (asSQL) asLocal = kFALSE;
00211
00212 const Char_t *format = kRFC822;
00213 if (opt.Contains("c")) {
00214 format = kISO8601;
00215 if (!asLocal) format = kISO8601Z;
00216 }
00217 if (asSQL) format = kSQL;
00218
00219
00220 time_t seconds = (time_t) fSec;
00221 #ifdef _REENTRANT
00222 struct tm buf;
00223 struct tm *ptm = (asLocal) ? localtime_r(&seconds, &buf) : gmtime_r(&seconds, &buf);
00224 #else
00225 struct tm *ptm = (asLocal) ? localtime(&seconds) : gmtime(&seconds);
00226 #endif
00227
00228
00229
00230 strftime(formatted[ibuffer], sizeof(formatted[ibuffer]), format, ptm);
00231
00232 if (asSQL) return formatted[ibuffer];
00233
00234
00235 Char_t *ptr = strrchr(formatted[ibuffer], '#');
00236 if (ptr) *ptr = '%';
00237 sprintf(formatted2[ibuffer], formatted[ibuffer], fNanoSec);
00238
00239 return formatted2[ibuffer];
00240 }
00241
00242
00243 void TTimeStamp::Copy(TTimeStamp &ts) const
00244 {
00245
00246
00247 ts.fSec = fSec;
00248 ts.fNanoSec = fNanoSec;
00249 }
00250
00251
00252 UInt_t TTimeStamp::GetDate(Bool_t inUTC, Int_t secOffset,
00253 UInt_t *year, UInt_t *month, UInt_t *day) const
00254 {
00255
00256
00257
00258 time_t atime = fSec + secOffset;
00259 #ifdef _REENTRANT
00260 struct tm buf;
00261 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
00262 #else
00263 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00264 #endif
00265
00266 if (day) *day = ptm->tm_mday;
00267 if (month) *month = ptm->tm_mon + 1;
00268 if (year) *year = ptm->tm_year + 1900;
00269
00270 return (1900+ptm->tm_year)*10000 + (1+ptm->tm_mon)*100 + ptm->tm_mday;
00271 }
00272
00273
00274 UInt_t TTimeStamp::GetTime(Bool_t inUTC, Int_t secOffset,
00275 UInt_t *hour, UInt_t *min, UInt_t *sec) const
00276 {
00277
00278
00279
00280 time_t atime = fSec + secOffset;
00281 #ifdef _REENTRANT
00282 struct tm buf;
00283 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
00284 #else
00285 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00286 #endif
00287
00288 if (hour) *hour = ptm->tm_hour;
00289 if (min) *min = ptm->tm_min;
00290 if (sec) *sec = ptm->tm_sec;
00291
00292 return ptm->tm_hour*10000 + ptm->tm_min*100 + ptm->tm_sec;
00293 }
00294
00295
00296 Int_t TTimeStamp::GetDayOfYear(Bool_t inUTC, Int_t secOffset) const
00297 {
00298
00299
00300
00301 time_t atime = fSec + secOffset;
00302 #ifdef _REENTRANT
00303 struct tm buf;
00304 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
00305 #else
00306 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00307 #endif
00308
00309 Int_t day = ptm->tm_mday;
00310 Int_t month = ptm->tm_mon + 1;
00311 Int_t year = ptm->tm_year + 1900;
00312
00313 return GetDayOfYear(day, month, year);
00314 }
00315
00316
00317 Int_t TTimeStamp::GetDayOfWeek(Bool_t inUTC, Int_t secOffset) const
00318 {
00319
00320
00321
00322 time_t atime = fSec + secOffset;
00323 #ifdef _REENTRANT
00324 struct tm buf;
00325 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
00326 #else
00327 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00328 #endif
00329
00330 Int_t day = ptm->tm_mday;
00331 Int_t month = ptm->tm_mon + 1;
00332 Int_t year = ptm->tm_year + 1900;
00333
00334 return GetDayOfWeek(day, month, year);
00335 }
00336
00337
00338 Int_t TTimeStamp::GetMonth(Bool_t inUTC, Int_t secOffset) const
00339 {
00340
00341
00342 time_t atime = fSec + secOffset;
00343 #ifdef _REENTRANT
00344 struct tm buf;
00345 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
00346 #else
00347 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00348 #endif
00349
00350 return ptm->tm_mon + 1;
00351 }
00352
00353
00354 Int_t TTimeStamp::GetWeek(Bool_t inUTC, Int_t secOffset) const
00355 {
00356
00357
00358
00359
00360 time_t atime = fSec + secOffset;
00361 #ifdef _REENTRANT
00362 struct tm buf;
00363 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
00364 #else
00365 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00366 #endif
00367
00368 Int_t day = ptm->tm_mday;
00369 Int_t month = ptm->tm_mon + 1;
00370 Int_t year = ptm->tm_year + 1900;
00371
00372 return GetWeek(day, month, year);
00373 }
00374
00375
00376 Bool_t TTimeStamp::IsLeapYear(Bool_t inUTC, Int_t secOffset) const
00377 {
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 time_t atime = fSec + secOffset;
00389 #ifdef _REENTRANT
00390 struct tm buf;
00391 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
00392 #else
00393 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00394 #endif
00395
00396 Int_t year = ptm->tm_year + 1900;
00397
00398 return IsLeapYear(year);
00399 }
00400
00401
00402 Int_t TTimeStamp::GetZoneOffset()
00403 {
00404
00405
00406
00407
00408
00409 #ifndef R__WIN32
00410 tzset();
00411 #if defined(R__WINGCC)
00412 return _timezone;
00413 #else
00414 #if !defined(R__MACOSX) && !defined(R__FBSD) && !defined(R__OBSD)
00415 return timezone;
00416 #else
00417 time_t tp = 0;
00418 time(&tp);
00419 #ifdef _REENTRANT
00420 struct tm buf;
00421 return -localtime_r(&tp, &buf)->tm_gmtoff;
00422 #else
00423 return -localtime(&tp)->tm_gmtoff;
00424 #endif
00425 #endif
00426 #endif
00427 #else
00428 _tzset();
00429 return _timezone;
00430 #endif
00431 }
00432
00433
00434 void TTimeStamp::Add(const TTimeStamp &offset)
00435 {
00436
00437
00438 fSec += offset.fSec;
00439 fNanoSec += offset.fNanoSec;
00440 NormalizeNanoSec();
00441 }
00442
00443
00444 void TTimeStamp::Print(Option_t *option) const
00445 {
00446
00447
00448 printf("Date/Time = %s\n", AsString(option));
00449 }
00450
00451
00452 void TTimeStamp::Set()
00453 {
00454
00455
00456
00457
00458
00459
00460 #ifdef R__WIN32
00461 ULARGE_INTEGER time;
00462 GetSystemTimeAsFileTime((FILETIME *)&time);
00463
00464
00465
00466 fNanoSec = Int_t((time.QuadPart * (unsigned __int64) 100) %
00467 (unsigned __int64) 1000000000);
00468 time.QuadPart -=
00469 (unsigned __int64) (1000*1000*10)
00470 * (unsigned __int64) (60 * 60 * 24)
00471 * (unsigned __int64) (134774);
00472
00473 fSec = Int_t(time.QuadPart/(unsigned __int64) (1000*1000*10));
00474 #else
00475 struct timeval tp;
00476 gettimeofday(&tp, 0);
00477 fSec = tp.tv_sec;
00478 fNanoSec = tp.tv_usec*1000;
00479 #endif
00480
00481 static Int_t sec = 0, nsec = 0, fake_ns = 0;
00482
00483 R__LOCKGUARD2(gTimeMutex);
00484
00485 if (fSec == sec && fNanoSec == nsec)
00486 fNanoSec += ++fake_ns;
00487 else {
00488 fake_ns = 0;
00489 sec = fSec;
00490 nsec = fNanoSec;
00491 }
00492 }
00493
00494
00495 void TTimeStamp::Set(Int_t year, Int_t month, Int_t day,
00496 Int_t hour, Int_t min, Int_t sec,
00497 Int_t nsec, Bool_t isUTC, Int_t secOffset)
00498 {
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 if (year <= 37) year += 2000;
00514 if (year >= 70 && year <= 137) year += 1900;
00515
00516 if (year >= 1900) year -= 1900;
00517
00518 struct tm tmstruct;
00519 tmstruct.tm_year = year;
00520 tmstruct.tm_mon = month-1;
00521 tmstruct.tm_mday = day;
00522 tmstruct.tm_hour = hour;
00523 tmstruct.tm_min = min;
00524 tmstruct.tm_sec = sec + secOffset;
00525 tmstruct.tm_isdst = -1;
00526
00527 const time_t bad_time_t = (time_t) -1;
00528
00529
00530
00531
00532 time_t utc_sec = (isUTC) ? MktimeFromUTC(&tmstruct) : mktime(&tmstruct);
00533
00534 if (utc_sec == bad_time_t)
00535 Error("TTimeStamp::Set","mktime returned -1");
00536
00537 fSec = utc_sec;
00538 fNanoSec = nsec;
00539
00540 NormalizeNanoSec();
00541 }
00542
00543
00544 void TTimeStamp::Set(Int_t date, Int_t time, Int_t nsec,
00545 Bool_t isUTC, Int_t secOffset)
00546 {
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 Int_t year = date/10000;
00563 Int_t month = (date-year*10000)/100;
00564 Int_t day = date%100;
00565
00566
00567 const Int_t oneday = 240000;
00568 while (time < 0) {
00569 time += oneday;
00570 day -= 1;
00571 }
00572 while (time > oneday) {
00573 time -= oneday;
00574 day += 1;
00575 }
00576 Int_t hour = time/10000;
00577 Int_t min = (time-hour*10000)/100;
00578 Int_t sec = time%100;
00579
00580 Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
00581 }
00582
00583
00584 void TTimeStamp::Set(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate)
00585 {
00586
00587
00588
00589
00590
00591 struct tm localtm;
00592 memset (&localtm, 0, sizeof (localtm));
00593
00594 if (dosDate) {
00595 localtm.tm_year = ((tloc >> 25) & 0x7f) + 80;
00596 localtm.tm_mon = ((tloc >> 21) & 0xf);
00597 localtm.tm_mday = (tloc >> 16) & 0x1f;
00598 localtm.tm_hour = (tloc >> 11) & 0x1f;
00599 localtm.tm_min = (tloc >> 5) & 0x3f;
00600 localtm.tm_sec = (tloc & 0x1f) * 2 + secOffset;
00601 localtm.tm_isdst = -1;
00602 } else {
00603 time_t t = (time_t) tloc;
00604 #ifdef _REENTRANT
00605 struct tm tpa;
00606 struct tm *tp = localtime_r(&t, &tpa);
00607 #else
00608 struct tm *tp = localtime(&t);
00609 #endif
00610 localtm.tm_year = tp->tm_year;
00611 localtm.tm_mon = tp->tm_mon;
00612 localtm.tm_mday = tp->tm_mday;
00613 localtm.tm_hour = tp->tm_hour;
00614 localtm.tm_min = tp->tm_min;
00615 localtm.tm_sec = tp->tm_sec + secOffset;
00616 localtm.tm_isdst = -1;
00617 }
00618
00619 const time_t bad_time_t = (time_t) -1;
00620
00621
00622
00623
00624 time_t utc_sec = (isUTC && dosDate) ? MktimeFromUTC(&localtm) : mktime(&localtm);
00625
00626 if (utc_sec == bad_time_t)
00627 Error("TTimeStamp::Set","mktime returned -1");
00628
00629 fSec = utc_sec;
00630 fNanoSec = 0;
00631
00632 NormalizeNanoSec();
00633 }
00634
00635
00636 void TTimeStamp::NormalizeNanoSec()
00637 {
00638
00639
00640 const Int_t kNsPerSec = 1000000000;
00641
00642 while (fNanoSec < 0) {
00643 fNanoSec += kNsPerSec;
00644 fSec -= 1;
00645 }
00646
00647
00648 while (fNanoSec >= kNsPerSec) {
00649 fNanoSec -= kNsPerSec;
00650 fSec += 1;
00651 }
00652 }
00653
00654
00655 time_t TTimeStamp::MktimeFromUTC(tm_t *tmstruct)
00656 {
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 Int_t daysInMonth[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00669 Int_t year = tmstruct->tm_year + 1900;
00670 daysInMonth[1] = IsLeapYear(year) ? 29 : 28;
00671
00672
00673
00674 Int_t &ref_tm_mon = tmstruct->tm_mon;
00675 Int_t &ref_tm_mday = tmstruct->tm_mday;
00676
00677 tmstruct->tm_yday = 0;
00678 for (Int_t imonth = 0; imonth < ref_tm_mon; imonth++) {
00679 tmstruct->tm_yday += daysInMonth[imonth];
00680 }
00681 tmstruct->tm_yday += ref_tm_mday - 1;
00682
00683
00684 while (ref_tm_mday > daysInMonth[ref_tm_mon]) {
00685 ref_tm_mday -= daysInMonth[ref_tm_mon];
00686 ref_tm_mon++;
00687 }
00688
00689
00690
00691
00692 tmstruct->tm_isdst = 0;
00693
00694
00695
00696
00697 Int_t utc_sec = tmstruct->tm_sec +
00698 tmstruct->tm_min*60 +
00699 tmstruct->tm_hour*3600 +
00700 tmstruct->tm_yday*86400 +
00701 (tmstruct->tm_year-70)*31536000 +
00702 ((tmstruct->tm_year-69)/4)*86400;
00703
00704 return utc_sec;
00705 }
00706
00707
00708 Int_t TTimeStamp::GetDayOfYear(Int_t day, Int_t month, Int_t year)
00709 {
00710
00711
00712
00713 Int_t dayOfYear = 0;
00714 Int_t daysInMonth[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00715 daysInMonth[1] = IsLeapYear(year) ? 29 : 28;
00716
00717 for (Int_t i = 0; i < (month - 1); i++)
00718 dayOfYear += daysInMonth[i];
00719 dayOfYear += day;
00720
00721 return dayOfYear;
00722 }
00723
00724
00725 Int_t TTimeStamp::GetDayOfWeek(Int_t day, Int_t month, Int_t year)
00726 {
00727
00728
00729
00730 Int_t dayno;
00731
00732 if (month < 3) {
00733 year--;
00734 month += 12;
00735 }
00736
00737 dayno = 1 + day + 2*month + 3*(month + 1)/5 + year + year/4 - year/100 + year/400;
00738 dayno %= 7;
00739
00740
00741 return ((dayno == 0) ? 7 : dayno);
00742 }
00743
00744
00745 Int_t TTimeStamp::GetWeek(Int_t day, Int_t month, Int_t year)
00746 {
00747
00748
00749
00750
00751 Int_t dayOfYear = GetDayOfYear(day, month, year);
00752 Int_t dayJan1st = GetDayOfWeek(1, 1, year);
00753 Int_t week = (dayOfYear + dayJan1st - 2) / 7 + 1;
00754
00755 if (dayJan1st > 4)
00756 week--;
00757
00758 if (week == 53) {
00759 Int_t dayNextJan1st = GetDayOfWeek(1, 1, year + 1);
00760 if (dayNextJan1st > 1 && dayNextJan1st < 5) {
00761 year++;
00762 week = 1;
00763 }
00764 } else if (week == 0) {
00765 Int_t dayPrevJan1st = GetDayOfWeek(1, 1, year - 1);
00766 week = (dayPrevJan1st < 5 && dayJan1st > 4) ? 53 : 52;
00767 year--;
00768 }
00769 return year * 100 + week;
00770 }
00771
00772
00773 Bool_t TTimeStamp::IsLeapYear(Int_t year)
00774 {
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 return (year % 4 == 0) && !((year % 100 == 0) && (year % 400 > 0));
00786 }
00787
00788
00789 void TTimeStamp::DumpTMStruct(const tm_t &tmstruct)
00790 {
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 printf(" tm { year %4d, mon %2d, day %2d,\n",
00803 tmstruct.tm_year,
00804 tmstruct.tm_mon,
00805 tmstruct.tm_mday);
00806 printf(" hour %2d, min %2d, sec %2d,\n",
00807 tmstruct.tm_hour,
00808 tmstruct.tm_min,
00809 tmstruct.tm_sec);
00810 printf(" wday %2d, yday %3d, isdst %2d",
00811 tmstruct.tm_wday,
00812 tmstruct.tm_yday,
00813 tmstruct.tm_isdst);
00814 #if (defined(linux) && !defined(R__WINGCC)) || defined(R__MACOSX)
00815 printf(",\n tm_gmtoff %6ld, tm_zone \"%s\"",
00816 #if defined(__USE_BSD) || defined(R__MACOSX)
00817 tmstruct.tm_gmtoff, tmstruct.tm_zone);
00818 #else
00819 tmstruct.__tm_gmtoff, tmstruct.__tm_zone);
00820 #endif
00821 #endif
00822 printf(" }\n");
00823 }