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

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