55 TVirtualMutex *gTimeMutex = 0;
60 std::ostream& operator<<(std::ostream& os,
const TTimeStamp& ts)
63 if (os.tie()) os.tie()->flush();
64 os << ts.AsString(
"c");
67 if (os.flags() & std::ios::unitbuf) os.flush();
74 TBuffer &operator>>(TBuffer &buf, TTimeStamp &ts)
83 TBuffer &operator<<(TBuffer &buf,
const TTimeStamp &ts)
85 ((TTimeStamp&)ts).Streamer(buf);
95 TTimeStamp::TTimeStamp()
115 TTimeStamp::TTimeStamp(UInt_t year, UInt_t month,
116 UInt_t day, UInt_t hour,
117 UInt_t min, UInt_t sec,
119 Bool_t isUTC, Int_t secOffset)
121 Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
137 TTimeStamp::TTimeStamp(UInt_t date, UInt_t time,
139 Bool_t isUTC, Int_t secOffset)
141 Set(date, time, nsec, isUTC, secOffset);
150 TTimeStamp::TTimeStamp(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate)
152 Set(tloc, isUTC, secOffset, dosDate);
168 Double_t TTimeStamp::AsGMST(Double_t UT1Offset)
const
170 Double_t D = (AsJulianDate() + UT1Offset/86400000.0) - 2451545.0;
171 Double_t D_r = D - fmod(2.0*D+1.0, 2.0)/2.0;
172 Double_t T = D_r/36525.0;
173 Double_t sidereal = (24110.54841 + 8640184.812866*T + 0.093142*T*T
174 - 0.0000062*T*T*T + (D - D_r)*86400.0*1.002737909350795)/3600.0;
175 Double_t rval = fmod(sidereal, 24.0);
176 return rval < 0 ? rval + 24.0 : rval;
191 Double_t TTimeStamp::AsGAST(Double_t UT1Offset)
const
193 Double_t Pi = 3.14159265358979323846;
194 Double_t D = (AsJulianDate() + UT1Offset/86400000.0) - 2451545.0;
195 Double_t epsilon = (23.4393 - 0.0000004 * D) * Pi / 180.0;
196 Double_t L = (280.47 + 0.98565 * D) * Pi / 180.0;
197 Double_t Omega = (125.04 - 0.052954 * D) * Pi / 180.0;
198 Double_t Deltapsi = -0.000319 * std::sin(Omega) - 0.000024 * std::sin(2.0 * L);
199 Double_t eqeq = Deltapsi * std::cos(epsilon);
200 Double_t rval = fmod(AsGMST(UT1Offset) + eqeq, 24.0);
201 return rval < 0 ? rval + 24.0 : rval;
214 Double_t TTimeStamp::AsLMST(Double_t Longitude, Double_t UT1Offset)
const
216 Double_t rval = fmod(AsGMST(UT1Offset) + Longitude/15.0, 24.0);
217 return rval < 0 ? rval + 24.0 : rval;
230 Double_t TTimeStamp::AsLAST(Double_t Longitude, Double_t UT1Offset)
const
232 Double_t rval = fmod(AsGAST(UT1Offset) + Longitude/15.0, 24.0);
233 return rval < 0 ? rval + 24.0 : rval;
271 const Char_t *TTimeStamp::AsString(Option_t *option)
const
273 const Int_t nbuffers = 8;
275 static Char_t formatted[nbuffers][64];
276 static Char_t formatted2[nbuffers][64];
278 static Int_t ibuffer = nbuffers;
280 R__LOCKGUARD2(gTimeMutex);
282 ibuffer = (ibuffer+1)%nbuffers;
284 TString opt = option;
287 if (opt.Contains(
"2")) {
289 sprintf(formatted[ibuffer],
"{%d,%d}", fSec, fNanoSec);
290 return formatted[ibuffer];
295 const Char_t *kRFC822 =
"%a, %d %b %Y %H:%M:%S %z (%Z) +#9ld nsec";
296 const Char_t *kISO8601 =
"%Y-%m-%d %H:%M:%S.#9.9ld%z";
297 const Char_t *kISO8601Z =
"%Y-%m-%d %H:%M:%S.#9.9ldZ";
300 const Char_t *kRFC822 =
"%a, %d %b %Y %H:%M:%S %Z +#9ld nsec";
301 const Char_t *kISO8601 =
"%Y-%m-%d %H:%M:%S.#9.9ld%Z";
302 const Char_t *kISO8601Z =
"%Y-%m-%d %H:%M:%S.#9.9ldZ";
304 const Char_t *kSQL =
"%Y-%m-%d %H:%M:%S";
306 Bool_t asLocal = opt.Contains(
"l");
307 Bool_t asSQL = opt.Contains(
"s");
308 if (asSQL) asLocal = kFALSE;
310 const Char_t *format = kRFC822;
311 if (opt.Contains(
"c")) {
313 if (!asLocal) format = kISO8601Z;
315 if (asSQL) format = kSQL;
318 time_t seconds = (time_t) fSec;
321 struct tm *ptm = (asLocal) ? localtime_r(&seconds, &buf) : gmtime_r(&seconds, &buf);
323 struct tm *ptm = (asLocal) ? localtime(&seconds) : gmtime(&seconds);
328 strftime(formatted[ibuffer],
sizeof(formatted[ibuffer]), format, ptm);
330 if (asSQL)
return formatted[ibuffer];
333 Char_t *ptr = strrchr(formatted[ibuffer],
'#');
335 sprintf(formatted2[ibuffer], formatted[ibuffer], fNanoSec);
337 return formatted2[ibuffer];
343 void TTimeStamp::Copy(TTimeStamp &ts)
const
346 ts.fNanoSec = fNanoSec;
353 UInt_t TTimeStamp::GetDate(Bool_t inUTC, Int_t secOffset,
354 UInt_t *year, UInt_t *month, UInt_t *day)
const
356 time_t atime = fSec + secOffset;
359 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
361 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
364 if (day) *day = ptm->tm_mday;
365 if (month) *month = ptm->tm_mon + 1;
366 if (year) *year = ptm->tm_year + 1900;
368 return (1900+ptm->tm_year)*10000 + (1+ptm->tm_mon)*100 + ptm->tm_mday;
375 UInt_t TTimeStamp::GetTime(Bool_t inUTC, Int_t secOffset,
376 UInt_t *hour, UInt_t *min, UInt_t *sec)
const
378 time_t atime = fSec + secOffset;
381 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
383 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
386 if (hour) *hour = ptm->tm_hour;
387 if (min) *min = ptm->tm_min;
388 if (sec) *sec = ptm->tm_sec;
390 return ptm->tm_hour*10000 + ptm->tm_min*100 + ptm->tm_sec;
397 Int_t TTimeStamp::GetDayOfYear(Bool_t inUTC, Int_t secOffset)
const
399 time_t atime = fSec + secOffset;
402 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
404 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
407 Int_t day = ptm->tm_mday;
408 Int_t month = ptm->tm_mon + 1;
409 Int_t year = ptm->tm_year + 1900;
411 return GetDayOfYear(day, month, year);
418 Int_t TTimeStamp::GetDayOfWeek(Bool_t inUTC, Int_t secOffset)
const
420 time_t atime = fSec + secOffset;
423 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
425 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
428 Int_t day = ptm->tm_mday;
429 Int_t month = ptm->tm_mon + 1;
430 Int_t year = ptm->tm_year + 1900;
432 return GetDayOfWeek(day, month, year);
438 Int_t TTimeStamp::GetMonth(Bool_t inUTC, Int_t secOffset)
const
440 time_t atime = fSec + secOffset;
443 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
445 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
448 return ptm->tm_mon + 1;
456 Int_t TTimeStamp::GetWeek(Bool_t inUTC, Int_t secOffset)
const
458 time_t atime = fSec + secOffset;
461 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
463 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
466 Int_t day = ptm->tm_mday;
467 Int_t month = ptm->tm_mon + 1;
468 Int_t year = ptm->tm_year + 1900;
470 return GetWeek(day, month, year);
484 Bool_t TTimeStamp::IsLeapYear(Bool_t inUTC, Int_t secOffset)
const
486 time_t atime = fSec + secOffset;
489 struct tm *ptm = (inUTC) ? gmtime_r(&atime, &buf) : localtime_r(&atime, &buf);
491 struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
494 Int_t year = ptm->tm_year + 1900;
496 return IsLeapYear(year);
504 Int_t TTimeStamp::GetZoneOffset()
509 #if defined(R__WINGCC)
512 #if !defined(R__FBSD) && !defined(R__OBSD)
519 return -localtime_r(&tp, &buf)->tm_gmtoff;
521 return -localtime(&tp)->tm_gmtoff;
534 void TTimeStamp::Add(
const TTimeStamp &offset)
537 fNanoSec += offset.fNanoSec;
544 void TTimeStamp::Print(Option_t *option)
const
546 printf(
"Date/Time = %s\n", AsString(option));
556 void TTimeStamp::Set()
560 GetSystemTimeAsFileTime((FILETIME *)&time);
564 fNanoSec = Int_t((time.QuadPart * (
unsigned __int64) 100) %
565 (
unsigned __int64) 1000000000);
567 (
unsigned __int64) (1000*1000*10)
568 * (
unsigned __int64) (60 * 60 * 24)
569 * (
unsigned __int64) (134774);
571 fSec = Int_t(time.QuadPart/(
unsigned __int64) (1000*1000*10));
574 gettimeofday(&tp, 0);
576 fNanoSec = tp.tv_usec*1000;
579 static Int_t sec = 0, nsec = 0, fake_ns = 0;
581 R__LOCKGUARD2(gTimeMutex);
583 if (fSec == sec && fNanoSec == nsec)
584 fNanoSec += ++fake_ns;
607 void TTimeStamp::Set(Int_t year, Int_t month, Int_t day,
608 Int_t hour, Int_t min, Int_t sec,
609 Int_t nsec, Bool_t isUTC, Int_t secOffset)
612 if (year <= 37) year += 2000;
613 if (year >= 70 && year <= 137) year += 1900;
615 if (year >= 1900) year -= 1900;
618 tmstruct.tm_year = year;
619 tmstruct.tm_mon = month-1;
620 tmstruct.tm_mday = day;
621 tmstruct.tm_hour = hour;
622 tmstruct.tm_min = min;
623 tmstruct.tm_sec = sec + secOffset;
624 tmstruct.tm_isdst = -1;
626 const time_t bad_time_t = (time_t) -1;
631 time_t utc_sec = (isUTC) ? MktimeFromUTC(&tmstruct) : mktime(&tmstruct);
633 if (utc_sec == bad_time_t)
634 Error(
"TTimeStamp::Set",
"mktime returned -1");
660 void TTimeStamp::Set(Int_t date, Int_t time, Int_t nsec,
661 Bool_t isUTC, Int_t secOffset)
663 Int_t year = date/10000;
664 Int_t month = (date-year*10000)/100;
665 Int_t day = date%100;
668 const Int_t oneday = 240000;
673 while (time > oneday) {
677 Int_t hour = time/10000;
678 Int_t min = (time-hour*10000)/100;
679 Int_t sec = time%100;
681 Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
690 void TTimeStamp::Set(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate)
693 memset (&localtm, 0,
sizeof (localtm));
696 localtm.tm_year = ((tloc >> 25) & 0x7f) + 80;
697 localtm.tm_mon = ((tloc >> 21) & 0xf);
698 localtm.tm_mday = (tloc >> 16) & 0x1f;
699 localtm.tm_hour = (tloc >> 11) & 0x1f;
700 localtm.tm_min = (tloc >> 5) & 0x3f;
701 localtm.tm_sec = (tloc & 0x1f) * 2 + secOffset;
702 localtm.tm_isdst = -1;
704 time_t t = (time_t) tloc;
707 struct tm *tp = localtime_r(&t, &tpa);
709 struct tm *tp = localtime(&t);
711 localtm.tm_year = tp->tm_year;
712 localtm.tm_mon = tp->tm_mon;
713 localtm.tm_mday = tp->tm_mday;
714 localtm.tm_hour = tp->tm_hour;
715 localtm.tm_min = tp->tm_min;
716 localtm.tm_sec = tp->tm_sec + secOffset;
717 localtm.tm_isdst = -1;
720 const time_t bad_time_t = (time_t) -1;
725 time_t utc_sec = (isUTC && dosDate) ? MktimeFromUTC(&localtm) : mktime(&localtm);
727 if (utc_sec == bad_time_t)
728 Error(
"TTimeStamp::Set",
"mktime returned -1");
739 void TTimeStamp::NormalizeNanoSec()
741 const Int_t kNsPerSec = 1000000000;
743 while (fNanoSec < 0) {
744 fNanoSec += kNsPerSec;
749 while (fNanoSec >= kNsPerSec) {
750 fNanoSec -= kNsPerSec;
767 time_t TTimeStamp::MktimeFromUTC(tm_t *tmstruct)
769 Int_t daysInMonth[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
770 Int_t year = tmstruct->tm_year + 1900;
771 daysInMonth[1] = IsLeapYear(year) ? 29 : 28;
775 Int_t &ref_tm_mon = tmstruct->tm_mon;
776 Int_t &ref_tm_mday = tmstruct->tm_mday;
778 tmstruct->tm_yday = 0;
779 for (Int_t imonth = 0; imonth < ref_tm_mon; imonth++) {
780 tmstruct->tm_yday += daysInMonth[imonth];
782 tmstruct->tm_yday += ref_tm_mday - 1;
785 while (ref_tm_mday > daysInMonth[ref_tm_mon]) {
786 ref_tm_mday -= daysInMonth[ref_tm_mon];
793 tmstruct->tm_isdst = 0;
798 Int_t utc_sec = tmstruct->tm_sec +
799 tmstruct->tm_min*60 +
800 tmstruct->tm_hour*3600 +
801 tmstruct->tm_yday*86400 +
802 (tmstruct->tm_year-70)*31536000 +
803 ((tmstruct->tm_year-69)/4)*86400;
812 Int_t TTimeStamp::GetDayOfYear(Int_t day, Int_t month, Int_t year)
815 Int_t daysInMonth[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
816 daysInMonth[1] = IsLeapYear(year) ? 29 : 28;
818 for (Int_t i = 0; i < (month - 1); i++)
819 dayOfYear += daysInMonth[i];
829 Int_t TTimeStamp::GetDayOfWeek(Int_t day, Int_t month, Int_t year)
838 dayno = 1 + day + 2*month + 3*(month + 1)/5 + year + year/4 - year/100 + year/400;
842 return ((dayno == 0) ? 7 : dayno);
850 Int_t TTimeStamp::GetWeek(Int_t day, Int_t month, Int_t year)
852 Int_t dayOfYear = GetDayOfYear(day, month, year);
853 Int_t dayJan1st = GetDayOfWeek(1, 1, year);
854 Int_t week = (dayOfYear + dayJan1st - 2) / 7 + 1;
860 Int_t dayNextJan1st = GetDayOfWeek(1, 1, year + 1);
861 if (dayNextJan1st > 1 && dayNextJan1st < 5) {
865 }
else if (week == 0) {
866 Int_t dayPrevJan1st = GetDayOfWeek(1, 1, year - 1);
867 week = (dayPrevJan1st < 5 && dayJan1st > 4) ? 53 : 52;
870 return year * 100 + week;
884 Bool_t TTimeStamp::IsLeapYear(Int_t year)
886 return (year % 4 == 0) && !((year % 100 == 0) && (year % 400 > 0));
903 void TTimeStamp::DumpTMStruct(
const tm_t &tmstruct)
905 printf(
" tm { year %4d, mon %2d, day %2d,\n",
909 printf(
" hour %2d, min %2d, sec %2d,\n",
913 printf(
" wday %2d, yday %3d, isdst %2d",
917 #if (defined(linux) && !defined(R__WINGCC)) || defined(R__MACOSX)
918 printf(
",\n tm_gmtoff %6ld, tm_zone \"%s\"",
919 #
if defined(__USE_BSD) || defined(R__MACOSX) || defined(__USE_MISC)
920 tmstruct.tm_gmtoff, tmstruct.tm_zone);
922 tmstruct.__tm_gmtoff, tmstruct.__tm_zone);