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

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