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

Last change on this file since 9301 was 9210, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 31.6 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-2008
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#ifndef __USE_XOPEN
74#define __USE_XOPEN // on some systems needed for strptime
75#endif
76
77#include <time.h> // struct tm
78#include <sys/time.h> // struct timeval
79
80#include <TTime.h>
81
82#include "MLog.h"
83#include "MLogManip.h"
84
85#include "MAstro.h"
86
87ClassImp(MTime);
88
89using namespace std;
90
91const UInt_t MTime::kHour = 3600000; // [ms] one hour
92const UInt_t MTime::kDay = MTime::kHour*24; // [ms] one day
93const UInt_t MTime::kDaySec = 3600*24; // [s] one day
94
95// --------------------------------------------------------------------------
96//
97// Constructor. Calls SetMjd(d) for d>0 in all other cases the time
98// is set to the current UTC time.
99//
100MTime::MTime(Double_t d)
101{
102 Init(0, 0);
103 if (d<=0)
104 Now();
105 else
106 SetMjd(d);
107}
108
109// --------------------------------------------------------------------------
110//
111// Constructor. Calls Set(y, m, d, h, min, s, ms, ns).
112// To check validity test for (*this)==MTime()
113//
114MTime::MTime(UShort_t y, Byte_t m, Byte_t d, Byte_t h, Byte_t min, Byte_t s, UShort_t ms, UInt_t ns)
115{
116 Set(y, m, d, h, min, s, ms, ns);
117}
118
119// --------------------------------------------------------------------------
120//
121// Return date as year(y), month(m), day(d)
122//
123void MTime::GetDate(UShort_t &y, Byte_t &m, Byte_t &d) const
124{
125 MAstro::Mjd2Ymd((Long_t)fTime<0?fMjd-1:fMjd, y, m, d);
126}
127
128// --------------------------------------------------------------------------
129//
130// Return date as year(y), month(m), day(d). If the time is afternoon
131// (>=13:00:00) the date of the next day is returned.
132//
133void MTime::GetDateOfSunrise(UShort_t &y, Byte_t &m, Byte_t &d) const
134{
135 MAstro::Mjd2Ymd(fMjd, y, m, d);
136}
137
138// --------------------------------------------------------------------------
139//
140// Return date as year(y), month(m), day(d). If the time is afternoon
141// (>=13:00:00) the date of the next day is returned.
142//
143MTime MTime::GetDateOfSunrise() const
144{
145 UShort_t y;
146 Byte_t m;
147 Byte_t d;
148
149 MAstro::Mjd2Ymd(fMjd, y, m, d);
150
151 return MTime(y, m, d);
152}
153
154// --------------------------------------------------------------------------
155//
156// GetMoonPhase - calculate phase of moon as a fraction:
157// Returns -1 if calculation failed
158//
159// see MAstro::GetMoonPhase
160//
161Double_t MTime::GetMoonPhase() const
162{
163 return MAstro::GetMoonPhase(GetMjd());
164}
165
166// --------------------------------------------------------------------------
167//
168// Calculate the Period to which the time belongs to. The Period is defined
169// as the number of synodic months ellapsed since the first full moon
170// after Jan 1st 1980 (which was @ MJD=44240.37917)
171//
172// see MAstro::GetMoonPeriod
173//
174Double_t MTime::GetMoonPeriod() const
175{
176 return MAstro::GetMoonPeriod(GetMjd());
177}
178
179// --------------------------------------------------------------------------
180//
181// Set the time corresponding to the moon period.
182//
183// see MTime::GetMoonPeriod and MAstro::GetMoonPeriod
184//
185void MTime::SetMoonPeriod(Double_t p)
186{
187 SetMjd(MAstro::GetMoonPeriodMjd(p));
188}
189
190// --------------------------------------------------------------------------
191//
192// To get the moon period as defined for MAGIC observation we take the
193// nearest integer mjd, eg:
194// 53257.8 --> 53258
195// 53258.3 --> 53258
196 // Which is the time between 13h and 12:59h of the following day. To
197// this day-period we assign the moon-period at midnight. To get
198// the MAGIC definition we now substract 284.
199//
200// For MAGIC observation period do eg:
201// GetMagicPeriod(53257.91042)
202// or
203// MTime t;
204// t.SetMjd(53257.91042);
205// GetMagicPeriod(t.GetMjd());
206// or
207// MTime t;
208// t.Set(2004, 1, 1, 12, 32, 11);
209// GetMagicPeriod(t.GetMjd());
210//
211// To get a floating point magic period use
212// GetMoonPeriod()-284
213//
214// see MAstro::GetMagicPeriod
215//
216Int_t MTime::GetMagicPeriod() const
217{
218 return MAstro::GetMagicPeriod(GetMjd());
219}
220
221// --------------------------------------------------------------------------
222//
223// Set the start time (noon) of a MAGIC period
224//
225// see MTime::GetMagicPeriod and MAstro::GetMagicPeriod
226//
227void MTime::SetMagicPeriodStart(Int_t p)
228{
229 SetMjd(MAstro::GetMagicPeriodStart(p));
230}
231
232// --------------------------------------------------------------------------
233//
234// Return the time in the range [0h, 24h) = [0h0m0.000s - 23h59m59.999s]
235//
236void MTime::GetTime(Byte_t &h, Byte_t &m, Byte_t &s, UShort_t &ms) const
237{
238 Long_t tm = GetTime24();
239 ms = tm%1000; // [ms]
240 tm /= 1000; // [s]
241 s = tm%60; // [s]
242 tm /= 60; // [m]
243 m = tm%60; // [m]
244 tm /= 60; // [h]
245 h = tm; // [h]
246}
247
248// --------------------------------------------------------------------------
249//
250// Return time as MJD (=JD-24000000.5)
251//
252Double_t MTime::GetMjd() const
253{
254 return fMjd+(Double_t)(fNanoSec/1e6+(Long_t)fTime)/kDay;
255}
256
257// --------------------------------------------------------------------------
258//
259// Return a time which is expressed in milliseconds since 01/01/1995 0:00h
260// This is compatible with root's definition used in gSystem->Now()
261// and TTime.
262// Note, gSystem->Now() returns local time, such that it may differ
263// from GetRootTime() (if you previously called MTime::Now())
264//
265TTime MTime::GetRootTime() const
266{
267 return (ULong_t)((GetMjd()-49718)*kDay);
268}
269
270// --------------------------------------------------------------------------
271//
272// Return a time which is expressed in seconds since 01/01/1970 0:00h
273// This is compatible with root's definition used in the constructor of
274// TDatime.
275//
276TDatime MTime::GetRootDatime() const
277{
278 return TDatime((UInt_t)((GetMjd()-40587)*kDaySec));
279}
280
281// --------------------------------------------------------------------------
282//
283// Return a time which is expressed in seconds since 01/01/1995 0:00h
284// This is compatible with root's definition used in TAxis.
285// Note, a TAxis always displayes (automatically) given times in
286// local time (while here we return UTC) such, that you may encounter
287// strange offsets. You can get rid of this by calling:
288// TAxis::SetTimeFormat("[your-format] %F1995-01-01 00:00:00 GMT");
289//
290Double_t MTime::GetAxisTime() const
291{
292 return (GetMjd()-49718)*kDaySec;
293}
294
295// --------------------------------------------------------------------------
296//
297// Counterpart of GetAxisTime
298//
299void MTime::SetAxisTime(Double_t time)
300{
301 SetMjd(time/kDaySec+49718);
302}
303
304// --------------------------------------------------------------------------
305//
306// Set unix time (seconds since epoche 1970-01-01 00:00)
307//
308void MTime::SetUnixTime(Long64_t sec, ULong64_t usec)
309{
310 const Long64_t totsec = sec + usec/1000000;
311 const UInt_t mjd = totsec/kDaySec + 40587;
312
313 const UInt_t ms = totsec%kDaySec*1000 + (usec/1000)%1000;
314 const UInt_t us = usec%1000;
315
316 SetMjd(mjd, ms, us*1000);
317}
318
319// --------------------------------------------------------------------------
320//
321// Set MTime to time expressed in a 'struct timeval'
322//
323void MTime::Set(const struct timeval &tv)
324{
325 SetUnixTime(tv.tv_sec, tv.tv_usec);
326}
327
328// --------------------------------------------------------------------------
329//
330// Set this to the date of easter corresponding to the given year.
331// If calculation was not possible it is set to MTime()
332//
333// The date corresponding to the year of MTime(-1) is returned
334// if year<0
335//
336// The date corresponding to the Year() is returned if year==0.
337//
338// for more information see: GetEaster and MAstro::GetEasterOffset()
339//
340void MTime::SetEaster(Short_t year)
341{
342 *this = GetEaster(year==0 ? Year() : year);
343}
344
345// --------------------------------------------------------------------------
346//
347// Set a time expressed in MJD, Time of Day (eg. 23:12.779h expressed
348// in milliseconds) and a nanosecond part.
349//
350Bool_t MTime::SetMjd(UInt_t mjd, ULong_t ms, UInt_t ns)
351{
352 // [d] mjd (eg. 52320)
353 // [ms] time (eg. 17h expressed in ms)
354 // [ns] time (ns part of time)
355
356 if (ms>kDay-1 || ns>999999)
357 return kFALSE;
358
359 const Bool_t am = ms<kHour*13; // day of sunrise?
360
361 fMjd = am ? mjd : mjd + 1;
362 fTime = (Long_t)(am ? ms : ms-kDay);
363 fNanoSec = ns;
364
365 return kTRUE;
366}
367
368// --------------------------------------------------------------------------
369//
370// Set MTime to given MJD (eg. 52080.0915449892)
371//
372void MTime::SetMjd(Double_t m)
373{
374 const UInt_t mjd = (UInt_t)TMath::Floor(m);
375 const Double_t frac = fmod(m, 1)*kDay; // [ms] Fraction of day
376 const UInt_t ns = (UInt_t)fmod(frac*1e6, 1000000);
377
378 SetMjd(mjd, (ULong_t)TMath::Floor(frac), ns);
379}
380
381// --------------------------------------------------------------------------
382//
383// Set MTime to given time and date
384//
385Bool_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)
386{
387 if (h>23 || min>59 || s>59 || ms>999 || ns>999999)
388 return kFALSE;
389
390 const Int_t mjd = MAstro::Ymd2Mjd(y, m, d);
391 if (mjd<0)
392 return kFALSE;
393
394 const ULong_t tm = ((((h*60+min)*60)+s)*1000)+ms;
395
396 return SetMjd(mjd, tm, ns);
397}
398
399// --------------------------------------------------------------------------
400//
401// Return contents as a TString of the form:
402// "dd.mm.yyyy hh:mm:ss.fff"
403//
404Bool_t MTime::SetString(const char *str)
405{
406 if (!str)
407 return kFALSE;
408
409 UInt_t y, mon, d, h, m, s, ms;
410 const Int_t n = sscanf(str, "%02u.%02u.%04u %02u:%02u:%02u.%03u",
411 &d, &mon, &y, &h, &m, &s, &ms);
412
413 return n==7 ? Set(y, mon, d, h, m, s, ms) : kFALSE;
414}
415
416// --------------------------------------------------------------------------
417//
418// Return contents as a TString of the form:
419// "yyyy-mm-dd hh:mm:ss"
420//
421Bool_t MTime::SetSqlDateTime(const char *str)
422{
423 if (!str)
424 return kFALSE;
425
426 UInt_t y, mon, d, h, m, s, ms;
427
428 if (7==sscanf(str, "%04u-%02u-%02u %02u:%02u:%02u.%u", &y, &mon, &d, &h, &m, &s, &ms))
429 return Set(y, mon, d, h, m, s, ms);
430
431 if (6==sscanf(str, "%04u-%02u-%02u %02u:%02u:%02u", &y, &mon, &d, &h, &m, &s))
432 return Set(y, mon, d, h, m, s);
433
434 if (5==sscanf(str, "%04u-%02u-%02u %02u:%02u", &y, &mon, &d, &h, &m))
435 return Set(y, mon, d, h, m);
436
437 if (4==sscanf(str, "%04u-%02u-%02u %02u", &y, &mon, &d, &h))
438 return Set(y, mon, d, h);
439
440 if (3==sscanf(str, "%04u-%02u-%02u", &y, &mon, &d))
441 return Set(y, mon, d);
442
443 return kFALSE;
444}
445
446// --------------------------------------------------------------------------
447//
448// Return contents as a TString of the form:
449// "yyyymmddhhmmss"
450//
451Bool_t MTime::SetSqlTimeStamp(const char *str)
452{
453 if (!str)
454 return kFALSE;
455
456 UInt_t y, mon, d, h, m, s;
457 const Int_t n = sscanf(str, "%04u%02u%02u%02u%02u%02u",
458 &y, &mon, &d, &h, &m, &s);
459
460 return n==6 ? Set(y, mon, d, h, m, s) : kFALSE;
461}
462
463// --------------------------------------------------------------------------
464//
465// Set MTime to time expressed as in CT1 PreProc files
466//
467void MTime::SetCT1Time(UInt_t mjd, UInt_t t1, UInt_t t0)
468{
469 // int isecs_since_midday; // seconds passed since midday before sunset (JD of run start)
470 // int isecfrac_200ns; // fractional part of isecs_since_midday
471 // fTime->SetTime(isecfrac_200ns, isecs_since_midday);
472 fNanoSec = (200*t1)%1000000;
473 const ULong_t ms = (200*t1)/1000000 + t0+12*kHour;
474
475 fTime = (Long_t)(ms<13*kHour ? ms : ms-kDay);
476
477 fMjd = mjd+1;
478}
479
480// --------------------------------------------------------------------------
481//
482// Set MTime to time expressed as float (yymmdd.ffff)
483// for details see MAstro::Yymmdd2Mjd
484//
485void MTime::SetCorsikaTime(Float_t t)
486{
487 const UInt_t yymmdd = (UInt_t)TMath::Floor(t);
488 const UInt_t mjd = MAstro::Yymmdd2Mjd(yymmdd);
489 const Double_t frac = fmod(t, 1)*kDay; // [ms] Fraction of day
490 const UInt_t ns = (UInt_t)fmod(frac*1e6, 1000000);
491
492 SetMjd(mjd, (ULong_t)TMath::Floor(frac), ns);
493}
494
495// --------------------------------------------------------------------------
496//
497// Update the magic time. Make sure, that the MJD is set correctly.
498// It must be the MJD of the corresponding night. You can set it
499// by Set(2003, 12, 24);
500//
501// It is highly important, that the time correspoding to the night is
502// between 13:00:00.0 (day of dawning) and 12:59:59.999 (day of sunrise)
503//
504Bool_t MTime::UpdMagicTime(Byte_t h, Byte_t m, Byte_t s, UInt_t ns)
505{
506 if (h>23 || m>59 || s>59 || ns>999999999)
507 return kFALSE;
508
509 const ULong_t tm = ((((h*60+m)*60)+s)*1000)+ns/1000000;
510
511 fTime = (Long_t)(tm<kHour*13 ? tm : tm-kDay); // day of sunrise?
512 fNanoSec = ns%1000000;
513
514 return kTRUE;
515}
516
517// --------------------------------------------------------------------------
518//
519// Conversion from Universal Time to Greenwich mean sidereal time,
520// with rounding errors minimized.
521//
522// The result is the Greenwich Mean Sidereal Time (radians)
523//
524// There is no restriction on how the UT is apportioned between the
525// date and ut1 arguments. Either of the two arguments could, for
526// example, be zero and the entire date+time supplied in the other.
527// However, the routine is designed to deliver maximum accuracy when
528// the date argument is a whole number and the ut argument lies in
529// the range 0 to 1, or vice versa.
530//
531// The algorithm is based on the IAU 1982 expression (see page S15 of
532// the 1984 Astronomical Almanac). This is always described as giving
533// the GMST at 0 hours UT1. In fact, it gives the difference between
534// the GMST and the UT, the steady 4-minutes-per-day drawing-ahead of
535// ST with respect to UT. When whole days are ignored, the expression
536// happens to equal the GMST at 0 hours UT1 each day.
537//
538// In this routine, the entire UT1 (the sum of the two arguments date
539// and ut) is used directly as the argument for the standard formula.
540// The UT1 is then added, but omitting whole days to conserve accuracy.
541//
542// The extra numerical precision delivered by the present routine is
543// unlikely to be important in an absolute sense, but may be useful
544// when critically comparing algorithms and in applications where two
545// sidereal times close together are differenced.
546//
547Double_t MTime::GetGmst() const
548{
549 const Double_t ut = (Double_t)(fNanoSec/1e6+(Long_t)fTime)/kDay;
550
551 // Julian centuries since J2000.
552 const Double_t t = (ut -(51544.5-fMjd)) / 36525.0;
553
554 // GMST at this UT1
555 const Double_t r1 = 24110.54841+(8640184.812866+(0.093104-6.2e-6*t)*t)*t;
556 const Double_t r2 = 86400.0*ut;
557
558 const Double_t sum = (r1+r2)/kDaySec;
559
560 return fmod(sum, 1)*TMath::TwoPi();//+TMath::TwoPi();
561}
562
563// --------------------------------------------------------------------------
564//
565// Return Day of the week: Sun=0, Mon=1, ..., Sat=6
566//
567Byte_t MTime::WeekDay() const
568{
569 return TMath::FloorNint(GetMjd()+3)%7;
570}
571
572// --------------------------------------------------------------------------
573//
574// Get the day of the year represented by day, month and year.
575// Valid return values range between 1 and 366, where January 1 = 1.
576//
577UInt_t MTime::DayOfYear() const
578{
579 MTime jan1st;
580 jan1st.Set(Year(), 1, 1);
581
582 const Double_t newyear = TMath::Floor(jan1st.GetMjd());
583 const Double_t mjd = TMath::Floor(GetMjd());
584
585 return TMath::Nint(mjd-newyear)+1;
586}
587
588// --------------------------------------------------------------------------
589//
590// Return Mjd of the first day (a monday) which belongs to week 1 of
591// the year give as argument. The returned Mjd might be a date in the
592// year before.
593//
594// see also MTime::Week()
595//
596Int_t MTime::GetMjdWeek1(Short_t year)
597{
598 MTime t;
599 t.Set(year, 1, 4);
600
601 return (Int_t)t.GetMjd() + t.WeekDay() - 6;
602}
603
604// --------------------------------------------------------------------------
605//
606// Get the week of the year. Valid week values are between 1 and 53.
607// If for a january date a week number above 50 is returned the
608// week belongs to the previous year. If for a december data 1 is
609// returned the week already belongs to the next year.
610//
611// The year to which the week belongs is returned in year.
612//
613// Die Kalenderwochen werden für Jahre ab 1976 berechnet, da mit
614// Geltung vom 1. Januar 1976 der Wochenbeginn auf Montag festgelegt
615// wurde. Die erste Woche ist definiert als die Woche, in der
616// mindestens 4 der ersten 7 Januartage fallen (also die Woche, in der
617// der 4. Januar liegt). Beides wurde damals festgelegt in der DIN 1355
618// (1974). Inhaltlich gleich regelt das die Internationale Norm
619// ISO 8601 (1988), die von der Europäischen Union als EN 28601 (1992)
620// übernommen und in Deutschland als DIN EN 28601 (1993) umgesetzt
621// wurde.
622//
623Int_t MTime::Week(Short_t &year) const
624{
625 // Possibilities for Week 1:
626 //
627 // Mo 4.Jan: Mo 4. - So 10. -0 6-6
628 // Di 4.Jan: Mo 3. - So 9. -1 6-5
629 // Mi 4.Jan: Mo 2. - So 8. -2 6-4
630 // Do 4.Jan: Mo 1. - So 7. -3 6-3
631 // Fr 4.Jan: Mo 31. - So 6. -4 6-2
632 // Sa 4.Jan: Mo 30. - So 5. -5 6-1
633 // So 4.Jan: Mo 29. - So 4. -6 6-0
634 //
635 const Int_t mjd2 = GetMjdWeek1(Year()-1);
636 const Int_t mjd0 = GetMjdWeek1(Year());
637 const Int_t mjd3 = GetMjdWeek1(Year()+1);
638
639 // Today
640 const Int_t mjd = (Int_t)GetMjd();
641
642 // Week belongs to last year, return week of last year
643 if (mjd<mjd0)
644 {
645 year = Year()-1;
646 return (mjd-mjd2)/7 + 1;
647 }
648
649 // Check if Week belongs to next year (can only be week 1)
650 if ((mjd3-mjd)/7==1)
651 {
652 year = Year()+1;
653 return 1;
654 }
655
656 // Return calculated Week
657 year = Year();
658 return (mjd-mjd0)/7 + 1;
659}
660
661// --------------------------------------------------------------------------
662//
663// Is the given year a leap year.
664// The calendar year is 365 days long, unless the year is exactly divisible
665// by 4, in which case an extra day is added to February to make the year
666// 366 days long. If the year is the last year of a century, eg. 1700, 1800,
667// 1900, 2000, then it is only a leap year if it is exactly divisible by
668// 400. Therefore, 1900 wasn't a leap year but 2000 was. The reason for
669// these rules is to bring the average length of the calendar year into
670// line with the length of the Earth's orbit around the Sun, so that the
671// seasons always occur during the same months each year.
672//
673Bool_t MTime::IsLeapYear() const
674{
675 const UInt_t y = Year();
676 return (y%4==0) && !((y%100==0) && (y%400>0));
677}
678
679// --------------------------------------------------------------------------
680//
681// Set the time to the current system time. The timezone is ignored.
682// If everything is set correctly you'll get UTC.
683//
684void MTime::Now()
685{
686#ifdef __LINUX__
687 struct timeval tv;
688 if (gettimeofday(&tv, NULL)<0)
689 Clear();
690 else
691 Set(tv);
692#else
693 Clear();
694#endif
695}
696
697// --------------------------------------------------------------------------
698//
699// Return contents as a TString of the form:
700// "dd.mm.yyyy hh:mm:ss.fff"
701//
702TString MTime::GetString() const
703{
704 UShort_t y, ms;
705 Byte_t mon, d, h, m, s;
706
707 GetDate(y, mon, d);
708 GetTime(h, m, s, ms);
709
710 return TString(Form("%02d.%02d.%04d %02d:%02d:%02d.%03d", d, mon, y, h, m, s, ms));
711}
712
713// --------------------------------------------------------------------------
714//
715// Return contents as a string format'd with strftime:
716// Here is a short summary of the most important formats. For more
717// information see the man page (or any other description) of
718// strftime...
719//
720// %a The abbreviated weekday name according to the current locale.
721// %A The full weekday name according to the current locale.
722// %b The abbreviated month name according to the current locale.
723// %B The full month name according to the current locale.
724// %c The preferred date and time representation for the current locale.
725// %d The day of the month as a decimal number (range 01 to 31).
726// %e Like %d, the day of the month as a decimal number,
727// but a leading zero is replaced by a space.
728// %H The hour as a decimal number using a 24-hour clock (range 00 to 23)
729// %k The hour (24-hour clock) as a decimal number (range 0 to 23);
730// single digits are preceded by a blank.
731// %m The month as a decimal number (range 01 to 12).
732// %M The minute as a decimal number (range 00 to 59).
733// %R The time in 24-hour notation (%H:%M). For a
734// version including the seconds, see %T below.
735// %S The second as a decimal number (range 00 to 61).
736// %T The time in 24-hour notation (%H:%M:%S).
737// %x The preferred date representation for the current
738// locale without the time.
739// %X The preferred time representation for the current
740// locale without the date.
741// %y The year as a decimal number without a century (range 00 to 99).
742// %Y The year as a decimal number including the century.
743// %+ The date and time in date(1) format.
744//
745// The default is: Tuesday 16.February 2004 12:17:22
746//
747// The maximum size of the return string is 128 (incl. NULL)
748//
749// For dates before 1. 1.1902 a null string is returned
750// For dates after 31.12.2037 a null string is returned
751//
752// To change the localization use loc, eg loc = "da_DK", "de_DE".
753// Leaving the argument empty will just take the default localization.
754//
755// If loc is "", each part of the locale that should be modified is set
756// according to the environment variables. The details are implementation
757// dependent. For glibc, first (regardless of category), the environment
758// variable LC_ALL is inspected, next the environment variable with the
759// same name as the category (LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONE?
760// TARY, LC_NUMERIC, LC_TIME) and finally the environment variable LANG.
761// The first existing environment variable is used.
762//
763// A locale name is typically of the form language[_territory][.code?
764// set][@modifier], where language is an ISO 639 language code, territory
765// is an ISO 3166 country code, and codeset is a character set or encoding
766// identifier like ISO-8859-1 or UTF-8. For a list of all supported
767// locales, try "locale -a", cf. locale(1).
768//
769TString MTime::GetStringFmt(const char *fmt, const char *loc) const
770{
771 if (!fmt)
772 fmt = "%A %e.%B %Y %H:%M:%S";
773
774 UShort_t y, ms;
775 Byte_t mon, d, h, m, s;
776
777 GetDate(y, mon, d);
778 GetTime(h, m, s, ms);
779
780 // If date<1902 strftime crahses on my (tbretz) laptop
781 // it doesn't crash in the DC.
782 // if (y<1902 || y>2037)
783 // return "";
784
785 struct tm time;
786 time.tm_sec = s;
787 time.tm_min = m;
788 time.tm_hour = h;
789 time.tm_mday = d;
790 time.tm_mon = mon-1;
791 time.tm_year = y-1900;
792 time.tm_isdst = -1;
793
794 // -1: If dst, isdst is set to 1 but hour is not changed
795 // 0: If dst, hour is changed
796
797 // Get old local
798 const TString locale = setlocale(LC_TIME, 0);
799
800 // Set new local (e.g. Montag instead of Monday)
801 setlocale(LC_TIME, loc);
802
803 // recalculate tm_yday and tm_wday
804 mktime(&time);
805
806 // We get errors for example for 1910-01-01
807 // if (mktime(&time)<0)
808 // return "";
809
810 char ret[128];
811 const size_t rc = strftime(ret, 127, fmt, &time);
812
813 setlocale(LC_TIME, locale);
814
815 return rc ? ret : "";
816}
817
818// --------------------------------------------------------------------------
819//
820// Set the time according to the format fmt.
821// Default is "%A %e.%B %Y %H:%M:%S"
822//
823// For more information see GetStringFmt
824//
825Bool_t MTime::SetStringFmt(const char *time, const char *fmt, const char *loc)
826{
827 if (!fmt)
828 fmt = "%A %e.%B %Y %H:%M:%S";
829
830 struct tm t;
831 memset(&t, 0, sizeof(struct tm));
832
833 const TString locale = setlocale(LC_TIME, 0);
834
835 setlocale(LC_TIME, loc);
836 strptime(time, fmt, &t);
837 setlocale(LC_TIME, locale);
838
839 return Set(t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
840}
841
842// --------------------------------------------------------------------------
843//
844// Return contents as a TString of the form:
845// "yyyy-mm-dd hh:mm:ss"
846//
847TString MTime::GetSqlDateTime() const
848{
849 return GetStringFmt("%Y-%m-%d %H:%M:%S");
850}
851
852// --------------------------------------------------------------------------
853//
854// Return contents as a TString of the form:
855// "yyyymmddhhmmss"
856//
857TString MTime::GetSqlTimeStamp() const
858{
859 return GetStringFmt("%Y%m%d%H%M%S");
860}
861
862// --------------------------------------------------------------------------
863//
864// Return contents as a TString of the form:
865// "yyyymmdd_hhmmss"
866//
867TString MTime::GetFileName() const
868{
869 return GetStringFmt("%Y%m%d_%H%M%S");
870}
871
872// --------------------------------------------------------------------------
873//
874// Print MTime as string
875//
876void MTime::Print(Option_t *) const
877{
878 UShort_t yea, ms;
879 Byte_t mon, day, h, m, s;
880
881 GetDate(yea, mon, day);
882 GetTime(h, m, s, ms);
883
884 *fLog << all << GetDescriptor() << ": ";
885 *fLog << GetString() << Form(" (+%dns)", fNanoSec) << endl;
886}
887
888// --------------------------------------------------------------------------
889//
890// Calls Set(t[0], t[1], t[2], t[3], t[4], t[5], 0)
891//
892Bool_t MTime::SetBinary(const UInt_t t[6])
893{
894 return Set(t[0], t[1], t[2], t[3], t[4], t[5], 0);
895}
896
897// --------------------------------------------------------------------------
898//
899// Assign:
900// t[0] = year;
901// t[1] = month;
902// t[2] = day;
903// t[3] = hour;
904// t[4] = minute;
905// t[5] = second;
906//
907void MTime::GetBinary(UInt_t t[6]) const
908{
909 UShort_t yea, ms;
910 Byte_t mon, day, h, m, s;
911
912 GetDate(yea, mon, day);
913 GetTime(h, m, s, ms);
914
915 t[0] = yea;
916 t[1] = mon;
917 t[2] = day;
918 t[3] = h;
919 t[4] = m;
920 t[5] = s;
921}
922
923// --------------------------------------------------------------------------
924//
925// Read seven bytes representing y, m, d, h, m, s
926//
927istream &MTime::ReadBinary(istream &fin)
928{
929 UShort_t y;
930 Byte_t mon, d, h, m, s;
931
932 fin.read((char*)&y, 2);
933 fin.read((char*)&mon, 1);
934 fin.read((char*)&d, 1);
935 fin.read((char*)&h, 1);
936 fin.read((char*)&m, 1);
937 fin.read((char*)&s, 1); // Total=7
938
939 Set(y, mon, d, h, m, s, 0);
940
941 return fin;
942}
943
944// --------------------------------------------------------------------------
945//
946// Write seven bytes representing y, m, d, h, m, s
947//
948ostream &MTime::WriteBinary(ostream &out) const
949{
950 UShort_t y, ms;
951 Byte_t mon, d, h, m, s;
952
953 GetDate(y, mon, d);
954 GetTime(h, m, s, ms);
955
956 out.write((char*)&y, 2);
957 out.write((char*)&mon, 1);
958 out.write((char*)&d, 1);
959 out.write((char*)&h, 1);
960 out.write((char*)&m, 1);
961 out.write((char*)&s, 1); // Total=7
962
963 return out;
964}
965
966void MTime::AddMilliSeconds(UInt_t ms)
967{
968 fTime += ms;
969
970 fTime += 11*kHour;
971 fMjd += (Long_t)fTime/kDay;
972 fTime = (Long_t)fTime%kDay;
973 fTime -= 11*kHour;
974}
975
976void MTime::Plus1ns()
977{
978 fNanoSec++;
979
980 if (fNanoSec<1000000)
981 return;
982
983 fNanoSec = 0;
984 fTime += 1;
985
986 if ((Long_t)fTime<(Long_t)kDay*13)
987 return;
988
989 fTime = 11*kDay;
990 fMjd++;
991}
992
993void MTime::Minus1ns()
994{
995 if (fNanoSec>0)
996 {
997 fNanoSec--;
998 return;
999 }
1000
1001 fTime -= 1;
1002 fNanoSec = 999999;
1003
1004 if ((Long_t)fTime>=-(Long_t)kDay*11)
1005 return;
1006
1007 fTime = 13*kDay-1;
1008 fMjd--;
1009}
1010
1011/*
1012MTime MTime::operator-(const MTime &tm1)
1013{
1014 const MTime &tm0 = *this;
1015
1016 MTime t0 = tm0>tm1 ? tm0 : tm1;
1017 const MTime &t1 = tm0>tm1 ? tm1 : tm0;
1018
1019 if (t0.fNanoSec<t1.fNanoSec)
1020 {
1021 t0.fNanoSec += 1000000;
1022 t0.fTime -= 1;
1023 }
1024
1025 t0.fNanoSec -= t1.fNanoSec;
1026 t0.fTime -= t1.fTime;
1027
1028 if ((Long_t)t0.fTime<-(Long_t)kHour*11)
1029 {
1030 t0.fTime += kDay;
1031 t0.fMjd--;
1032 }
1033
1034 t0.fMjd -= t1.fMjd;
1035
1036 return t0;
1037}
1038
1039void MTime::operator-=(const MTime &t)
1040{
1041 *this = *this-t;
1042}
1043
1044MTime MTime::operator+(const MTime &t1)
1045{
1046 MTime t0 = *this;
1047
1048 t0.fNanoSec += t1.fNanoSec;
1049
1050 if (t0.fNanoSec>999999)
1051 {
1052 t0.fNanoSec -= 1000000;
1053 t0.fTime += kDay;
1054 }
1055
1056 t0.fTime += t1.fTime;
1057
1058 if ((Long_t)t0.fTime>=(Long_t)kHour*13)
1059 {
1060 t0.fTime -= kDay;
1061 t0.fMjd++;
1062 }
1063
1064 t0.fMjd += t1.fMjd;
1065
1066 return t0;
1067}
1068
1069void MTime::operator+=(const MTime &t)
1070{
1071 *this = *this+t;
1072}
1073*/
1074
1075void MTime::SetMean(const MTime &t0, const MTime &t1)
1076{
1077 // This could be an operator+
1078 *this = t0;
1079
1080 fNanoSec += t1.fNanoSec;
1081
1082 if (fNanoSec>999999)
1083 {
1084 fNanoSec -= 1000000;
1085 fTime += kDay;
1086 }
1087
1088 fTime += t1.fTime;
1089
1090 if ((Long_t)fTime>=(Long_t)kHour*13)
1091 {
1092 fTime -= kDay;
1093 fMjd++;
1094 }
1095
1096 fMjd += t1.fMjd;
1097
1098 // This could be an operator/
1099 if ((Long_t)fTime<0)
1100 {
1101 fTime += kDay;
1102 fMjd--;
1103 }
1104
1105 Int_t reminder = fMjd%2;
1106 fMjd /= 2;
1107
1108 fTime += reminder*kDay;
1109 reminder = (Long_t)fTime%2;
1110 fTime /= 2;
1111
1112 fNanoSec += reminder*1000000;
1113 fNanoSec /= 2;
1114
1115 fTime += 11*kHour;
1116 fMjd += (Long_t)fTime/kDay;
1117 fTime = (Long_t)fTime%kDay;
1118 fTime -= 11*kHour;
1119}
1120
1121void MTime::SetMean(Double_t t0, Double_t t1)
1122{
1123 const Double_t mean = (t0+t1)*(0.5/kDaySec);
1124 SetMjd(mean);
1125}
1126
1127void MTime::AsciiRead(istream &fin)
1128{
1129 fin >> *this;
1130}
1131
1132Bool_t MTime::AsciiWrite(ostream &out) const
1133{
1134 out << *this;
1135 return out;
1136}
1137
1138// --------------------------------------------------------------------------
1139//
1140// Calculate the day of easter for the given year.
1141// MTime() is returned if this was not possible.
1142//
1143// In case of the default argument or the year less than zero
1144// the date of eastern of the current year (the year corresponding to
1145// MTime(-1)) is returned.
1146//
1147// for more information see: MAstro::GetDayOfEaster()
1148//
1149MTime MTime::GetEaster(Short_t year)
1150{
1151 if (year<0)
1152 year = MTime(-1).Year();
1153
1154 const Int_t day = MAstro::GetEasterOffset(year);
1155 if (day<0)
1156 return MTime();
1157
1158 MTime t;
1159 t.Set(year, 3, 1);
1160 t.SetMjd(t.GetMjd() + day);
1161
1162 return t;
1163}
Note: See TracBrowser for help on using the repository browser.