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
00029
00030 #include "Validity/VldTimeStamp.h"
00031
00032 #include "MessageService/MsgService.h"
00033 CVSID("$Id: VldTimeStamp.cxx,v 1.25 2005/06/02 16:53:36 rhatcher Exp $");
00034
00035 #ifdef R__WIN32
00036 #include "Windows4Root.h"
00037 #else
00038 #include <unistd.h>
00039
00040 #include <sys/time.h>
00041 #endif
00042
00043 #include "TString.h"
00044
00045 ClassImp(VldTimeStamp)
00046
00047 const Int_t kNsPerSec = 1000000000;
00048
00049
00050 std::ostream& operator<<(std::ostream& os, const VldTimeStamp& ts)
00051 {
00052 if (os.good()) {
00053 if (os.tie()) os.tie()->flush();
00054 os << ts.AsString("c");
00055 }
00056
00057 if (os.flags() & std::ios::unitbuf) os.flush();
00058 return os;
00059 }
00060
00061 VldTimeStamp VldTimeStamp::GetBOT()
00062 {
00063 return VldTimeStamp(0,0);
00064 }
00065
00066 VldTimeStamp VldTimeStamp::GetEOT()
00067 {
00068 return VldTimeStamp((1<<31)-1,0);
00069 }
00070
00071
00072
00073
00074
00075
00076
00077 VldTimeStamp::VldTimeStamp() { Set(); }
00078 VldTimeStamp::~VldTimeStamp() { ; }
00079
00080
00081 VldTimeStamp::VldTimeStamp(UInt_t year, UInt_t month,
00082 UInt_t day, UInt_t hour,
00083 UInt_t min, UInt_t sec,
00084 UInt_t nsec,
00085 Bool_t isUTC, Int_t secOffset)
00086 {
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
00098 }
00099
00100
00101 VldTimeStamp::VldTimeStamp(UInt_t date, UInt_t time, UInt_t nsec,
00102 Bool_t isUTC, Int_t secOffset)
00103 {
00104
00105
00106
00107 Set(date, time, nsec, isUTC, secOffset);
00108 }
00109
00110
00111 const char *VldTimeStamp::AsString(Option_t *option) const
00112 {
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 const int nbuffers = 8;
00146
00147 static char formatted[nbuffers][64];
00148 static char formatted2[nbuffers][64];
00149 static int ibuffer = nbuffers;
00150 ibuffer = (ibuffer+1)%nbuffers;
00151
00152 TString opt = option;
00153 opt.ToLower();
00154
00155 if (opt.Contains("2")) {
00156
00157 sprintf(formatted[ibuffer], "{%d,%d}", fSec, fNanoSec);
00158 return formatted[ibuffer];
00159 }
00160
00161 #ifdef linux
00162
00163 const char *RFC822 = "%a, %d %b %Y %H:%M:%S %z (%Z) +#9ld nsec";
00164 const char *ISO8601 = "%Y-%m-%d %H:%M:%S.#9.9ld%z";
00165 const char *ISO8601Z = "%Y-%m-%d %H:%M:%S.#9.9ldZ";
00166 #else
00167
00168 const char *RFC822 = "%a, %d %b %Y %H:%M:%S %Z +#9ld nsec";
00169 const char *ISO8601 = "%Y-%m-%d %H:%M:%S.#9.9ld%Z";
00170 const char *ISO8601Z = "%Y-%m-%d %H:%M:%S.#9.9ldZ";
00171 #endif
00172 const char *SQL = "%Y-%m-%d %H:%M:%S";
00173
00174 Bool_t asLocal = opt.Contains("l");
00175 Bool_t asSQL = opt.Contains("s");
00176 if (asSQL) asLocal = kFALSE;
00177
00178 const char *format = RFC822;
00179 if (opt.Contains("c")) {
00180 format = ISO8601;
00181 if (!asLocal) format = ISO8601Z;
00182 }
00183 if (asSQL) format = SQL;
00184
00185 struct tm *ptm;
00186 time_t seconds = (time_t) fSec;
00187
00188
00189
00190
00191 ptm = (asLocal) ? localtime(&seconds) : gmtime(&seconds);
00192
00193
00194
00195 strftime(formatted[ibuffer], sizeof(formatted[ibuffer]), format, ptm);
00196
00197 if (asSQL) return formatted[ibuffer];
00198
00199
00200 char *ptr = strrchr(formatted[ibuffer], '#');
00201 if (ptr) *ptr = '%';
00202 sprintf(formatted2[ibuffer], formatted[ibuffer], fNanoSec);
00203
00204 return formatted2[ibuffer];
00205 }
00206
00207
00208 void VldTimeStamp::Copy(VldTimeStamp &ts) const
00209 {
00210
00211
00212 ts.fSec = fSec;
00213 ts.fNanoSec = fNanoSec;
00214
00215 }
00216
00217
00218 Int_t VldTimeStamp::GetDate(Bool_t inUTC, Int_t secOffset,
00219 UInt_t* year, UInt_t* month, UInt_t* day) const
00220 {
00221
00222
00223
00224 time_t atime = fSec + secOffset;
00225 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00226
00227 if (year) *year = ptm->tm_year + 1900;
00228 if (month) *month = ptm->tm_mon + 1;
00229 if (day) *day = ptm->tm_mday;
00230
00231 return (1900+ptm->tm_year)*10000 + (1+ptm->tm_mon)*100 + ptm->tm_mday;
00232
00233 }
00234
00235
00236 Int_t VldTimeStamp::GetTime(Bool_t inUTC, Int_t secOffset,
00237 UInt_t* hour, UInt_t* min, UInt_t* sec) const
00238 {
00239
00240
00241
00242 time_t atime = fSec + secOffset;
00243 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00244
00245 if (hour) *hour = ptm->tm_hour;
00246 if (min) *min = ptm->tm_min;
00247 if (sec) *sec = ptm->tm_sec;
00248
00249 return ptm->tm_hour*10000 + ptm->tm_min*100 + ptm->tm_sec;
00250
00251 }
00252
00253
00254 Int_t VldTimeStamp::GetZoneOffset()
00255 {
00256
00257
00258
00259
00260 #ifndef R__WIN32
00261 tzset();
00262 #if !defined(R__MACOSX) && !defined(R__FBSD)
00263 return timezone;
00264 #else
00265 time_t *tp = 0;
00266 time(tp);
00267 return localtime(tp)->tm_gmtoff;
00268 #endif
00269 #else
00270 _tzset();
00271 return _timezone;
00272 #endif
00273 }
00274
00275
00276 void VldTimeStamp::Add(const VldTimeStamp &offset)
00277 {
00278
00279
00280 fSec += offset.fSec;
00281 fNanoSec += offset.fNanoSec;
00282 NormalizeNanoSec();
00283
00284 }
00285
00286 void VldTimeStamp::Add(Double_t seconds)
00287 {
00288
00289
00290 fSec += (Int_t) seconds;
00291 fNanoSec += (Int_t) (fmod(seconds,1.0) * 1e9);
00292 NormalizeNanoSec();
00293 if(seconds > 1e6)
00294 MSG("Vld",Msg::kWarning) << "VldTimeStamp moved by offset " << seconds <<" which is too large to maintain ns accuracy." << endl;
00295 }
00296
00297
00298 void VldTimeStamp::Print(Option_t *option) const
00299 {
00300
00301
00302 printf("Date/Time = %s\n", AsString(option));
00303
00304 }
00305
00306
00307 void VldTimeStamp::Set()
00308 {
00309
00310
00311
00312
00313
00314
00315 #ifdef R__WIN32
00316 ULARGE_INTEGER time;
00317 GetSystemTimeAsFileTime((FILETIME *)&time);
00318
00319
00320
00321 fNanoSec = Int_t((time.QuadPart * (unsigned __int64) 100) %
00322 (unsigned __int64) 1000000000);
00323 time.QuadPart -=
00324 (unsigned __int64) (1000*1000*10)
00325 * (unsigned __int64) (60 * 60 * 24)
00326 * (unsigned __int64) (134774);
00327
00328 fSec = Int_t(time.QuadPart/(unsigned __int64) (1000*1000*10));
00329 #else
00330
00331
00332 struct timeval now;
00333 if (!gettimeofday(&now,0)) {
00334 fSec = now.tv_sec;
00335 fNanoSec = now.tv_usec * 1000;
00336 }
00337 else {
00338 time_t nowtime;
00339 time(&nowtime);
00340 fSec = nowtime;
00341 fNanoSec = 0;
00342 }
00343 #endif
00344 static Int_t sec = 0, nsec = 0, fake_ns = 0;
00345
00346 if (fSec == sec && fNanoSec == nsec)
00347 fNanoSec += ++fake_ns;
00348 else {
00349 fake_ns = 0;
00350 sec = fSec;
00351 nsec = fNanoSec;
00352 }
00353
00354 }
00355
00356
00357 void VldTimeStamp::Set(Int_t year, Int_t month, Int_t day,
00358 Int_t hour, Int_t min, Int_t sec,
00359 Int_t nsec, Bool_t isUTC, Int_t secOffset)
00360 {
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 if (year <= 37) year += 2000;
00377 if (year >= 70 && year <= 137) year += 1900;
00378
00379 if (year >= 1900) year -= 1900;
00380
00381 struct tm tmstruct;
00382 tmstruct.tm_year = year;
00383 tmstruct.tm_mon = month-1;
00384 tmstruct.tm_mday = day;
00385 tmstruct.tm_hour = hour;
00386 tmstruct.tm_min = min;
00387 tmstruct.tm_sec = sec + secOffset;
00388 tmstruct.tm_isdst = -1;
00389
00390 const time_t bad_time_t = (time_t) -1;
00391
00392
00393
00394
00395 time_t utc_sec = (isUTC) ? MktimeFromUTC(&tmstruct) : mktime(&tmstruct);
00396
00397
00398
00399 if (utc_sec == bad_time_t)
00400 MSG("Vld",Msg::kInfo)
00401 << "VldTimeStamp::Set mktime returned -1" << endl;
00402
00403 fSec = utc_sec;
00404 fNanoSec = nsec;
00405
00406 NormalizeNanoSec();
00407 }
00408
00409
00410 void VldTimeStamp::Set(Int_t date, Int_t time, Int_t nsec,
00411 Bool_t isUTC, Int_t secOffset)
00412 {
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 Int_t year = date/10000;
00429 Int_t month = (date-year*10000)/100;
00430 Int_t day = date%100;
00431
00432
00433 const Int_t oneday = 240000;
00434 while (time < 0) {
00435 time += oneday;
00436 day -= 1;
00437 }
00438 while (time > oneday) {
00439 time -= oneday;
00440 day += 1;
00441 }
00442 Int_t hour = time/10000;
00443 Int_t min = (time-hour*10000)/100;
00444 Int_t sec = time%100;
00445
00446 Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
00447
00448 }
00449
00450
00451 void VldTimeStamp::NormalizeNanoSec()
00452 {
00453
00454
00455
00456 while (fNanoSec < 0) {
00457 fNanoSec += kNsPerSec;
00458 fSec -= 1;
00459 }
00460
00461 while (fNanoSec >= kNsPerSec) {
00462 fNanoSec -= kNsPerSec;
00463 fSec += 1;
00464 }
00465 }
00466
00467 time_t VldTimeStamp::MktimeFromUTC(tm_t *tmstruct)
00468 {
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 const Int_t days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00481 const Int_t daysLeap[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00482
00483 Int_t year = tmstruct->tm_year + 1900;
00484 Bool_t isleap = VldTimeStamp::IsLeapYear(year);
00485
00486 const Int_t *daysInMonth = days;
00487 if (isleap) daysInMonth = daysLeap;
00488
00489
00490
00491 int &ref_tm_mon = tmstruct->tm_mon;
00492 int &ref_tm_mday = tmstruct->tm_mday;
00493
00494 tmstruct->tm_yday = 0;
00495 for (Int_t imonth = 0; imonth < ref_tm_mon; imonth++) {
00496 tmstruct->tm_yday += daysInMonth[imonth];
00497 }
00498 tmstruct->tm_yday += ref_tm_mday - 1;
00499
00500
00501 while (ref_tm_mday > daysInMonth[ref_tm_mon]) {
00502 ref_tm_mday -= daysInMonth[ref_tm_mon];
00503 ref_tm_mon++;
00504 }
00505
00506
00507
00508
00509 tmstruct->tm_isdst = 0;
00510
00511
00512
00513
00514 Int_t utc_sec = tmstruct->tm_sec +
00515 tmstruct->tm_min*60 +
00516 tmstruct->tm_hour*3600 +
00517 tmstruct->tm_yday*86400 +
00518 (tmstruct->tm_year-70)*31536000 +
00519 ((tmstruct->tm_year-69)/4)*86400;
00520
00521 return utc_sec;
00522 }
00523
00524
00525 Bool_t VldTimeStamp::IsLeapYear(Int_t year)
00526 {
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 if (year%4 != 0) {
00540 return false;
00541 }
00542 else {
00543 if (year%400 == 0) {
00544 return true;
00545 }
00546 else {
00547 if (year%100 == 0) {
00548 return false;
00549 }
00550 else {
00551 return true;
00552 }
00553 }
00554 }
00555
00556 }
00557
00558
00559 void VldTimeStamp::DumpTMStruct(const tm_t &tmstruct)
00560 {
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 printf(" tm { year %4d, mon %2d, day %2d,\n",
00573 tmstruct.tm_year,
00574 tmstruct.tm_mon,
00575 tmstruct.tm_mday);
00576 printf(" hour %2d, min %2d, sec %2d,\n",
00577 tmstruct.tm_hour,
00578 tmstruct.tm_min,
00579 tmstruct.tm_sec);
00580 printf(" wday %2d, yday %3d, isdst %2d",
00581 tmstruct.tm_wday,
00582 tmstruct.tm_yday,
00583 tmstruct.tm_isdst);
00584 #ifdef linux
00585
00586
00587 printf(",\n tm_gmtoff %7ld, tm_zone \"%s\"",
00588 #ifdef __USE_BSD
00589 tmstruct.tm_gmtoff,tmstruct.tm_zone);
00590 #else
00591 tmstruct.__tm_gmtoff,tmstruct.__tm_zone);
00592 #endif
00593 #endif
00594 printf("}\n");
00595 }
00596