source: tags/Mars-V0.8.5/mbase/MTime.cc

Last change on this file was 4452, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 15.9 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 as VERY IMPORTANT stuff!
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 "MLogManip.h"
80
81#include "MAstro.h"
82
83ClassImp(MTime);
84
85using namespace std;
86
87const UInt_t MTime::kHour = 3600000; // [ms] one hour
88const UInt_t MTime::kDay = MTime::kHour*24; // [ms] one day
89
90// --------------------------------------------------------------------------
91//
92// Constructor. Calls SetMjd(d) for d>0 in all other cases the time
93// is set to the current UTC time.
94//
95MTime::MTime(Double_t d)
96{
97 Init(0, 0);
98 if (d<=0)
99 Now();
100 else
101 SetMjd(d);
102}
103
104// --------------------------------------------------------------------------
105//
106// Return date as year(y), month(m), day(d)
107//
108void MTime::GetDate(UShort_t &y, Byte_t &m, Byte_t &d) const
109{
110 MAstro::Mjd2Ymd((Long_t)fTime<0?fMjd-1:fMjd, y, m, d);
111}
112
113// --------------------------------------------------------------------------
114//
115// Return the time in the range [0h, 24h) = [0h0m0.000s - 23h59m59.999s]
116//
117void MTime::GetTime(Byte_t &h, Byte_t &m, Byte_t &s, UShort_t &ms) const
118{
119 Long_t tm = GetTime24();
120 ms = tm%1000; // [ms]
121 tm /= 1000; // [s]
122 s = tm%60; // [s]
123 tm /= 60; // [m]
124 m = tm%60; // [m]
125 tm /= 60; // [h]
126 h = tm; // [h]
127}
128
129// --------------------------------------------------------------------------
130//
131// Return time as MJD (=JD-24000000.5)
132//
133Double_t MTime::GetMjd() const
134{
135 return fMjd+(Double_t)(fNanoSec/1e6+(Long_t)fTime)/kDay;
136}
137
138// --------------------------------------------------------------------------
139//
140// Return a time which is expressed in milliseconds since 01/01/1995 0:00h
141// This is compatible with root's definition used in gSystem->Now()
142// and TTime.
143// Note, gSystem->Now() returns local time, such that it may differ
144// from GetRootTime() (if you previously called MTime::Now())
145//
146TTime MTime::GetRootTime() const
147{
148 return (ULong_t)((GetMjd()-49718)*kDay);
149}
150
151// --------------------------------------------------------------------------
152//
153// Return a time which is expressed in seconds since 01/01/1995 0:00h
154// This is compatible with root's definition used in TAxis.
155// Note, a TAxis always displayes (automatically) given times in
156// local time (while here we return UTC) such, that you may encounter
157// strange offsets. You can get rid of this by calling:
158// TAxis::SetTimeFormat("[your-format] %F1995-01-01 00:00:00");
159//
160// Be carefull: It seems that root takes sommer and winter time into account!
161// In some circumstances you may need
162// TAxis::SetTimeFormat("[your-format] %F1995-01-00 23:00:00");
163//
164Double_t MTime::GetAxisTime() const
165{
166 return (GetMjd()-49718)*kDay/1000;
167}
168
169// --------------------------------------------------------------------------
170//
171// Set a time expressed in MJD, Time of Day (eg. 23:12.779h expressed
172// in milliseconds) and a nanosecond part.
173//
174Bool_t MTime::SetMjd(UInt_t mjd, ULong_t ms, UInt_t ns)
175{
176 // [d] mjd (eg. 52320)
177 // [ms] time (eg. 17h expressed in ms)
178 // [ns] time (ns part of time)
179
180 if (ms>kDay-1 || ns>999999)
181 return kFALSE;
182
183 const Bool_t am = ms<kHour*13; // day of sunrise?
184
185 fMjd = am ? mjd : mjd + 1;
186 fTime = (Long_t)(am ? ms : ms-kDay);
187 fNanoSec = ns;
188
189 return kTRUE;
190}
191
192// --------------------------------------------------------------------------
193//
194// Set MTime to given MJD (eg. 52080.0915449892)
195//
196void MTime::SetMjd(Double_t m)
197{
198 const UInt_t mjd = (UInt_t)TMath::Floor(m);
199 const Double_t frac = fmod(m, 1)*kDay; // [ms] Fraction of day
200 const UInt_t ns = (UInt_t)fmod(frac*1e6, 1000000);
201
202 SetMjd(mjd, (ULong_t)TMath::Floor(frac), ns);
203}
204
205// --------------------------------------------------------------------------
206//
207// Set MTime to given time and date
208//
209Bool_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)
210{
211 if (h>23 || min>59 || s>59 || ms>999 || ns>999999)
212 return kFALSE;
213
214 const Int_t mjd = MAstro::Ymd2Mjd(y, m, d);
215 if (mjd<0)
216 return kFALSE;
217
218 const ULong_t tm = ((((h*60+min)*60)+s)*1000)+ms;
219
220 return SetMjd(mjd, tm, ns);
221}
222
223// --------------------------------------------------------------------------
224//
225// Set MTime to time expressed in a 'struct timeval'
226//
227void MTime::Set(const struct timeval &tv)
228{
229 const UInt_t mjd = 1000*tv.tv_sec/kDay + 40587;
230 const Long_t tm = tv.tv_sec%(24*3600)*1000 + tv.tv_usec/1000;
231 const UInt_t ms = tv.tv_usec%1000;
232
233 SetMjd(mjd, tm, ms*1000);
234}
235
236// --------------------------------------------------------------------------
237//
238// Return contents as a TString of the form:
239// "dd.mm.yyyy hh:mm:ss.fff"
240//
241Bool_t MTime::SetString(const char *str)
242{
243 if (!str)
244 return kFALSE;
245
246 UInt_t y, mon, d, h, m, s, ms;
247 const Int_t n = sscanf(str, "%02u.%02u.%04u %02u:%02u:%02u.%03u",
248 &d, &mon, &y, &h, &m, &s, &ms);
249
250 return n==7 ? Set(y, mon, d, h, m, s, ms) : kFALSE;
251}
252
253// --------------------------------------------------------------------------
254//
255// Return contents as a TString of the form:
256// "yyyy-mm-dd hh:mm:ss"
257//
258Bool_t MTime::SetSqlDateTime(const char *str)
259{
260 if (!str)
261 return kFALSE;
262
263 UInt_t y, mon, d, h, m, s;
264 const Int_t n = sscanf(str, "%04u-%02u-%02u %02u:%02u:%02u",
265 &y, &mon, &d, &h, &m, &s);
266
267 return n==6 ? Set(y, mon, d, h, m, s) : kFALSE;
268}
269
270// --------------------------------------------------------------------------
271//
272// Return contents as a TString of the form:
273// "yyyymmddhhmmss"
274//
275Bool_t MTime::SetSqlTimeStamp(const char *str)
276{
277 if (!str)
278 return kFALSE;
279
280 UInt_t y, mon, d, h, m, s;
281 const Int_t n = sscanf(str, "%04u%02u%02u%02u%02u%02u",
282 &y, &mon, &d, &h, &m, &s);
283
284 return n==6 ? Set(y, mon, d, h, m, s) : kFALSE;
285}
286
287// --------------------------------------------------------------------------
288//
289// Set MTime to time expressed as in CT1 PreProc files
290//
291void MTime::SetCT1Time(UInt_t mjd, UInt_t t1, UInt_t t0)
292{
293 // int isecs_since_midday; // seconds passed since midday before sunset (JD of run start)
294 // int isecfrac_200ns; // fractional part of isecs_since_midday
295 // fTime->SetTime(isecfrac_200ns, isecs_since_midday);
296 fNanoSec = (200*t1)%1000000;
297 const ULong_t ms = (200*t1)/1000000 + t0+12*kHour;
298
299 fTime = (Long_t)(ms<13*kHour ? ms : ms-kDay);
300
301 fMjd = mjd+1;
302}
303
304// --------------------------------------------------------------------------
305//
306// Update the magic time. Make sure, that the MJD is set correctly.
307// It must be the MJD of the corresponding night. You can set it
308// by Set(2003, 12, 24);
309//
310// It is highly important, that the time correspoding to the night is
311// between 13:00:00.0 (day of dawning) and 12:59:59.999 (day of sunrise)
312//
313Bool_t MTime::UpdMagicTime(Byte_t h, Byte_t m, Byte_t s, UInt_t ns)
314{
315 if (h>23 || m>59 || s>59 || ns>999999999)
316 return kFALSE;
317
318 const ULong_t tm = ((((h*60+m)*60)+s)*1000)+ns/1000000;
319
320 fTime = (Long_t)(tm<kHour*13 ? tm : tm-kDay); // day of sunrise?
321 fNanoSec = ns%1000000;
322
323 return kTRUE;
324
325}
326
327// --------------------------------------------------------------------------
328//
329// Conversion from Universal Time to Greenwich mean sidereal time,
330// with rounding errors minimized.
331//
332// The result is the Greenwich Mean Sidereal Time (radians)
333//
334// There is no restriction on how the UT is apportioned between the
335// date and ut1 arguments. Either of the two arguments could, for
336// example, be zero and the entire date+time supplied in the other.
337// However, the routine is designed to deliver maximum accuracy when
338// the date argument is a whole number and the ut argument lies in
339// the range 0 to 1, or vice versa.
340//
341// The algorithm is based on the IAU 1982 expression (see page S15 of
342// the 1984 Astronomical Almanac). This is always described as giving
343// the GMST at 0 hours UT1. In fact, it gives the difference between
344// the GMST and the UT, the steady 4-minutes-per-day drawing-ahead of
345// ST with respect to UT. When whole days are ignored, the expression
346// happens to equal the GMST at 0 hours UT1 each day.
347//
348// In this routine, the entire UT1 (the sum of the two arguments date
349// and ut) is used directly as the argument for the standard formula.
350// The UT1 is then added, but omitting whole days to conserve accuracy.
351//
352// The extra numerical precision delivered by the present routine is
353// unlikely to be important in an absolute sense, but may be useful
354// when critically comparing algorithms and in applications where two
355// sidereal times close together are differenced.
356//
357Double_t MTime::GetGmst() const
358{
359 const Double_t ut = (Double_t)(fNanoSec/1e6+(Long_t)fTime)/kDay;
360
361 // Julian centuries since J2000.
362 const Double_t t = (ut -(51544.5-fMjd)) / 36525.0;
363
364 // GMST at this UT1
365 const Double_t r1 = 24110.54841+(8640184.812866+(0.093104-6.2e-6*t)*t)*t;
366 const Double_t r2 = 86400.0*ut;
367
368 const Double_t sum = (r1+r2)/(24*3600);
369
370 return fmod(sum, 1)*TMath::TwoPi();//+TMath::TwoPi();
371}
372
373// --------------------------------------------------------------------------
374//
375// Set the time to the current system time. The timezone is ignored.
376// If everything is set correctly you'll get UTC.
377//
378void MTime::Now()
379{
380#ifdef __LINUX__
381 struct timeval tv;
382 if (gettimeofday(&tv, NULL)<0)
383 Clear();
384 else
385 Set(tv);
386#else
387 Clear();
388#endif
389}
390
391// --------------------------------------------------------------------------
392//
393// Return contents as a TString of the form:
394// "dd.mm.yyyy hh:mm:ss.fff"
395//
396TString MTime::GetString() const
397{
398 UShort_t y, ms;
399 Byte_t mon, d, h, m, s;
400
401 GetDate(y, mon, d);
402 GetTime(h, m, s, ms);
403
404 return TString(Form("%02d.%02d.%04d %02d:%02d:%02d.%03d", d, mon, y, h, m, s, ms));
405}
406
407// --------------------------------------------------------------------------
408//
409// Return contents as a string format'd with strftime:
410// Here is a short summary of the most important formats. For more
411// information see the man page (or any other description) of
412// strftime...
413//
414// %a The abbreviated weekday name according to the current locale.
415// %A The full weekday name according to the current locale.
416// %b The abbreviated month name according to the current locale.
417// %B The full month name according to the current locale.
418// %c The preferred date and time representation for the current locale.
419// %d The day of the month as a decimal number (range 01 to 31).
420// %e Like %d, the day of the month as a decimal number,
421// but a leading zero is replaced by a space.
422// %H The hour as a decimal number using a 24-hour clock (range 00 to 23)
423// %k The hour (24-hour clock) as a decimal number (range 0 to 23);
424// single digits are preceded by a blank.
425// %m The month as a decimal number (range 01 to 12).
426// %M The minute as a decimal number (range 00 to 59).
427// %R The time in 24-hour notation (%H:%M). For a
428// version including the seconds, see %T below.
429// %S The second as a decimal number (range 00 to 61).
430// %T The time in 24-hour notation (%H:%M:%S).
431// %x The preferred date representation for the current
432// locale without the time.
433// %X The preferred time representation for the current
434// locale without the date.
435// %y The year as a decimal number without a century (range 00 to 99).
436// %Y The year as a decimal number including the century.
437// %+ The date and time in date(1) format.
438//
439// The default is: Tuesday 16.February 2004 12:17:22
440//
441// The maximum size of the return string is 128 (incl. NULL)
442//
443TString MTime::GetStringFmt(const char *fmt) const
444{
445 if (!fmt)
446 fmt = "%A %e.%B %Y %H:%M:%S";
447
448 UShort_t y, ms;
449 Byte_t mon, d, h, m, s;
450
451 GetDate(y, mon, d);
452 GetTime(h, m, s, ms);
453
454 struct tm time;
455 time.tm_sec = s;
456 time.tm_min = m;
457 time.tm_hour = h;
458 time.tm_mday = d;
459 time.tm_mon = mon-1;
460 time.tm_year = y-1900;
461 time.tm_isdst = 0;
462
463 // recalculate tm_yday and tm_wday
464 mktime(&time);
465
466 char ret[128];
467 return TString(strftime(ret, 127, fmt, &time) ? ret : "");
468}
469
470// --------------------------------------------------------------------------
471//
472// Return contents as a TString of the form:
473// "yyyy-mm-dd hh:mm:ss"
474//
475TString MTime::GetSqlDateTime() const
476{
477 return GetStringFmt("%Y-%m-%d %H:%M:%S");
478}
479
480// --------------------------------------------------------------------------
481//
482// Return contents as a TString of the form:
483// "yyyymmddhhmmss"
484//
485TString MTime::GetSqlTimeStamp() const
486{
487 return GetStringFmt("%Y%m%d%H%M%S");
488}
489
490// --------------------------------------------------------------------------
491//
492// Return contents as a TString of the form:
493// "yyyymmdd_hhmmss"
494//
495TString MTime::GetFileName() const
496{
497 return GetStringFmt("%Y%m%d_%H%M%S");
498}
499
500// --------------------------------------------------------------------------
501//
502// Print MTime as string
503//
504void MTime::Print(Option_t *) const
505{
506 UShort_t yea, ms;
507 Byte_t mon, day, h, m, s;
508
509 GetDate(yea, mon, day);
510 GetTime(h, m, s, ms);
511
512 *fLog << all << GetDescriptor() << ": ";
513 *fLog << GetString() << Form(" (+%dns)", fNanoSec) << endl;
514}
515
516istream &MTime::ReadBinary(istream &fin)
517{
518 UShort_t y;
519 Byte_t mon, d, h, m, s;
520
521 fin.read((char*)&y, 2);
522 fin.read((char*)&mon, 1);
523 fin.read((char*)&d, 1);
524 fin.read((char*)&h, 1);
525 fin.read((char*)&m, 1);
526 fin.read((char*)&s, 1); // Total=7
527
528 Set(y, mon, d, h, m, s, 0);
529
530 return fin;
531}
Note: See TracBrowser for help on using the repository browser.