source: trunk/Mars/mbase/MTime.cc@ 13831

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