Logo ROOT   6.14/05
Reference Guide
TDatime.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Rene Brun 05/01/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TDatime
13 \ingroup Base
14 
15 This class stores the date and time with a precision of one second
16 in an unsigned 32 bit word (950130 124559).
17 The date is stored with the origin being the 1st January 1995.
18 
19 This class has no support for time zones. The time is assumed
20 to be in the local time of the machine where the object was created.
21 As a result, TDatime objects are not portable between machines
22 operating in different time zones and unsuitable for storing the
23 date/time of data taking events and the like. If absolute time is
24 required, use TTimeStamp.
25 */
26 
27 #include <ROOT/RConfig.h>
28 
29 #include <time.h>
30 
31 #ifdef WIN32
32 #include "Windows4Root.h"
33 #include <string.h>
34 #endif
35 
36 #include "TBuffer.h"
37 #include "Strlen.h"
38 #include "TDatime.h"
39 #include "TError.h"
40 #include "Bytes.h"
41 #include "TString.h"
42 
43 
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 /// Create a TDatime and set it to the current time.
48 
50 {
51  Set();
52 }
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 /// Create a TDatime and set it to the specified date and time.
56 /// See Set(Int_t, Int_t) about the date, time format.
57 
59 {
60  Set(date, time);
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 /// Create a TDatime and set it to the specified year, month,
65 /// day, time, hour, minute and second. See Set() about the format.
66 
67 TDatime::TDatime(Int_t year, Int_t month, Int_t day,
68  Int_t hour, Int_t min, Int_t sec)
69 {
70  Set(year, month, day, hour, min, sec);
71 }
72 
73 ////////////////////////////////////////////////////////////////////////////////
74 /// Expects as input a string in SQL date/time compatible format, like:
75 /// yyyy-mm-dd hh:mm:ss.
76 
77 TDatime::TDatime(const char *sqlDateTime)
78 {
79  Set(sqlDateTime);
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Returns day of week, with Monday being day 1 and Sunday day 7.
84 
86 {
87  static TString weekDays[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
88  TString wd = AsString();
89  int day;
90  for (day = 0; day < 7; day++) {
91  if (wd(0, 3) == weekDays[day])
92  break;
93  }
94  return (day < 7) ? day+1: -1;
95 }
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 /// Return the date & time as a string (ctime() format).
99 /// Copy result because it points to a statically allocated string.
100 
101 const char *TDatime::AsString() const
102 {
103  time_t t = Convert();
104  char *retStr = ctime(&t);
105  if (retStr) {
106  *(retStr + 24) = 0;
107  return retStr;
108  } else {
109  static const char *defaulttime = "15/06/96";
110  Error("TDatime::AsString", "could not get time string");
111  return defaulttime;
112  }
113 }
114 
115 ////////////////////////////////////////////////////////////////////////////////
116 /// Return the date & time as a string (ctime() format).
117 /// Result is copied into out (and out is returned). Make sure
118 /// out can at least contain 26 characters. Thread safe.
119 
120 const char *TDatime::AsString(char *out) const
121 {
122  time_t t = Convert();
123 #ifdef _REENTRANT
124 #if defined(R__SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)
125  char *retStr = ctime_r(&t, out, 26);
126 #else
127  char *retStr = ctime_r(&t, out);
128 #endif
129 #else
130  char *retStr = ctime(&t);
131 #endif
132  if (retStr) {
133  *(retStr + 24) = 0;
134 #ifndef _REENTRANT
135  strcpy(out, retStr);
136 #endif
137  return retStr;
138  } else {
139  static const char *defaulttime = "15/06/96";
140  strcpy(out, defaulttime);
141  Error("TDatime::AsString", "could not get time string");
142  return defaulttime;
143  }
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// Return the date & time in SQL compatible string format, like:
148 /// 1997-01-15 20:16:28. The returned string buffer is static and
149 /// will be reused.
150 
151 const char *TDatime::AsSQLString() const
152 {
153  static char sqldate[20];
154 
155  UInt_t year = fDatime>>26;
156  UInt_t month = (fDatime<<6)>>28;
157  UInt_t day = (fDatime<<10)>>27;
158  UInt_t hour = (fDatime<<15)>>27;
159  UInt_t min = (fDatime<<20)>>26;
160  UInt_t sec = (fDatime<<26)>>26;
161 
162  snprintf(sqldate,20, "%04d-%02d-%02d %02d:%02d:%02d", (year+1995), month, day,
163  hour, min, sec);
164 
165  return sqldate;
166 }
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 /// Convert fDatime from TDatime format to the standard time_t format.
170 /// If toGMT is true, the time offset of the current local time zone is
171 /// subtracted from the returned time_t. One use of such a non-standard time_t
172 /// value is to convert a TDatime object that contains local time to GMT,
173 /// as in this example:
174 /// ~~~ {.cpp}
175 /// TDatime now;
176 /// now.Set(now.Convert(kTRUE));
177 /// ~~~
178 /// Caution: the time_t returned from Convert(kTRUE) is incompatible with
179 /// regular Unix time - it contains an artificial, locale-dependent offset.
180 
182 {
183  UInt_t year = fDatime>>26;
184  UInt_t month = (fDatime<<6)>>28;
185  UInt_t day = (fDatime<<10)>>27;
186  UInt_t hour = (fDatime<<15)>>27;
187  UInt_t min = (fDatime<<20)>>26;
188  UInt_t sec = (fDatime<<26)>>26;
189 
190  struct tm tp;
191  tp.tm_year = year+95;
192  tp.tm_mon = month-1;
193  tp.tm_mday = day;
194  tp.tm_hour = hour;
195  tp.tm_min = min;
196  tp.tm_sec = sec;
197  tp.tm_isdst = -1;
198 
199  time_t t = mktime(&tp);
200  if ((int)t == -1) {
201  Error("TDatime::Convert", "error converting fDatime to time_t");
202  return 0;
203  }
204  if (toGMT) {
205 #ifdef _REENTRANT
206  struct tm tg;
207  struct tm *tgp = gmtime_r(&t, &tg);
208 #else
209  struct tm *tgp = gmtime(&t);
210 #endif
211  tgp->tm_isdst = -1;
212  t = mktime(tgp);
213  }
214  return (UInt_t)t;
215 }
216 
217 ////////////////////////////////////////////////////////////////////////////////
218 /// Copy this to datime.
219 
220 void TDatime::Copy(TDatime &datime) const
221 {
222  datime.fDatime = fDatime;
223 }
224 
225 ////////////////////////////////////////////////////////////////////////////////
226 /// Encode Date/Time into buffer, used by I/O system.
227 
228 void TDatime::FillBuffer(char *&buffer)
229 {
230  tobuf(buffer, fDatime);
231 }
232 
233 ////////////////////////////////////////////////////////////////////////////////
234 /// Return raw date/time as encoded by TDatime. Note, this value cannot
235 /// be used to e.g. calculate time differences, as it is an encoded value.
236 /// To calculate time differences use the Convert() method to get a time
237 /// in seconds and then subtract the values.
238 
240 {
241  return fDatime;
242 }
243 
244 ////////////////////////////////////////////////////////////////////////////////
245 /// Return date in form of 19971224 (i.e. 24/12/1997)
246 
248 {
249  UInt_t year = fDatime>>26;
250  UInt_t month = (fDatime<<6)>>28;
251  UInt_t day = (fDatime<<10)>>27;
252  return 10000*(year+1995) + 100*month + day;
253 }
254 
255 ////////////////////////////////////////////////////////////////////////////////
256 /// Return time in form of 123623 (i.e. 12:36:23)
257 
259 {
260  UInt_t hour = (fDatime<<15)>>27;
261  UInt_t min = (fDatime<<20)>>26;
262  UInt_t sec = (fDatime<<26)>>26;
263  return 10000*hour + 100*min + sec;
264 }
265 
266 ////////////////////////////////////////////////////////////////////////////////
267 /// Print date and time.
268 
270 {
271  printf("Date/Time = %s\n", AsString());
272 }
273 
274 ////////////////////////////////////////////////////////////////////////////////
275 /// Decode Date/Time from output buffer, used by I/O system.
276 
277 void TDatime::ReadBuffer(char *&buffer)
278 {
279  frombuf(buffer, &fDatime);
280 }
281 
282 ////////////////////////////////////////////////////////////////////////////////
283 /// Set Date/Time to current time as reported by the system.
284 /// Date and Time are encoded into one single unsigned 32 bit word.
285 /// Date is stored with the origin being the 1st January 1995.
286 /// Time has 1 second precision.
287 
289 {
290 #ifndef WIN32
291  time_t tloc = time(0);
292 #ifdef _REENTRANT
293  struct tm tpa;
294  struct tm *tp = localtime_r(&tloc, &tpa);
295 #else
296  struct tm *tp = localtime(&tloc);
297 #endif
298  UInt_t year = tp->tm_year;
299  UInt_t month = tp->tm_mon + 1;
300  UInt_t day = tp->tm_mday;
301  UInt_t hour = tp->tm_hour;
302  UInt_t min = tp->tm_min;
303  UInt_t sec = tp->tm_sec;
304 #else
305  SYSTEMTIME tp;
306  GetLocalTime(&tp);
307  UInt_t year = tp.wYear-1900;
308  UInt_t month = tp.wMonth;
309  UInt_t day = tp.wDay;
310  UInt_t hour = tp.wHour;
311  UInt_t min = tp.wMinute;
312  UInt_t sec = tp.wSecond;
313 #endif
314 
315  fDatime = (year-95)<<26 | month<<22 | day<<17 | hour<<12 | min<<6 | sec;
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// The input arg is a time_t value returned by time() or a value
320 /// returned by Convert(). This value is the number of seconds since
321 /// the EPOCH (i.e. 00:00:00 on Jan 1m 1970). If dosDate is true then
322 /// the input is a dosDate value.
323 
324 void TDatime::Set(UInt_t tloc, Bool_t dosDate)
325 {
326  UInt_t year, month, day, hour, min, sec;
327 
328  if (dosDate) {
329  year = ((tloc >> 25) & 0x7f) + 80;
330  month = ((tloc >> 21) & 0xf);
331  day = (tloc >> 16) & 0x1f;
332  hour = (tloc >> 11) & 0x1f;
333  min = (tloc >> 5) & 0x3f;
334  sec = (tloc & 0x1f) * 2;
335  } else {
336  time_t t = (time_t) tloc;
337 #ifdef _REENTRANT
338  struct tm tpa;
339  struct tm *tp = localtime_r(&t, &tpa);
340 #else
341  struct tm *tp = localtime(&t);
342 #endif
343  year = tp->tm_year;
344  month = tp->tm_mon + 1;
345  day = tp->tm_mday;
346  hour = tp->tm_hour;
347  min = tp->tm_min;
348  sec = tp->tm_sec;
349  }
350 
351  fDatime = (year-95)<<26 | month<<22 | day<<17 | hour<<12 | min<<6 | sec;
352 }
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 /// Set date and time. Data must be in format 980418 or 19980418 and time in
356 /// 224512 (second precision). The date must
357 /// be >= 950101.
358 ///
359 /// For years >= 2000, date can be given in the form 20001127 or 1001127
360 /// internally the date will be converted to 1001127
361 
362 void TDatime::Set(Int_t date, Int_t time)
363 {
364  if (date > 19000000) date -= 19000000;
365  if (date < 950101) {
366  Error("TDatime::Set", "year smaller than 1995");
367  return;
368  }
369 
370  Int_t year = date/10000;
371  Int_t month = (date-year*10000)/100;
372  Int_t day = date%100;
373 
374  Int_t hour, min, sec;
375 
376  hour = time/10000;
377  min = (time-hour*10000)/100;
378  sec = time%100;
379 
380  fDatime = (year-95)<<26 | month<<22 | day<<17 | hour<<12 | min<<6 | sec;
381 }
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 /// Set date and time. Year may be xx where 95 <= xx <= 158 (158 being 2058).
385 /// The year must be >= 1995.
386 
387 void TDatime::Set(Int_t year, Int_t month, Int_t day,
388  Int_t hour, Int_t min, Int_t sec)
389 {
390  if (year < 159) year += 1900;
391  if (year < 1995) {
392  Error("TDatime::Set", "year must be >= 1995");
393  return;
394  }
395 
396  fDatime = (year-1995)<<26 | month<<22 | day<<17 | hour<<12 | min<<6 | sec;
397 }
398 
399 ////////////////////////////////////////////////////////////////////////////////
400 /// Expects as input a string in SQL date/time compatible format, like:
401 /// yyyy-mm-dd hh:mm:ss.
402 
403 void TDatime::Set(const char* sqlDateTime)
404 {
405  Int_t yy, mm, dd, hh, mi, ss;
406 
407  if (sscanf(sqlDateTime, "%d-%d-%d %d:%d:%d", &yy, &mm, &dd, &hh, &mi, &ss) == 6)
408  Set(yy, mm, dd, hh, mi, ss);
409  else {
410  Error("TDatime(sqlDatTime)", "input string not in right format, set"
411  " to current date/time");
412  Set();
413  }
414 }
415 
416 ////////////////////////////////////////////////////////////////////////////////
417 /// Stream a object of type TDatime.
418 
419 void TDatime::Streamer(TBuffer &b)
420 {
421  if (b.IsReading()) {
422  b >> fDatime;
423  } else {
424  b << fDatime;
425  }
426 }
427 
428 ////////////////////////////////////////////////////////////////////////////////
429 /// Static function that returns the date and time. The input is
430 /// in TDatime format (as obtained via TDatime::Get()).
431 /// Date is returned in the format 950223 February 23 1995.
432 /// Time is returned in the format 102459 10h 24m 59s.
433 
434 void TDatime::GetDateTime(UInt_t datetime, Int_t &date, Int_t &time)
435 {
436  UInt_t year = datetime>>26;
437  UInt_t month = (datetime<<6)>>28;
438  UInt_t day = (datetime<<10)>>27;
439  UInt_t hour = (datetime<<15)>>27;
440  UInt_t min = (datetime<<20)>>26;
441  UInt_t sec = (datetime<<26)>>26;
442  date = 10000*(year+1995) + 100*month + day;
443  time = 10000*hour + 100*min + sec;
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Static function that returns the global day number from date. The input is
448 /// in TDatime format yyyymmdd (as obtained via TDatime::GetDate()).
449 /// This algorithm is only accurate for dates later than October 1582
450 /// (earliest date on Gregorian calendar).
451 
453 {
454  // date is in form yyyymmdd
455  Int_t dy = date / 10000;
456  Int_t dm = (date - dy*10000)/100;
457  Int_t dd = (date - dy*10000 - dm*100);
458 
459  Int_t m = (dm + 9)%12; // mar=0, feb=11
460  Int_t y = dy - m/10; // if Jan/Feb, year--
461  return y*365 + y/4 - y/100 + y/400 + (m*306 + 5)/10 + (dd - 1);
462 }
463 
464 ////////////////////////////////////////////////////////////////////////////////
465 /// Static function that returns the date from the global day number.
466 /// The output is in TDatime yyyymmdd format (as obtained via
467 /// TDatime::GetDate()).
468 
470 {
471  Long_t ld = day;
472  Int_t y = int((10000*ld + 14780)/3652425);
473  Int_t ddd = day - (y*365 + y/4 - y/100 + y/400);
474  if (ddd < 0) {
475  y--;
476  ddd = day - (y*365 + y/4 - y/100 + y/400);
477  }
478  Int_t mi = (52 + 100*ddd)/3060;
479  Int_t dy = y + (mi + 2)/12;
480  Int_t dm = (mi + 2)%12 + 1;
481  Int_t dd = ddd - (mi*306 + 5)/10 + 1;
482 
483  return dy*10000 + dm*100 + dd;
484 }
485 
486 ////////////////////////////////////////////////////////////////////////////////
487 /// Static function that returns the global day number from date. The input is
488 /// in TDatime format yyyymmdd (as obtained via TDatime::GetDate()).
489 /// This algorithm is only accurate for dates later than October 1582
490 /// (earliest date on Gregorian calendar) and it is checked that the date
491 /// is larger than 15821001 and conversion is correct.
492 /// In case of conversion failure 0 is returned.
493 /// No need to use when you know dates are larger than October 1582.
494 
496 {
497  static Int_t calstart = 0;
498  if (!calstart)
499  calstart = TDatime::GetGlobalDayFromDate(15821001);
501  if (d < calstart)
502  ::Warning("TDatime::GetLegalGlobalDayFromDate", "dates before Oct. 1582 are inaccurate.");
504  if (dte != date) {
505  ::Error("TDatime::GetLegalGlobalDayFromDate", "illegal date %d", dte);
506  return 0;
507  }
508  return d;
509 }
510 
511 ////////////////////////////////////////////////////////////////////////////////
512 /// Print a TDatime at the prompt.
513 
514 std::string cling::printValue(const TDatime* val) {
515  char buf[30];
516  return std::string(val->AsString(buf));
517 }
Bool_t IsReading() const
Definition: TBuffer.h:83
void frombuf(char *&buf, Bool_t *x)
Definition: Bytes.h:280
auto * m
Definition: textangle.C:8
TDatime()
Create a TDatime and set it to the current time.
Definition: TDatime.cxx:49
void Set()
Set Date/Time to current time as reported by the system.
Definition: TDatime.cxx:288
const char Option_t
Definition: RtypesCore.h:62
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Basic string class.
Definition: TString.h:131
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
static constexpr double mm
void ReadBuffer(char *&buffer)
Decode Date/Time from output buffer, used by I/O system.
Definition: TDatime.cxx:277
static Int_t GetLegalGlobalDayFromDate(Int_t date)
Static function that returns the global day number from date.
Definition: TDatime.cxx:495
Int_t GetDate() const
Return date in form of 19971224 (i.e. 24/12/1997)
Definition: TDatime.cxx:247
static Int_t GetDateFromGlobalDay(Int_t day)
Static function that returns the date from the global day number.
Definition: TDatime.cxx:469
void Copy(TDatime &datime) const
Copy this to datime.
Definition: TDatime.cxx:220
static void GetDateTime(UInt_t datetime, Int_t &date, Int_t &time)
Static function that returns the date and time.
Definition: TDatime.cxx:434
void FillBuffer(char *&buffer)
Encode Date/Time into buffer, used by I/O system.
Definition: TDatime.cxx:228
void tobuf(char *&buf, Bool_t x)
Definition: Bytes.h:57
void Error(const char *location, const char *msgfmt,...)
std::string printValue(const TDatime *val)
Print a TDatime at the prompt.
Definition: TDatime.cxx:514
static Int_t GetGlobalDayFromDate(Int_t date)
Static function that returns the global day number from date.
Definition: TDatime.cxx:452
UInt_t Get() const
Return raw date/time as encoded by TDatime.
Definition: TDatime.cxx:239
const char * AsSQLString() const
Return the date & time in SQL compatible string format, like: 1997-01-15 20:16:28.
Definition: TDatime.cxx:151
unsigned int UInt_t
Definition: RtypesCore.h:42
void Print(Option_t *option="") const
Print date and time.
Definition: TDatime.cxx:269
void Warning(const char *location, const char *msgfmt,...)
Int_t GetTime() const
Return time in form of 123623 (i.e. 12:36:23)
Definition: TDatime.cxx:258
long Long_t
Definition: RtypesCore.h:50
#define d(i)
Definition: RSha256.hxx:102
#define ClassImp(name)
Definition: Rtypes.h:359
Double_t y[n]
Definition: legend1.C:17
Int_t GetDayOfWeek() const
Returns day of week, with Monday being day 1 and Sunday day 7.
Definition: TDatime.cxx:85
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:101
UInt_t Convert(Bool_t toGMT=kFALSE) const
Convert fDatime from TDatime format to the standard time_t format.
Definition: TDatime.cxx:181
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
#define snprintf
Definition: civetweb.c:1351
UInt_t fDatime
Definition: TDatime.h:42
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37