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