source: trunk/MagicSoft/Mars/mbase/MTime.cc@ 3370

Last change on this file since 3370 was 3148, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 13.7 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 12/2000 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2003
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MTime
28//
29// A generalized MARS time stamp.
30//
31//
32// We do not use floating point values here, because of several reasons:
33// - having the times stored in integers only is more accurate and
34// more reliable in comparison conditions
35// - storing only integers gives similar bit-pattern for similar times
36// which makes compression (eg gzip algorithm in TFile) more
37// successfull
38//
39// Note, that there are many conversion function converting the day time
40// into a readable string. Also a direct interface to SQL time strings
41// is available.
42//
43// If you are using MTime containers as axis lables in root histograms
44// use GetAxisTime(). Make sure that you use the correct TimeFormat
45// on your TAxis (see GetAxisTime())
46//
47//
48// WARNING: Be carefull changing this class. It is also used in the
49// MAGIC drive software cosy!
50//
51// Remarke: If you encounter strange behaviour, check the casting.
52// Note, that on Linux machines ULong_t and UInt_t is the same.
53//
54//
55// Version 1:
56// ----------
57// - first version
58//
59// Version 2:
60// ----------
61// - removed fTimeStamp[2]
62//
63// Version 3:
64// ----------
65// - removed fDurtaion - we may put it back when it is needed
66// - complete rewrite of the data members (old ones completely replaced)
67//
68/////////////////////////////////////////////////////////////////////////////
69#include "MTime.h"
70
71#include <iomanip>
72
73#include <time.h> // struct tm
74#include <sys/time.h> // struct timeval
75
76#include <TTime.h>
77
78#include "MLog.h"
79#include "MAstro.h"
80
81ClassImp(MTime);
82
83using namespace std;
84
85const UInt_t MTime::kHour = 3600000; // [ms] one hour
86const UInt_t MTime::kDay = MTime::kHour*24; // [ms] one day
87
88// --------------------------------------------------------------------------
89//
90// Constructor. Calls SetMjd(d) for d>0 in all other cases the time
91// is set to the current UTC time.
92//
93MTime::MTime(Double_t d)
94{
95 Init(0, 0);
96 if (d<=0)
97 Now();
98 else
99 SetMjd(d);
100}
101
102// --------------------------------------------------------------------------
103//
104// Return date as year(y), month(m), day(d)
105//
106void MTime::GetDate(UShort_t &y, Byte_t &m, Byte_t &d) const
107{
108 MAstro::Mjd2Ymd((Long_t)fTime<0?fMjd-1:fMjd, y, m, d);
109}
110
111// --------------------------------------------------------------------------
112//
113// Return the time in the range [0h, 24h) = [0h0m0.000s - 23h59m59.999s]
114//
115void MTime::GetTime(Byte_t &h, Byte_t &m, Byte_t &s, UShort_t &ms) const
116{
117 Long_t tm = GetTime24();
118 ms = tm%1000; // [ms]
119 tm /= 1000; // [s]
120 s = tm%60; // [s]
121 tm /= 60; // [m]
122 m = tm%60; // [m]
123 tm /= 60; // [h]
124 h = tm; // [h]
125}
126
127// --------------------------------------------------------------------------
128//
129// Return time as MJD (=JD-24000000.5)
130//
131Double_t MTime::GetMjd() const
132{
133 return fMjd+(Double_t)(fNanoSec/1e6+(Long_t)fTime)/kDay;
134}
135
136// --------------------------------------------------------------------------
137//
138// Return a time which is expressed in milliseconds since 01/01/1995 0:00h
139// This is compatible with root's definition used in gSystem->Now()
140// and TTime.
141// Note, gSystem->Now() returns local time, such that it may differ
142// from GetRootTime() (if you previously called MTime::Now())
143//
144TTime MTime::GetRootTime() const
145{
146 return (ULong_t)((GetMjd()-49718)*kDay);
147}
148
149// --------------------------------------------------------------------------
150//
151// Return a time which is expressed in seconds since 01/01/1995 0:00h
152// This is compatible with root's definition used in TAxis.
153// Note, a TAxis always displayes (automatically) given times in
154// local time (while here we return UTC) such, that you may encounter
155// strange offsets. You can get rid of this by calling:
156// TAxis::SetTimeFormat("[your-format] %F1995-01-01 00:00:00");
157//
158Double_t MTime::GetAxisTime() const
159{
160 return (GetMjd()-49718)*kDay/1000;
161}
162
163// --------------------------------------------------------------------------
164//
165// Set a time expressed in MJD, Time of Day (eg. 23:12.779h expressed
166// in milliseconds) and a nanosecond part.
167//
168Bool_t MTime::Set(UInt_t mjd, ULong_t ms, UInt_t ns)
169{
170 // [d] mjd (eg. 52320)
171 // [ms] time (eg. 17h expressed in ms)
172 // [ns] time (ns part of time)
173
174 if (ms>kDay-1 || ns>999999)
175 return kFALSE;
176
177 const Bool_t am = ms<kHour*13; // day of sunrise?
178
179 fMjd = am ? mjd : mjd + 1;
180 fTime = (Long_t)(am ? ms : ms-kDay);
181 fNanoSec = ns;
182
183 return kTRUE;
184}
185
186// --------------------------------------------------------------------------
187//
188// Set MTime to given MJD (eg. 52080.0915449892)
189//
190void MTime::SetMjd(Double_t m)
191{
192 const UInt_t mjd = (UInt_t)TMath::Floor(m);
193 const Double_t frac = fmod(m, 1)*kDay; // [ms] Fraction of day
194 const UInt_t ns = (UInt_t)fmod(frac*1e6, 1000000);
195
196 Set(mjd, (ULong_t)TMath::Floor(frac), ns);
197}
198
199// --------------------------------------------------------------------------
200//
201// Set MTime to given time and date
202//
203Bool_t MTime::Set(UShort_t y, Byte_t m, Byte_t d, Byte_t h, Byte_t min, Byte_t s, UShort_t ms, UInt_t ns)
204{
205 if (h>23 || min>59 || s>59 || ms>999 || ns>999999)
206 return kFALSE;
207
208 const Int_t mjd = MAstro::Ymd2Mjd(y, m, d);
209 if (mjd<0)
210 return kFALSE;
211
212 const ULong_t tm = ((((h*60+min)*60)+s)*1000)+ms;
213
214 return Set(mjd, tm, ns);
215}
216
217// --------------------------------------------------------------------------
218//
219// Set MTime to time expressed in a 'struct timeval'
220//
221void MTime::Set(const struct timeval &tv)
222{
223 const UInt_t mjd = 1000*tv.tv_sec/kDay + 40587;
224 const Long_t tm = tv.tv_sec%(24*3600)*1000 + tv.tv_usec/1000;
225 const UInt_t ms = tv.tv_usec%1000;
226
227 Set(mjd, tm, ms*1000);
228}
229
230// --------------------------------------------------------------------------
231//
232// Return contents as a TString of the form:
233// "dd.mm.yyyy hh:mm:ss.fff"
234//
235Bool_t MTime::SetString(const char *str)
236{
237 if (!str)
238 return kFALSE;
239
240 UInt_t y, mon, d, h, m, s, ms;
241 const Int_t n = sscanf(str, "%02u.%02u.%04u %02u:%02u:%02u.%03u",
242 &d, &mon, &y, &h, &m, &s, &ms);
243
244 return n==7 ? Set(y, mon, d, h, m, s, ms) : kFALSE;
245}
246
247// --------------------------------------------------------------------------
248//
249// Return contents as a TString of the form:
250// "yyyy-mm-dd hh:mm:ss"
251//
252Bool_t MTime::SetSqlDateTime(const char *str)
253{
254 if (!str)
255 return kFALSE;
256
257 UInt_t y, mon, d, h, m, s;
258 const Int_t n = sscanf(str, "%04u-%02u-%02u %02u:%02u:%02u",
259 &y, &mon, &d, &h, &m, &s);
260
261 return n==6 ? Set(y, mon, d, h, m, s) : kFALSE;
262}
263
264// --------------------------------------------------------------------------
265//
266// Return contents as a TString of the form:
267// "yyyymmddhhmmss"
268//
269Bool_t MTime::SetSqlTimeStamp(const char *str)
270{
271 if (!str)
272 return kFALSE;
273
274 UInt_t y, mon, d, h, m, s;
275 const Int_t n = sscanf(str, "%04u%02u%02u%02u%02u%02u",
276 &y, &mon, &d, &h, &m, &s);
277
278 return n==6 ? Set(y, mon, d, h, m, s) : kFALSE;
279}
280
281// --------------------------------------------------------------------------
282//
283// Set MTime to time expressed as in CT1 PreProc files
284//
285void MTime::SetCT1Time(UInt_t mjd, UInt_t t1, UInt_t t0)
286{
287 // int isecs_since_midday; // seconds passed since midday before sunset (JD of run start)
288 // int isecfrac_200ns; // fractional part of isecs_since_midday
289 // fTime->SetTime(isecfrac_200ns, isecs_since_midday);
290 fNanoSec = (200*t1)%1000000;
291 const ULong_t ms = (200*t1)/1000000 + t0+12*kHour;
292
293 fTime = (Long_t)(ms<13*kHour ? ms : ms-kDay);
294
295 fMjd = mjd+1;
296}
297
298// --------------------------------------------------------------------------
299//
300// Update the magic time. Make sure, that the MJD is set correctly.
301// It must be the MJD of the corresponding night. You can set it
302// by Set(2003, 12, 24);
303//
304// It is highly important, that the time correspoding to the night is
305// between 13:00:00.0 (day of dawning) and 12:59:59.999 (day of sunrise)
306//
307Bool_t MTime::UpdMagicTime(Byte_t h, Byte_t m, Byte_t s, UInt_t ns)
308{
309 if (h>23 || m>59 || s>59 || ns>999999999)
310 return kFALSE;
311
312 const ULong_t tm = ((((h*60+m)*60)+s)*1000)+ns/1000000;
313
314 fTime = (Long_t)(tm<kHour*13 ? tm : tm-kDay); // day of sunrise?
315 fNanoSec = ns%1000000;
316
317 return kTRUE;
318
319}
320
321// --------------------------------------------------------------------------
322//
323// Set the time to the current system time. The timezone is ignored.
324// If everything is set correctly you'll get UTC.
325//
326void MTime::Now()
327{
328#ifdef __LINUX__
329 struct timeval tv;
330 if (gettimeofday(&tv, NULL)<0)
331 Clear();
332 else
333 Set(tv);
334#else
335 Clear();
336#endif
337}
338
339// --------------------------------------------------------------------------
340//
341// Return contents as a TString of the form:
342// "dd.mm.yyyy hh:mm:ss.fff"
343//
344TString MTime::GetString() const
345{
346 UShort_t y, ms;
347 Byte_t mon, d, h, m, s;
348
349 GetDate(y, mon, d);
350 GetTime(h, m, s, ms);
351
352 return TString(Form("%02d.%02d.%04d %02d:%02d:%02d.%03d", d, mon, y, h, m, s, ms));
353}
354
355// --------------------------------------------------------------------------
356//
357// Return contents as a string format'd with strftime:
358// Here is a short summary of the most important formats. For more
359// information see the man page (or any other description) of
360// strftime...
361//
362// %a The abbreviated weekday name according to the current locale.
363// %A The full weekday name according to the current locale.
364// %b The abbreviated month name according to the current locale.
365// %B The full month name according to the current locale.
366// %c The preferred date and time representation for the current locale.
367// %d The day of the month as a decimal number (range 01 to 31).
368// %e Like %d, the day of the month as a decimal number,
369// but a leading zero is replaced by a space.
370// %H The hour as a decimal number using a 24-hour clock (range 00 to 23)
371// %k The hour (24-hour clock) as a decimal number (range 0 to 23);
372// single digits are preceded by a blank.
373// %m The month as a decimal number (range 01 to 12).
374// %M The minute as a decimal number (range 00 to 59).
375// %R The time in 24-hour notation (%H:%M). For a
376// version including the seconds, see %T below.
377// %S The second as a decimal number (range 00 to 61).
378// %T The time in 24-hour notation (%H:%M:%S).
379// %x The preferred date representation for the current
380// locale without the time.
381// %X The preferred time representation for the current
382// locale without the date.
383// %y The year as a decimal number without a century (range 00 to 99).
384// %Y The year as a decimal number including the century.
385// %+ The date and time in date(1) format.
386//
387// The default is: Tuesday 16.February 2004 12:17:22
388//
389// The maximum size of the return string is 128 (incl. NULL)
390//
391TString MTime::GetStringFmt(const char *fmt) const
392{
393 if (!fmt)
394 fmt = "%A %e.%B %Y %H:%M:%S";
395
396 UShort_t y, ms;
397 Byte_t mon, d, h, m, s;
398
399 GetDate(y, mon, d);
400 GetTime(h, m, s, ms);
401
402 struct tm time;
403 time.tm_sec = s;
404 time.tm_min = m;
405 time.tm_hour = h;
406 time.tm_mday = d;
407 time.tm_mon = mon-1;
408 time.tm_year = y-1900;
409 time.tm_isdst = 0;
410
411 // recalculate tm_yday and tm_wday
412 mktime(&time);
413
414 char ret[128];
415 return TString(strftime(ret, 127, fmt, &time) ? ret : "");
416}
417
418// --------------------------------------------------------------------------
419//
420// Return contents as a TString of the form:
421// "yyyy-mm-dd hh:mm:ss"
422//
423TString MTime::GetSqlDateTime() const
424{
425 return GetStringFmt("%Y-%m-%d %H:%M:%S");
426}
427
428// --------------------------------------------------------------------------
429//
430// Return contents as a TString of the form:
431// "yyyymmddhhmmss"
432//
433TString MTime::GetSqlTimeStamp() const
434{
435 return GetStringFmt("%Y%m%d%H%M%S");
436}
437
438// --------------------------------------------------------------------------
439//
440// Return contents as a TString of the form:
441// "yyyymmdd_hhmmss"
442//
443TString MTime::GetFileName() const
444{
445 return GetStringFmt("%Y%m%d_%H%M%S");
446}
447
448// --------------------------------------------------------------------------
449//
450// Print MTime as string
451//
452void MTime::Print(Option_t *) const
453{
454 UShort_t yea, ms;
455 Byte_t mon, day, h, m, s;
456
457 GetDate(yea, mon, day);
458 GetTime(h, m, s, ms);
459
460 *fLog << GetDescriptor() << ": ";
461 *fLog << GetString() << Form(" (+%dns)", fNanoSec) << endl;
462}
463
464istream &MTime::ReadBinary(istream &fin)
465{
466 UShort_t y;
467 Byte_t mon, d, h, m, s;
468
469 fin.read((char*)&y, 2);
470 fin.read((char*)&mon, 1);
471 fin.read((char*)&d, 1);
472 fin.read((char*)&h, 1);
473 fin.read((char*)&m, 1);
474 fin.read((char*)&s, 1); // Total=7
475
476 Set(y, mon, d, h, m, s, 0);
477
478 return fin;
479}
Note: See TracBrowser for help on using the repository browser.