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

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