]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliTimestamp.cxx
slewing correction data for data dir
[u/mrichter/AliRoot.git] / RALICE / AliTimestamp.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliTimestamp
20 // Handling of timestamps for (astro)particle physics reserach.
21 //
22 // This class is derived from TTimeStamp and provides additional
23 // facilities (e.g. Julian date) which are commonly used in the
24 // field of (astro)particle physics.
25 //
26 // The Julian Date (JD) indicates the number of days since noon (UT) on
27 // 01 jan -4712 (i.e. noon 01 jan 4713 BC), being day 0 of the Julian calendar.
28 //
29 // The Modified Julian Date (MJD) indicates the number of days since midnight
30 // (UT) on 17-nov-1858, which corresponds to 2400000.5 days after day 0 of the
31 // Julian calendar.
32 //
33 // The Truncated Julian Date (TJD) corresponds to 2440000.5 days after day 0
34 // of the Julian calendar and consequently TJD=MJD-40000.
35 // This TJD date indication was used by the Vela and Batse missions in
36 // view of Gamma Ray Burst investigations.
37 //
38 // The Julian Epoch (JE) indicates the fractional elapsed Julian year count
39 // since the start of the Gregorian year count.
40 // A Julian year is defined to be 365.25 days and starts at 01-jan 12:00:00 UT.
41 // As such, the integer part of JE corresponds to the usual Gregorian year count,
42 // apart from 01-jan before 12:00:00 UT.
43 // So, 01-jan-1965 12:00:00 UT corresponds to JE=1965.0
44 //
45 // The Besselian Epoch (BE) indicates the fractional elapsed Besselian year count
46 // since the start of the Gregorian year count.
47 // A Besselian (or tropical) year is defined to be 365.242198781 days.
48 //
49 // The Besselian and Julian epochs are used in astronomical catalogs
50 // to denote values of time varying observables like e.g. right ascension.
51 //
52 // Because of the fact that the Julian date indicators are all w.r.t. UT
53 // they provide an absolute timescale irrespective of timezone or daylight
54 // saving time (DST).
55 //
56 // In view of astronomical observations and positioning it is convenient
57 // to have also a UT equivalent related to stellar meridian transitions.
58 // This is achieved by the Greenwich Sidereal Time (GST).
59 // The GST is defined as the right ascension of the objects passing
60 // the Greenwich meridian at 00:00:00 UT.
61 // Due to the rotation of the Earth around the Sun, a sidereal day
62 // lasts 86164.09 seconds (23h 56m 04.09s) compared to the mean solar
63 // day of 86400 seconds (24h).
64 // Furthermore, precession of the earth's spin axis results in the fact
65 // that the zero point of right ascension (vernal equinox) gradually 
66 // moves along the celestial equator.
67 // In addition, tidal friction and ocean and atmospheric effects will
68 // induce seasonal variations in the earth's spin rate and polar motion
69 // of the earth's spin axis.
70 // To obtain a sidereal time measure, the above efects are taken
71 // into account via corrections in the UT to GST conversion.
72 //
73 // This AliTimestamp facility allows for picosecond precision, in view
74 // of time of flight analyses for particle physics experiments.
75 // For normal date/time indication the standard nanosecond precision
76 // will in general be sufficient.
77 // Note that when the fractional JD, MJD and TJD counts are used instead
78 // of the integer (days,sec,ns) specification, the nanosecond precision
79 // may be lost due to computer accuracy w.r.t. floating point operations.
80 //
81 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
82 // which corresponds to JD=2440587.5 or the start of MJD=40587 or TJD=587.
83 // Using the corresponding MJD of this EPOCH allows construction of
84 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input (M/T)JD and time.
85 // Obviously this TTimeStamp implementation would prevent usage of values
86 // smaller than JD=2440587.5 or MJD=40587 or TJD=587.
87 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
88 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
89 // However, this AliTimestamp facility provides support for the full range
90 // of (M/T)JD values, but the setting of the corresponding TTimeStamp parameters
91 // is restricted to the values allowed by the TTimeStamp implementation.
92 // For these earlier/later (M/T)JD values, the standard TTimeStamp parameters will
93 // be set corresponding to the start of the TTimeStamp EPOCH.
94 // This implies that for these earlier/later (M/T)JD values the TTimeStamp parameters
95 // do not match the Julian parameters of AliTimestamp.
96 // As such the standard TTimeStamp parameters do not appear on the print output
97 // when invoking the Date() memberfunction for these earlier/later (M/T)JD values.  
98 //
99 // Examples :
100 // ==========
101 //
102 // Note : All TTimeStamp functionality is available as well.
103 //
104 // AliTimestamp t;
105 //
106 // t.Date();
107 // 
108 // // Retrieve Julian Date
109 // Int_t jd,jsec,jns;
110 // t.GetJD(jd,jsec,jns);
111 //
112 // // Retrieve fractional Truncated Julian Date
113 // Double_t tjd=t.GetTJD();
114 //
115 // // Retrieve fractional Julian Epoch
116 // Double_t je=t.GetJE();
117 //
118 // // Set to a specific Modified Julian Date
119 // Int_t mjd=50537;
120 // Int_t mjsec=1528;
121 // Int_t mjns=185643;
122 // t.SetMJD(mjd,mjsec,mjns);
123 //
124 // t.Date();
125 //
126 // // Time intervals for e.g. trigger or TOF analysis
127 // AliEvent evt;
128 // AliTrack* tx=evt.GetTrack(5);
129 // AliTimestamp* timex=tx->GetTimestamp();
130 // Double_t dt=evt.GetDifference(timex,"ps");
131 // AliTimestamp trig((AliTimestamp)evt);
132 // trig.Add(0,0,2,173);
133 // AliSignal* sx=evt.GetHit(23);
134 // AliTimestamp* timex=sx->GetTimestamp();
135 // Double_t dt=trig.GetDifference(timex,"ps");
136 // Int_t d,s,ns,ps;
137 // trig.GetDifference(timex,d,s,ns,ps);
138 //
139 // // Some practical conversion facilities
140 // // Note : They don't influence the actual date/time settings
141 // //        and as such can also be invoked as AliTimestamp::Convert(...) etc...
142 // Int_t y=1921;
143 // Int_t m=7;
144 // Int_t d=21;
145 // Int_t hh=15;
146 // Int_t mm=23;
147 // Int_t ss=47;
148 // Int_t ns=811743;
149 // Double_t jdate=t.GetJD(y,m,d,hh,mm,ss,ns);
150 //
151 // Int_t days,secs,nsecs;
152 // Double_t date=421.1949327;
153 // t.Convert(date,days,secs,nsecs);
154 //
155 // days=875;
156 // secs=23;
157 // nsecs=9118483;
158 // date=t.Convert(days,secs,nsecs);
159 //
160 // Double_t mjdate=40563.823744;
161 // Double_t epoch=t.GetJE(mjdate,"mjd");
162 //
163 //--- Author: Nick van Eijndhoven 28-jan-2005 Utrecht University.
164 //- Modified: NvE $Date$ Utrecht University.
165 ///////////////////////////////////////////////////////////////////////////
166
167 #include "AliTimestamp.h"
168 #include "Riostream.h"
169
170 ClassImp(AliTimestamp) // Class implementation to enable ROOT I/O
171  
172 AliTimestamp::AliTimestamp() : TTimeStamp()
173 {
174 // Default constructor
175 // Creation of an AliTimestamp object and initialisation of parameters.
176 // All attributes are initialised to the current date/time as specified
177 // in the docs of TTimeStamp.
178
179  FillJulian();
180  fJps=0;
181 }
182 ///////////////////////////////////////////////////////////////////////////
183 AliTimestamp::AliTimestamp(TTimeStamp& t) : TTimeStamp(t)
184 {
185 // Creation of an AliTimestamp object and initialisation of parameters.
186 // All attributes are initialised to the values of the input TTimeStamp.
187
188  FillJulian();
189  fJps=0;
190 }
191 ///////////////////////////////////////////////////////////////////////////
192 AliTimestamp::~AliTimestamp()
193 {
194 // Destructor to delete dynamically allocated memory.
195 }
196 ///////////////////////////////////////////////////////////////////////////
197 AliTimestamp::AliTimestamp(const AliTimestamp& t) : TTimeStamp(t)
198 {
199 // Copy constructor
200
201  fMJD=t.fMJD;
202  fJsec=t.fJsec;
203  fJns=t.fJns;
204  fJps=t.fJps;
205  fCalcs=t.fCalcs;
206  fCalcns=t.fCalcns;
207 }
208 ///////////////////////////////////////////////////////////////////////////
209 void AliTimestamp::Date(Int_t mode,Double_t offset)
210 {
211 // Print date/time info.
212 //
213 // mode = 1 ==> Only the UT yy-mm-dd hh:mm:ss:ns:ps and GST info is printed
214 //        2 ==> Only the Julian parameter info is printed
215 //        3 ==> Both the UT, GST and Julian parameter info is printed
216 //
217 // offset : Local time offset from UT (and also GST) in fractional hours.
218 //
219 // When an offset value is specified, the corresponding local times
220 // LT and LST are printed as well.
221 //
222 // The default values are mode=3 and offset=0.
223 //
224 // Note : In case the (M/T)JD falls outside the TTimeStamp range,
225 //        the yy-mm-dd info will be omitted.
226
227  Int_t mjd,mjsec,mjns,mjps;
228  GetMJD(mjd,mjsec,mjns);
229  mjps=GetPs();
230
231  TString month[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
232  TString day[7]={"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
233  UInt_t y,m,d,wd;
234  Int_t hh,mm,ss,ns,ps;
235  
236  if (mode==1 || mode==3)
237  {
238   if (mjd>=40587 && (mjd<65442 || (mjd==65442 && mjsec<8047)))
239   {
240    GetDate(kTRUE,0,&y,&m,&d);
241    wd=GetDayOfWeek(kTRUE,0);
242    cout << " " << day[wd-1].Data() << ", " << setfill('0') << setw(2) << d << " "
243         << setfill(' ') << month[m-1].Data() << " " << y << " ";
244   }
245   else
246   {
247    cout << " Time ";
248   }
249   GetUT(hh,mm,ss,ns,ps);
250   cout << setfill('0') << setw(2) << hh << ":"
251        << setw(2) << mm << ":" << setw(2) << ss << "."
252        << setw(9) << ns << setw(3) << ps << " (UT)  ";
253   GetGST(hh,mm,ss,ns,ps);
254   cout << setfill('0') << setw(2) << hh << ":"
255        << setw(2) << mm << ":" << setw(2) << ss << "."
256        << setw(9) << ns << setw(3) << ps << " (GST)"<< endl;
257   if (offset)
258   {
259    // Determine the new date by including the offset
260    AliTimestamp t2(*this);
261    t2.Add(offset);
262    Int_t mjd2,mjsec2,mjns2;
263    t2.GetMJD(mjd2,mjsec2,mjns2);
264    if (mjd2>=40587 && (mjd2<65442 || (mjd2==65442 && mjsec2<8047)))
265    {
266     t2.GetDate(kTRUE,0,&y,&m,&d);
267     wd=t2.GetDayOfWeek(kTRUE,0);
268     cout << " " << day[wd-1].Data() << ", " << setfill('0') << setw(2) << d << " "
269          << setfill(' ') << month[m-1].Data() << " " << y << " ";
270    }
271    else
272    {
273     cout << " Time ";
274    }
275    // Determine the local time by including the offset w.r.t. the original timestamp
276    Double_t h;
277    h=GetUT(); 
278    h+=offset;
279    while (h<0)
280    {
281     h+=24.;
282    }
283    while (h>24)
284    {
285     h-=24.;
286    }
287    Convert(h,hh,mm,ss,ns,ps);
288    cout << setfill('0') << setw(2) << hh << ":"
289         << setw(2) << mm << ":" << setw(2) << ss << "."
290         << setw(9) << ns << setw(3) << ps << " (LT)  ";
291    h=GetGST(); 
292    h+=offset;
293    while (h<0)
294    {
295     h+=24.;
296    }
297    while (h>24)
298    {
299     h-=24.;
300    }
301    Convert(h,hh,mm,ss,ns,ps);
302    cout << setfill('0') << setw(2) << hh << ":"
303         << setw(2) << mm << ":" << setw(2) << ss << "."
304         << setw(9) << ns << setw(3) << ps << " (LST)"<< endl;
305   }
306  }
307  if (mode==2 || mode==3)
308  {
309   Int_t jd,jsec,jns;
310   GetJD(jd,jsec,jns);
311   Int_t tjd,tjsec,tjns;
312   GetTJD(tjd,tjsec,tjns);
313   cout << " Julian Epoch : " << setprecision(25) << GetJE()
314        << " Besselian Epoch : " << setprecision(25) << GetBE() << endl;
315   cout << " JD : " << jd << " sec : " << jsec << " ns : " << jns << " ps : " << fJps
316        << " Fractional : " << setprecision(25) << GetJD() << endl;
317   cout << " MJD : " << mjd << "  sec : " << mjsec << " ns : " << mjns << " ps : " << fJps
318        << " Fractional : " << setprecision(25) << GetMJD() << endl;
319   cout << " TJD : " << tjd << "  sec : " << tjsec << " ns : " << tjns << " ps : " << fJps
320        << " Fractional : " << setprecision(25) << GetTJD() << endl;
321  }
322 }
323 ///////////////////////////////////////////////////////////////////////////
324 Double_t AliTimestamp::GetJD(Int_t y,Int_t m,Int_t d,Int_t hh,Int_t mm,Int_t ss,Int_t ns) const
325 {
326 // Provide the (fractional) Julian Date (JD) corresponding to the UT date
327 // and time in the Gregorian calendar as specified by the input arguments.
328 //
329 // The input arguments represent the following :
330 // y  : year in UT (e.g. 1952, 2003 etc...)
331 // m  : month in UT (1=jan  2=feb etc...)
332 // d  : day in UT (1-31)
333 // hh : elapsed hours in UT (0-23) 
334 // mm : elapsed minutes in UT (0-59)
335 // ss : elapsed seconds in UT (0-59)
336 // ns : remaining fractional elapsed second of UT in nanosecond
337 //
338 // This algorithm is valid for all AD dates in the Gregorian calendar
339 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
340 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
341 //
342 // In case of invalid input, a value of -1 is returned.
343 //
344 // Note :
345 // ------
346 // This memberfunction only provides the JD corresponding to the
347 // UT input arguments. It does NOT set the corresponding Julian parameters
348 // for the current AliTimestamp instance.
349 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
350 // To set the Julian parameters for the current AliTimestamp instance,
351 // please use the corresponding SET() memberfunctions of either AliTimestamp
352 // or TTimeStamp. 
353
354  if (y<0 || m<1 || m>12 || d<1 || d>31) return -1;
355  if (hh<0 || hh>23 || mm<0 || mm>59 || ss<0 || ss>59 || ns<0 || ns>1e9) return -1;
356
357  // The UT daytime in fractional hours
358  Double_t ut=double(hh)+double(mm)/60.+(double(ss)+double(ns)*1.e-9)/3600.;
359
360  Double_t JD=0;
361  
362  JD=367*y-int(7*(y+int((m+9)/12))/4)
363     -int(3*(int((y+(m-9)/7)/100)+1)/4)
364     +int(275*m/9)+d+1721028.5+ut/24.;
365
366  return JD;
367 }
368 ///////////////////////////////////////////////////////////////////////////
369 Double_t AliTimestamp::GetMJD(Int_t y,Int_t m,Int_t d,Int_t hh,Int_t mm,Int_t ss,Int_t ns) const
370 {
371 // Provide the (fractional) Modified Julian Date corresponding to the UT
372 // date and time in the Gregorian calendar as specified by the input arguments.
373 //
374 // The input arguments represent the following :
375 // y  : year in UT (e.g. 1952, 2003 etc...)
376 // m  : month in UT (1=jan  2=feb etc...)
377 // d  : day in UT (1-31)
378 // hh : elapsed hours in UT (0-23) 
379 // mm : elapsed minutes in UT (0-59)
380 // ss : elapsed seconds in UT (0-59)
381 // ns : remaining fractional elapsed second of UT in nanosecond
382 //
383 // This algorithm is valid for all AD dates in the Gregorian calendar
384 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
385 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
386 //
387 // In case of invalid input, a value of -1 is returned.
388 //
389 // Note :
390 // ------
391 // This memberfunction only provides the MJD corresponding to the
392 // UT input arguments. It does NOT set the corresponding Julian parameters
393 // for the current AliTimestamp instance.
394 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
395 // To set the Julian parameters for the current AliTimestamp instance,
396 // please use the corresponding SET() memberfunctions of either AliTimestamp
397 // or TTimeStamp.
398
399  Double_t JD=GetJD(y,m,d,hh,mm,ss,ns);
400
401  if (JD<0) return JD;
402
403  Double_t MJD=JD-2400000.5;
404
405  return MJD; 
406
407 ///////////////////////////////////////////////////////////////////////////
408 Double_t AliTimestamp::GetTJD(Int_t y,Int_t m,Int_t d,Int_t hh,Int_t mm,Int_t ss,Int_t ns) const
409 {
410 // Provide the (fractional) Truncated Julian Date corresponding to the UT
411 // date and time in the Gregorian calendar as specified by the input arguments.
412 //
413 // The input arguments represent the following :
414 // y  : year in UT (e.g. 1952, 2003 etc...)
415 // m  : month in UT (1=jan  2=feb etc...)
416 // d  : day in UT (1-31)
417 // hh : elapsed hours in UT (0-23) 
418 // mm : elapsed minutes in UT (0-59)
419 // ss : elapsed seconds in UT (0-59)
420 // ns : remaining fractional elapsed second of UT in nanosecond
421 //
422 // This algorithm is valid for all AD dates in the Gregorian calendar
423 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
424 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
425 //
426 // In case of invalid input, a value of -1 is returned.
427 //
428 // Note :
429 // ------
430 // This memberfunction only provides the TJD corresponding to the
431 // UT input arguments. It does NOT set the corresponding Julian parameters
432 // for the current AliTimestamp instance.
433 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
434 // To set the Julian parameters for the current AliTimestamp instance,
435 // please use the corresponding SET() memberfunctions of either AliTimestamp
436 // or TTimeStamp.
437
438  Double_t JD=GetJD(y,m,d,hh,mm,ss,ns);
439
440  if (JD<0) return JD;
441
442  Double_t TJD=JD-2440000.5;
443
444  return TJD; 
445
446 ///////////////////////////////////////////////////////////////////////////
447 Double_t AliTimestamp::GetJE(Double_t date,TString mode) const
448 {
449 // Provide the Julian Epoch (JE) corresponding to the specified date.
450 // The argument "mode" indicates the type of the argument "date".
451 //
452 // Available modes are :
453 // mode = "jd"  ==> date represents the Julian Date
454 //      = "mjd" ==> date represents the Modified Julian Date
455 //      = "tjd" ==> date represents the Truncated Julian Date
456 //
457 // The default is mode="jd".
458 //
459 // In case of invalid input, a value of -99999 is returned.
460 //
461 // Note :
462 // ------
463 // This memberfunction only provides the JE corresponding to the
464 // input arguments. It does NOT set the corresponding Julian parameters
465 // for the current AliTimestamp instance.
466 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
467 // To set the Julian parameters for the current AliTimestamp instance,
468 // please use the corresponding SET() memberfunctions of either AliTimestamp
469 // or TTimeStamp.
470
471  if ((mode != "jd") && (mode != "mjd") && (mode != "tjd")) return -99999;
472
473  Double_t jd=date;
474  if (mode=="mjd") jd=date+2400000.5;
475  if (mode=="tjd") jd=date+2440000.5;
476
477  Double_t je=2000.+(jd-2451545.)/365.25;
478
479  return je;
480 }
481 ///////////////////////////////////////////////////////////////////////////
482 Double_t AliTimestamp::GetBE(Double_t date,TString mode) const
483 {
484 // Provide the Besselian Epoch (JE) corresponding to the specified date.
485 // The argument "mode" indicates the type of the argument "date".
486 //
487 // Available modes are :
488 // mode = "jd"  ==> date represents the Julian Date
489 //      = "mjd" ==> date represents the Modified Julian Date
490 //      = "tjd" ==> date represents the Truncated Julian Date
491 //
492 // The default is mode="jd".
493 //
494 // In case of invalid input, a value of -99999 is returned.
495 //
496 // Note :
497 // ------
498 // This memberfunction only provides the BE corresponding to the
499 // input arguments. It does NOT set the corresponding Julian parameters
500 // for the current AliTimestamp instance.
501 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
502 // To set the Julian parameters for the current AliTimestamp instance,
503 // please use the corresponding SET() memberfunctions of either AliTimestamp
504 // or TTimeStamp.
505
506  if ((mode != "jd") && (mode != "mjd") && (mode != "tjd")) return -99999;
507
508  Double_t jd=date;
509  if (mode=="mjd") jd=date+2400000.5;
510  if (mode=="tjd") jd=date+2440000.5;
511
512  Double_t be=1900.+(jd-2415020.31352)/365.242198781;
513
514  return be;
515 }
516 ///////////////////////////////////////////////////////////////////////////
517 void AliTimestamp::Convert(Double_t date,Int_t& days,Int_t& secs,Int_t& ns) const
518 {
519 // Convert date as fractional day count into integer days, secs and ns.
520 //
521 // Note : Due to computer accuracy the ns value may become inaccurate.
522 //
523 // The arguments represent the following :
524 // date : The input date as fractional day count
525 // days : Number of elapsed days
526 // secs : Remaining number of elapsed seconds
527 // ns   : Remaining fractional elapsed second in nanoseconds
528 //
529 // Note :
530 // ------
531 // This memberfunction only converts the input date into the corresponding
532 // integer parameters. It does NOT set the corresponding Julian parameters
533 // for the current AliTimestamp instance.
534 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
535 // To set the Julian parameters for the current AliTimestamp instance,
536 // please use the corresponding SET() memberfunctions of either AliTimestamp
537 // or TTimeStamp.
538  
539  days=int(date);
540  date=date-double(days);
541  Int_t daysecs=24*3600;
542  date=date*double(daysecs);
543  secs=int(date);
544  date=date-double(secs);
545  ns=int(date*1.e9);
546 }
547 ///////////////////////////////////////////////////////////////////////////
548 Double_t AliTimestamp::Convert(Int_t days,Int_t secs,Int_t ns) const
549 {
550 // Convert date in integer days, secs and ns into fractional day count. 
551 //
552 // Note : Due to computer accuracy the ns precision may be lost.
553 //
554 // The input arguments represent the following :
555 // days : Number of elapsed days
556 // secs : Remaining number of elapsed seconds
557 // ns   : Remaining fractional elapsed second in nanoseconds
558 //
559 // Note :
560 // ------
561 // This memberfunction only converts the input integer parameters into the
562 // corresponding fractional day count. It does NOT set the corresponding
563 // Julian parameters for the current AliTimestamp instance.
564 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
565 // To set the Julian parameters for the current AliTimestamp instance,
566 // please use the corresponding SET() memberfunctions of either AliTimestamp
567 // or TTimeStamp.
568
569  Double_t frac=double(secs)+double(ns)*1.e-9;
570  Int_t daysecs=24*3600;
571  frac=frac/double(daysecs);
572  Double_t date=double(days)+frac;
573  return date;
574 }
575 ///////////////////////////////////////////////////////////////////////////
576 void AliTimestamp::Convert(Double_t h,Int_t& hh,Int_t& mm,Int_t& ss,Int_t& ns,Int_t& ps) const
577 {
578 // Convert fractional hour count h into hh:mm:ss:ns:ps.
579 //
580 // Note : Due to computer accuracy the ps value may become inaccurate.
581 //
582 // Note :
583 // ------
584 // This memberfunction only converts the input "h" into the corresponding
585 // integer parameters. It does NOT set the corresponding Julian parameters
586 // for the current AliTimestamp instance.
587 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
588 // To set the Julian parameters for the current AliTimestamp instance,
589 // please use the corresponding SET() memberfunctions of either AliTimestamp
590 // or TTimeStamp.
591  
592  hh=int(h);
593  h=h-double(hh);
594  h=h*60.;
595  mm=int(h);
596  h=h-double(mm);
597  h=h*60.;
598  ss=int(h);
599  h=h-double(ss);
600  h=h*1.e9;
601  ns=int(h);
602  h=h-double(ns);
603  h=h*1000.;
604  ps=int(h);
605 }
606 ///////////////////////////////////////////////////////////////////////////
607 Double_t AliTimestamp::Convert(Int_t hh,Int_t mm,Int_t ss,Int_t ns,Int_t ps) const
608 {
609 // Convert hh:mm:ss:ns:ps into fractional hour count. 
610 //
611 // Note : Due to computer accuracy the ps precision may be lost.
612 //
613 // Note :
614 // ------
615 // This memberfunction only converts the input integer parameters into the
616 // corresponding fractional hour count. It does NOT set the corresponding
617 // Julian parameters for the current AliTimestamp instance.
618 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
619 // To set the Julian parameters for the current AliTimestamp instance,
620 // please use the corresponding SET() memberfunctions of either AliTimestamp
621 // or TTimeStamp.
622
623  Double_t h=hh;
624  h+=double(mm)/60.+(double(ss)+double(ns)*1.e-9+double(ps)*1.e-12)/3600.;
625
626  return h;
627 }
628 ///////////////////////////////////////////////////////////////////////////
629 void AliTimestamp::FillJulian()
630 {
631 // Calculation and setting of the Julian date/time parameters corresponding
632 // to the current TTimeStamp date/time parameters.
633
634  UInt_t y,m,d,hh,mm,ss;
635
636  GetDate(kTRUE,0,&y,&m,&d);
637  GetTime(kTRUE,0,&hh,&mm,&ss);
638  Int_t ns=GetNanoSec();
639
640  Double_t mjd=GetMJD(y,m,d,hh,mm,ss,ns);
641
642  fMJD=int(mjd);
643  fJsec=GetSec()%(24*3600); // Daytime in elapsed seconds
644  fJns=ns;                  // Remaining fractional elapsed second in nanoseconds
645
646  // Store the TTimeStamp seconds and nanoseconds values
647  // for which this Julian calculation was performed.
648  fCalcs=GetSec();
649  fCalcns=GetNanoSec();
650 }
651 ///////////////////////////////////////////////////////////////////////////
652 void AliTimestamp::GetMJD(Int_t& mjd,Int_t& sec,Int_t& ns)
653 {
654 // Provide the Modified Julian Date (MJD) and time corresponding to the
655 // currently stored AliTimestamp date/time parameters.
656 //
657 // The returned arguments represent the following :
658 // mjd : The modified Julian date.
659 // sec : The number of seconds elapsed within the MJD.
660 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
661
662  if (fCalcs != GetSec() || fCalcns != GetNanoSec()) FillJulian();
663
664  mjd=fMJD;
665  sec=fJsec;
666  ns=fJns;
667 }
668 ///////////////////////////////////////////////////////////////////////////
669 Double_t AliTimestamp::GetMJD()
670 {
671 // Provide the (fractional) Modified Julian Date (MJD) corresponding to the
672 // currently stored AliTimestamp date/time parameters.
673 //
674 // Due to computer accuracy the ns precision may be lost.
675 // It is advised to use the (mjd,sec,ns) getter instead.
676
677  Int_t mjd=0;
678  Int_t sec=0;
679  Int_t ns=0;
680  GetMJD(mjd,sec,ns);
681
682  Double_t date=Convert(mjd,sec,ns);
683
684  return date;
685 }
686 ///////////////////////////////////////////////////////////////////////////
687 void AliTimestamp::GetTJD(Int_t& tjd,Int_t& sec, Int_t& ns)
688 {
689 // Provide the Truncated Julian Date (TJD) and time corresponding to the
690 // currently stored AliTimestamp date/time parameters.
691 //
692 // The returned arguments represent the following :
693 // tjd : The modified Julian date.
694 // sec : The number of seconds elapsed within the MJD.
695 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
696
697  Int_t mjd=0;
698  GetMJD(mjd,sec,ns);
699
700  tjd=mjd-40000;
701 }
702 ///////////////////////////////////////////////////////////////////////////
703 Double_t AliTimestamp::GetTJD()
704 {
705 // Provide the (fractional) Truncated Julian Date (TJD) corresponding to the
706 // currently stored AliTimestamp date/time parameters.
707 //
708 // Due to computer accuracy the ns precision may be lost.
709 // It is advised to use the (mjd,sec,ns) getter instead.
710
711  Int_t tjd=0;
712  Int_t sec=0;
713  Int_t ns=0;
714  GetTJD(tjd,sec,ns);
715
716  Double_t date=Convert(tjd,sec,ns);
717
718  return date;
719 }
720 ///////////////////////////////////////////////////////////////////////////
721 void AliTimestamp::GetJD(Int_t& jd,Int_t& sec, Int_t& ns)
722 {
723 // Provide the Julian Date (JD) and time corresponding to the currently
724 // stored AliTimestamp date/time parameters.
725 //
726 // The returned arguments represent the following :
727 // jd  : The Julian date.
728 // sec : The number of seconds elapsed within the JD.
729 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
730
731  Int_t mjd=0;
732  GetMJD(mjd,sec,ns);
733
734  jd=mjd+2400000;
735  sec+=12*3600;
736  if (sec >= 24*3600)
737  {
738   sec-=24*3600;
739   jd+=1;
740  }
741 }
742 ///////////////////////////////////////////////////////////////////////////
743 Double_t AliTimestamp::GetJD()
744 {
745 // Provide the (fractional) Julian Date (JD) corresponding to the currently
746 // stored AliTimestamp date/time parameters.
747 //
748 // Due to computer accuracy the ns precision may be lost.
749 // It is advised to use the (jd,sec,ns) getter instead.
750
751  Int_t jd=0;
752  Int_t sec=0;
753  Int_t ns=0;
754  GetJD(jd,sec,ns);
755
756  Double_t date=Convert(jd,sec,ns);
757
758  return date;
759 }
760 ///////////////////////////////////////////////////////////////////////////
761 Double_t AliTimestamp::GetJE()
762 {
763 // Provide the Julian Epoch (JE) corresponding to the currently stored
764 // AliTimestamp date/time parameters.
765
766  Double_t jd=GetJD();
767  Double_t je=GetJE(jd);
768  return je;
769 }
770 ///////////////////////////////////////////////////////////////////////////
771 Double_t AliTimestamp::GetBE()
772 {
773 // Provide the Besselian Epoch (BE) corresponding to the currently stored
774 // AliTimestamp date/time parameters.
775
776  Double_t jd=GetJD();
777  Double_t be=GetBE(jd);
778  return be;
779 }
780 ///////////////////////////////////////////////////////////////////////////
781 void AliTimestamp::SetMJD(Int_t mjd,Int_t sec,Int_t ns,Int_t ps)
782 {
783 // Set the Modified Julian Date (MJD) and time and update the TTimeStamp
784 // parameters accordingly (if possible).
785 //
786 // Note :
787 // ------
788 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
789 // which corresponds to the start of MJD=40587.
790 // Using the corresponding MJD of this EPOCH allows construction of
791 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
792 // Obviously this TTimeStamp implementation would prevent usage of MJD values
793 // smaller than 40587.
794 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
795 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
796 // However, this AliTimestamp facility provides support for the full range
797 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
798 // is restricted to the values allowed by the TTimeStamp implementation.
799 // For these earlier/later MJD values, the standard TTimeStamp parameters will
800 // be set corresponding to the start of the TTimeStamp EPOCH.  
801 // This implies that for these earlier/later MJD values the TTimeStamp parameters
802 // do not match the Julian parameters of AliTimestamp.  
803 //
804 // The input arguments represent the following :
805 // mjd : The modified Julian date.
806 // sec : The number of seconds elapsed within the MJD.
807 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
808 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the MJD.
809 //
810 // Note : ps=0 is the default value.
811
812  if (sec<0 || sec>=24*3600 || ns<0 || ns>=1e9 || ps<0 || ps>=1000)
813  {
814   cout << " *AliTimestamp::SetMJD* Invalid input."
815        << " sec : " << sec << " ns : " << ns << endl; 
816   return;
817  }
818
819  fMJD=mjd;
820  fJsec=sec;
821  fJns=ns;
822  fJps=ps;
823
824  Int_t epoch=40587; // MJD of the start of the epoch
825  Int_t limit=65442; // MJD of the latest possible TTimeStamp date/time
826  
827  Int_t date,time;
828  if (mjd<epoch || (mjd>=limit && sec>=8047))
829  {
830   Set(0,kFALSE,0,kFALSE);
831   date=GetDate();
832   time=GetTime();
833   Set(date,time,0,kTRUE,0);
834  }
835  else
836  {
837   // The elapsed time since start of EPOCH
838   Int_t days=mjd-epoch;
839   UInt_t secs=days*24*3600;
840   secs+=sec;
841   Set(secs,kFALSE,0,kFALSE);
842   date=GetDate();
843   time=GetTime();
844   Set(date,time,ns,kTRUE,0);
845  }
846
847  // Denote that the Julian and TTimeStamp parameters are synchronised,
848  // even in the case the MJD falls outside the TTimeStamp validity range.
849  // The latter still allows retrieval of Julian parameters for these
850  // earlier times.
851  fCalcs=GetSec();
852  fCalcns=GetNanoSec();
853 }
854 ///////////////////////////////////////////////////////////////////////////
855 void AliTimestamp::SetMJD(Double_t mjd)
856 {
857 // Set the Modified Julian Date (MJD) and time and update the TTimeStamp
858 // parameters accordingly (if possible).
859 //
860 // Note :
861 // ------
862 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
863 // which corresponds to the start of MJD=40587.
864 // Using the corresponding MJD of this EPOCH allows construction of
865 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
866 // Obviously this TTimeStamp implementation would prevent usage of MJD values
867 // smaller than 40587.
868 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
869 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
870 // However, this AliTimestamp facility provides support for the full range
871 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
872 // is restricted to the values allowed by the TTimeStamp implementation.
873 // For these earlier/later MJD values, the standard TTimeStamp parameters will
874 // be set corresponding to the start of the TTimeStamp EPOCH.  
875 // This implies that for these earlier/later MJD values the TTimeStamp parameters
876 // do not match the Julian parameters of AliTimestamp.  
877 //
878 // Due to computer accuracy the ns precision may be lost.
879 // It is advised to use the (mjd,sec,ns) setting instead.
880 //
881 // The input argument represents the following :
882 // mjd : The modified Julian date as fractional day count.
883
884  Int_t days=0;
885  Int_t secs=0;
886  Int_t ns=0;
887  Convert(mjd,days,secs,ns);
888  SetMJD(days,secs,ns);
889 }
890 ///////////////////////////////////////////////////////////////////////////
891 void AliTimestamp::SetJD(Int_t jd,Int_t sec,Int_t ns,Int_t ps)
892 {
893 // Set the Julian Date (JD) and time and update the TTimeStamp
894 // parameters accordingly (if possible).
895 //
896 // Note :
897 // ------
898 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
899 // which corresponds to JD=2440587.5 or the start of MJD=40587.
900 // Using the corresponding MJD of this EPOCH allows construction of
901 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
902 // Obviously this TTimeStamp implementation would prevent usage of values
903 // smaller than JD=2440587.5.
904 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
905 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
906 // However, this AliTimestamp facility provides support for the full range
907 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
908 // is restricted to the values allowed by the TTimeStamp implementation.
909 // For these earlier/later JD values, the standard TTimeStamp parameters will
910 // be set corresponding to the start of the TTimeStamp EPOCH.  
911 // This implies that for these earlier/later (M)JD values the TTimeStamp parameters
912 // do not match the Julian parameters of AliTimestamp.  
913 //
914 // The input arguments represent the following :
915 // jd  : The Julian date.
916 // sec : The number of seconds elapsed within the JD.
917 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
918 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the JD.
919 //
920 // Note : ps=0 is the default value.
921
922  Int_t mjd=jd-2400000;
923  sec-=12*3600;
924  if (sec<0)
925  {
926   sec+=24*3600;
927   mjd-=1;
928  }
929
930  SetMJD(mjd,sec,ns,ps);
931 }
932 ///////////////////////////////////////////////////////////////////////////
933 void AliTimestamp::SetJD(Double_t jd)
934 {
935 // Set the Julian Date (JD) and time and update the TTimeStamp
936 // parameters accordingly (if possible).
937 //
938 // Note :
939 // ------
940 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
941 // which corresponds to JD=2440587.5 or the start of MJD=40587.
942 // Using the corresponding MJD of this EPOCH allows construction of
943 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
944 // Obviously this TTimeStamp implementation would prevent usage of values
945 // smaller than JD=2440587.5.
946 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
947 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
948 // However, this AliTimestamp facility provides support for the full range
949 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
950 // is restricted to the values allowed by the TTimeStamp implementation.
951 // For these earlier/later JD values, the standard TTimeStamp parameters will
952 // be set corresponding to the start of the TTimeStamp EPOCH.  
953 // This implies that for these earlier/later (M)JD values the TTimeStamp parameters
954 // do not match the Julian parameters of AliTimestamp.  
955 //
956 // Due to computer accuracy the ns precision may be lost.
957 // It is advised to use the (jd,sec,ns) setting instead.
958 //
959 // The input argument represents the following :
960 // jd : The Julian date as fractional day count.
961
962  Int_t days=0;
963  Int_t secs=0;
964  Int_t ns=0;
965  Convert(jd,days,secs,ns);
966
967  SetJD(days,secs,ns);
968 }
969 ///////////////////////////////////////////////////////////////////////////
970 void AliTimestamp::SetTJD(Int_t tjd,Int_t sec,Int_t ns,Int_t ps)
971 {
972 // Set the Truncated Julian Date (TJD) and time and update the TTimeStamp
973 // parameters accordingly (if possible).
974 //
975 // Note :
976 // ------
977 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
978 // which corresponds to JD=2440587.5 or the start of TJD=587.
979 // Using the corresponding MJD of this EPOCH allows construction of
980 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
981 // Obviously this TTimeStamp implementation would prevent usage of values
982 // smaller than TJD=587.
983 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
984 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
985 // However, this AliTimestamp facility provides support for the full range
986 // of (T)JD values, but the setting of the corresponding TTimeStamp parameters
987 // is restricted to the values allowed by the TTimeStamp implementation.
988 // For these earlier/later JD values, the standard TTimeStamp parameters will
989 // be set corresponding to the start of the TTimeStamp EPOCH.  
990 // This implies that for these earlier/later (T)JD values the TTimeStamp parameters
991 // do not match the Julian parameters of AliTimestamp.  
992 //
993 // The input arguments represent the following :
994 // tjd : The Truncated Julian date.
995 // sec : The number of seconds elapsed within the JD.
996 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
997 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the JD.
998 //
999 // Note : ps=0 is the default value.
1000
1001  Int_t mjd=tjd+40000;
1002
1003  SetMJD(mjd,sec,ns,ps);
1004 }
1005 ///////////////////////////////////////////////////////////////////////////
1006 void AliTimestamp::SetTJD(Double_t tjd)
1007 {
1008 // Set the Truncated Julian Date (TJD) and time and update the TTimeStamp
1009 // parameters accordingly (if possible).
1010 //
1011 // Note :
1012 // ------
1013 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
1014 // which corresponds to JD=2440587.5 or the start of TJD=587.
1015 // Using the corresponding MJD of this EPOCH allows construction of
1016 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
1017 // Obviously this TTimeStamp implementation would prevent usage of values
1018 // smaller than TJD=587.
1019 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
1020 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
1021 // However, this AliTimestamp facility provides support for the full range
1022 // of (T)JD values, but the setting of the corresponding TTimeStamp parameters
1023 // is restricted to the values allowed by the TTimeStamp implementation.
1024 // For these earlier/later JD values, the standard TTimeStamp parameters will
1025 // be set corresponding to the start of the TTimeStamp EPOCH.  
1026 // This implies that for these earlier/later (T)JD values the TTimeStamp parameters
1027 // do not match the Julian parameters of AliTimestamp.  
1028 //
1029 // Due to computer accuracy the ns precision may be lost.
1030 // It is advised to use the (jd,sec,ns) setting instead.
1031 //
1032 // The input argument represents the following :
1033 // tjd : The Truncated Julian date as fractional day count.
1034
1035  Int_t days=0;
1036  Int_t secs=0;
1037  Int_t ns=0;
1038  Convert(tjd,days,secs,ns);
1039
1040  SetTJD(days,secs,ns);
1041 }
1042 ///////////////////////////////////////////////////////////////////////////
1043 void AliTimestamp::SetNs(Int_t ns)
1044 {
1045 // Set the remaining fractional number of seconds in nanosecond precision.
1046 // Notes :
1047 // -------
1048 // 1) The allowed range for the argument "ns" is [0,99999999].
1049 //    Outside that range no action is performed.
1050 // 2) The ns fraction can also be entered directly via SetMJD() etc...
1051 // 3) For additional accuracy see SetPs().
1052
1053  if (ns>=0 && ns<=99999999) fJns=ns; 
1054 }
1055 ///////////////////////////////////////////////////////////////////////////
1056 Int_t AliTimestamp::GetNs() const
1057 {
1058 // Provide the remaining fractional number of seconds in nanosecond precision.
1059 // This function allows trigger/timing analysis for (astro)particle physics
1060 // experiments.
1061 // Note : For additional accuracy see also GetPs().
1062
1063  return fJns; 
1064 }
1065 ///////////////////////////////////////////////////////////////////////////
1066 void AliTimestamp::SetPs(Int_t ps)
1067 {
1068 // Set the remaining fractional number of nanoseconds in picoseconds.
1069 // Notes :
1070 // -------
1071 // 1) The allowed range for the argument "ps" is [0,999].
1072 //    Outside that range no action is performed.
1073 // 2) The ps fraction can also be entered directly via SetMJD() etc...
1074
1075  if (ps>=0 && ps<=999) fJps=ps; 
1076 }
1077 ///////////////////////////////////////////////////////////////////////////
1078 Int_t AliTimestamp::GetPs() const
1079 {
1080 // Provide remaining fractional number of nanoseconds in picoseconds.
1081 // This function allows time of flight analysis for particle physics
1082 // experiments.
1083
1084  return fJps; 
1085 }
1086 ///////////////////////////////////////////////////////////////////////////
1087 void AliTimestamp::Add(Int_t d,Int_t s,Int_t ns,Int_t ps)
1088 {
1089 // Add (or subtract) a certain time difference to the current timestamp.
1090 // Subtraction can be achieved by entering negative values as input arguments.
1091 //
1092 // The time difference is entered via the following input arguments :
1093 //
1094 // d  : elapsed number of days
1095 // s  : (remaining) elapsed number of seconds
1096 // ns : (remaining) elapsed number of nanoseconds
1097 // ps : (remaining) elapsed number of picoseconds
1098 //
1099 // The specified d, s, ns and ps values will be used in an additive
1100 // way to determine the time difference.
1101 // So, specification of d=1, s=100, ns=0, ps=0 will result in the
1102 // same time difference addition as d=0, s=24*3600+100, ns=0, ps=0.
1103 // However, by making use of the latter the user should take care
1104 // of possible integer overflow problems in the input arguments,
1105 // which obviously will provide incorrect results. 
1106 //
1107 // Note : ps=0 is the default value.
1108
1109  Int_t days=0;
1110  Int_t secs=0;
1111  Int_t nsec=0;
1112  // Use Get functions to ensure updated Julian parameters. 
1113  GetMJD(days,secs,nsec);
1114  Int_t psec=GetPs();
1115
1116  psec+=ps%1000;
1117  nsec+=ps/1000;
1118  while (psec<0)
1119  {
1120   nsec-=1;
1121   psec+=1000;
1122  }
1123  while (psec>999)
1124  {
1125   nsec+=1;
1126   psec-=1000;
1127  }
1128
1129  nsec+=ns%1000000000;
1130  secs+=ns/1000000000;
1131  while (nsec<0)
1132  {
1133   secs-=1;
1134   nsec+=1000000000;
1135  }
1136  while (nsec>999999999)
1137  {
1138   secs+=1;
1139   nsec-=1000000000;
1140  }
1141
1142  secs+=s%(24*3600);
1143  days+=s/(24*3600);
1144  while (secs<0)
1145  {
1146   days-=1;
1147   secs+=24*3600;
1148  }
1149  while (secs>=24*3600)
1150  {
1151   days+=1;
1152   secs-=24*3600;
1153  }
1154
1155  days+=d;
1156
1157  SetMJD(days,secs,nsec,psec);
1158 }
1159 ///////////////////////////////////////////////////////////////////////////
1160 void AliTimestamp::Add(Double_t hours)
1161 {
1162 // Add (or subtract) a certain time difference to the current timestamp.
1163 // The time difference is specified as a (fractional) number of hours.
1164 // Subtraction can be achieved by entering a negative value as input argument.
1165
1166  Int_t d,s,ns,ps;
1167  Double_t h=fabs(hours);
1168  d=int(h/24.);
1169  h-=double(d)*24.;
1170  h*=3600.;
1171  s=int(h);
1172  h-=double(s);
1173  h*=1.e9;
1174  ns=int(h);
1175  h-=double(ns);
1176  ps=int(h*1000.);
1177  if (hours>0) Add(d,s,ns,ps);
1178  if (hours<0) Add(-d,-s,-ns,-ps);
1179 }
1180 ///////////////////////////////////////////////////////////////////////////
1181 Int_t AliTimestamp::GetDifference(AliTimestamp* t,Int_t& d,Int_t& s,Int_t& ns,Int_t& ps)
1182 {
1183 // Provide the time difference w.r.t the AliTimestamp specified on the input.
1184 // This memberfunction supports both very small (i.e. time of flight analysis
1185 // for particle physics experiments) and very long (i.e. investigation of
1186 // astrophysical phenomena) timescales.
1187 //
1188 // The time difference is returned via the following output arguments :
1189 // d  : elapsed number of days
1190 // s  : remaining elapsed number of seconds
1191 // ns : remaining elapsed number of nanoseconds
1192 // ps : remaining elapsed number of picoseconds
1193 //
1194 // Note :
1195 // ------
1196 // The calculated time difference is the absolute value of the time interval.
1197 // This implies that the values of d, s, ns and ps are always positive or zero.
1198 //
1199 // The integer return argument indicates whether the AliTimestamp specified
1200 // on the input argument occurred earlier (-1), simultaneously (0) or later (1).
1201
1202  if (!t) return 0;
1203
1204  // Ensure updated Julian parameters for this AliTimestamp instance 
1205  if (fCalcs != GetSec() || fCalcns != GetNanoSec()) FillJulian();
1206
1207  // Use Get functions to ensure updated Julian parameters. 
1208  t->GetMJD(d,s,ns);
1209  ps=t->GetPs();
1210
1211  d-=fMJD;
1212  s-=fJsec;
1213  ns-=fJns;
1214  ps-=fJps;
1215
1216  if (!d && !s && !ns && !ps) return 0;
1217
1218  Int_t sign=0;
1219
1220  if (d>0) sign=1;
1221  if (d<0) sign=-1;
1222
1223  if (!sign && s>0) sign=1;
1224  if (!sign && s<0) sign=-1;
1225
1226  if (!sign && ns>0) sign=1; 
1227  if (!sign && ns<0) sign=-1;
1228
1229  if (!sign && ps>0) sign=1; 
1230  if (!sign && ps<0) sign=-1;
1231
1232  // In case the input stamp was earlier, take the reverse difference
1233  // to simplify the algebra.
1234  if (sign<0)
1235  {
1236   d=-d;
1237   s=-s;
1238   ns=-ns;
1239   ps=-ps;
1240  }
1241
1242  // Here we always have a positive time difference
1243  // and can now unambiguously correct for other negative values.
1244  if (ps<0)
1245  {
1246   ns-=1;
1247   ps+=1000;
1248  }
1249
1250  if (ns<0)
1251  {
1252   s-=1;
1253   ns+=1000000000;
1254  }
1255
1256  if (s<0)
1257  {
1258   d-=1;
1259   s+=24*3600;
1260  }
1261
1262  return sign;
1263 }
1264 ///////////////////////////////////////////////////////////////////////////
1265 Int_t AliTimestamp::GetDifference(AliTimestamp& t,Int_t& d,Int_t& s,Int_t& ns,Int_t& ps)
1266 {
1267 // Provide the time difference w.r.t the AliTimestamp specified on the input.
1268 // This memberfunction supports both very small (i.e. time of flight analysis
1269 // for particle physics experiments) and very long (i.e. investigation of
1270 // astrophysical phenomena) timescales.
1271 //
1272 // The time difference is returned via the following output arguments :
1273 // d  : elapsed number of days
1274 // s  : remaining elapsed number of seconds
1275 // ns : remaining elapsed number of nanoseconds
1276 // ps : remaining elapsed number of picoseconds
1277 //
1278 // Note :
1279 // ------
1280 // The calculated time difference is the absolute value of the time interval.
1281 // This implies that the values of d, s, ns and ps are always positive or zero.
1282 //
1283 // The integer return argument indicates whether the AliTimestamp specified
1284 // on the input argument occurred earlier (-1), simultaneously (0) or later (1).
1285
1286  return GetDifference(&t,d,s,ns,ps);
1287 }
1288 ///////////////////////////////////////////////////////////////////////////
1289 Double_t AliTimestamp::GetDifference(AliTimestamp* t,TString u,Int_t mode)
1290 {
1291 // Provide the time difference w.r.t the AliTimestamp specified on the input
1292 // argument in the units as specified by the TString argument.
1293 // A positive return value means that the AliTimestamp specified on the input
1294 // argument occurred later, whereas a negative return value indicates an
1295 // earlier occurence. 
1296 //  
1297 // The units may be specified as :
1298 // u = "d"  ==> Time difference returned as (fractional) day count
1299 //     "s"  ==> Time difference returned as (fractional) second count
1300 //     "ns" ==> Time difference returned as (fractional) nanosecond count
1301 //     "ps" ==> Time difference returned as picosecond count
1302 //
1303 // It may be clear that for a time difference of several days, the picosecond
1304 // and even the nanosecond accuracy may be lost.
1305 // To cope with this, the "mode" argument has been introduced to allow 
1306 // timestamp comparison on only the specified units.
1307 //
1308 // The following operation modes are supported :
1309 // mode = 1 : Full time difference is returned in specified units
1310 //        2 : Time difference is returned in specified units by
1311 //            neglecting the elapsed time for the larger units than the
1312 //            ones specified.
1313 //        3 : Time difference is returned in specified units by only
1314 //            comparing the timestamps on the level of the specified units.
1315 //
1316 // Example :
1317 // ---------
1318 // AliTimestamp t1; // Corresponding to days=3, secs=501, ns=31, ps=7 
1319 // AliTimestamp t2; // Corresponding to days=5, secs=535, ns=12, ps=15
1320 //
1321 // The statement : Double_t val=t1.GetDifference(t2,....)
1322 // would return the following values :
1323 // val=(2*24*3600)+34-(19*1e-9)+(8*1e-12) for u="s" and mode=1
1324 // val=34-(19*1e-9)+(8*1e-12)             for u="s" and mode=2
1325 // val=34                                 for u="s" and mode=3
1326 // val=-19                                for u="ns" and mode=3
1327 //
1328 // The default is mode=1.
1329
1330  if (!t || mode<1 || mode>3) return 0;
1331
1332  Double_t dt=0;
1333
1334  // Ensure updated Julian parameters for this AliTimestamp instance 
1335  if (fCalcs != GetSec() || fCalcns != GetNanoSec()) FillJulian();
1336
1337  Int_t dd=0;
1338  Int_t ds=0;
1339  Int_t dns=0;
1340  Int_t dps=0;
1341
1342  // Use Get functions to ensure updated Julian parameters. 
1343  t->GetMJD(dd,ds,dns);
1344  dps=t->GetPs();
1345
1346  dd-=fMJD;
1347  ds-=fJsec;
1348  dns-=fJns;
1349  dps-=fJps;
1350
1351  // Time difference for the specified units only
1352  if (mode==3)
1353  {
1354   if (u=="d") dt=dd;
1355   if (u=="s") dt=ds;
1356   if (u=="ns") dt=dns;
1357   if (u=="ps") dt=dps;
1358   return dt;
1359  }
1360
1361  // Suppress elapsed time for the larger units than specified
1362  if (mode==2)
1363  {
1364   if (u=="s") dd=0;
1365   if (u=="ns")
1366   {
1367    dd=0;
1368    ds=0;
1369   }
1370   if (u=="ps")
1371   {
1372    dd=0;
1373    ds=0;
1374    dns=0;
1375   }
1376  }
1377
1378  // Compute the time difference as requested 
1379  if (u=="s" || u=="d")
1380  {
1381   // The time difference in (fractional) seconds
1382   dt=double(dd*24*3600+ds)+(double(dns)*1e-9)+(double(dps)*1e-12);
1383   if (u=="d") dt=dt/double(24*3600);
1384  }
1385  if (u=="ns") dt=(double(dd*24*3600+ds)*1e9)+double(dns)+(double(dps)*1e-3);
1386  if (u=="ps") dt=(double(dd*24*3600+ds)*1e12)+(double(dns)*1e3)+double(dps);
1387
1388  return dt;
1389 }
1390 ///////////////////////////////////////////////////////////////////////////
1391 Double_t AliTimestamp::GetDifference(AliTimestamp& t,TString u,Int_t mode)
1392 {
1393 // Provide the time difference w.r.t the AliTimestamp specified on the input
1394 // argument in the units as specified by the TString argument.
1395 // A positive return value means that the AliTimestamp specified on the input
1396 // argument occurred later, whereas a negative return value indicates an
1397 // earlier occurence. 
1398 //  
1399 // The units may be specified as :
1400 // u = "d"  ==> Time difference returned as (fractional) day count
1401 //     "s"  ==> Time difference returned as (fractional) second count
1402 //     "ns" ==> Time difference returned as (fractional) nanosecond count
1403 //     "ps" ==> Time difference returned as picosecond count
1404 //
1405 // It may be clear that for a time difference of several days, the picosecond
1406 // and even the nanosecond accuracy may be lost.
1407 // To cope with this, the "mode" argument has been introduced to allow 
1408 // timestamp comparison on only the specified units.
1409 //
1410 // The following operation modes are supported :
1411 // mode = 1 : Full time difference is returned in specified units
1412 //        2 : Time difference is returned in specified units by
1413 //            neglecting the elapsed time for the larger units than the
1414 //            ones specified.
1415 //        3 : Time difference is returned in specified units by only
1416 //            comparing the timestamps on the level of the specified units.
1417 //
1418 // Example :
1419 // ---------
1420 // AliTimestamp t1; // Corresponding to days=3, secs=501, ns=31, ps=7 
1421 // AliTimestamp t2; // Corresponding to days=5, secs=535, ns=12, ps=15
1422 //
1423 // The statement : Double_t val=t1.GetDifference(t2,....)
1424 // would return the following values :
1425 // val=(2*24*3600)+34-(19*1e-9)+(8*1e-12) for u="s" and mode=1
1426 // val=34-(19*1e-9)+(8*1e-12)             for u="s" and mode=2
1427 // val=34                                 for u="s" and mode=3
1428 // val=-19                                for u="ns" and mode=3
1429 //
1430 // The default is mode=1.
1431
1432  return GetDifference(&t,u,mode);
1433 }
1434 ///////////////////////////////////////////////////////////////////////////
1435 void AliTimestamp::SetUT(Int_t y,Int_t m,Int_t d,Int_t hh,Int_t mm,Int_t ss,Int_t ns,Int_t ps)
1436 {
1437 // Set the AliTimestamp parameters corresponding to the UT date and time
1438 // in the Gregorian calendar as specified by the input arguments.
1439 // This facility is exact upto picosecond precision and as such is
1440 // for scientific observations preferable above the corresponding
1441 // Set function(s) of TTimestamp.
1442 // The latter has a random spread in the sub-second part, which
1443 // might be of use in generating distinguishable timestamps while
1444 // still keeping second precision.
1445 //
1446 // The input arguments represent the following :
1447 // y  : year in UT (e.g. 1952, 2003 etc...)
1448 // m  : month in UT (1=jan  2=feb etc...)
1449 // d  : day in UT (1-31)
1450 // hh : elapsed hours in UT (0-23) 
1451 // mm : elapsed minutes in UT (0-59)
1452 // ss : elapsed seconds in UT (0-59)
1453 // ns : remaining fractional elapsed second of UT in nanosecond
1454 // ps : remaining fractional elapsed nanosecond of UT in picosecond
1455 //
1456 // Note : ns=0 and ps=0 are the default values.
1457 //
1458 // This facility first determines the elapsed days, seconds etc...
1459 // since the beginning of the specified UT year on bais of the
1460 // input arguments. Subsequently it invokes the SetUT memberfunction
1461 // for the elapsed timespan.
1462 // As such this facility is valid for all AD dates in the Gregorian
1463 // calendar with picosecond precision.
1464
1465  Int_t day=GetDayOfYear(d,m,y);
1466  Int_t secs=hh*3600+mm*60+ss;
1467  SetUT(y,day-1,secs,ns,ps);
1468 }
1469 ///////////////////////////////////////////////////////////////////////////
1470 void AliTimestamp::SetUT(Int_t y,Int_t d,Int_t s,Int_t ns,Int_t ps)
1471 {
1472 // Set the AliTimestamp parameters corresponding to the specified elapsed
1473 // timespan since the beginning of the new UT year.
1474 // This facility is exact upto picosecond precision and as such is
1475 // for scientific observations preferable above the corresponding
1476 // Set function(s) of TTimestamp.
1477 // The latter has a random spread in the sub-second part, which
1478 // might be of use in generating distinguishable timestamps while
1479 // still keeping second precision.
1480 //
1481 // The UT year and elapsed time span is entered via the following input arguments :
1482 //
1483 // y  : year in UT (e.g. 1952, 2003 etc...)
1484 // d  : elapsed number of days 
1485 // s  : (remaining) elapsed number of seconds
1486 // ns : (remaining) elapsed number of nanoseconds
1487 // ps : (remaining) elapsed number of picoseconds
1488 //
1489 // The specified d, s, ns and ps values will be used in an additive
1490 // way to determine the elapsed timespan.
1491 // So, specification of d=1, s=100, ns=0, ps=0 will result in the
1492 // same elapsed time span as d=0, s=24*3600+100, ns=0, ps=0.
1493 // However, by making use of the latter the user should take care
1494 // of possible integer overflow problems in the input arguments,
1495 // which obviously will provide incorrect results. 
1496 //
1497 // Note : ns=0 and ps=0 are the default values.
1498 //
1499 // This facility first sets the (M)JD corresponding to the start (01-jan 00:00:00)
1500 // of the specified UT year following the recipe of R.W. Sinnott
1501 // Sky & Telescope 82, (aug. 1991) 183.
1502 // Subsequently the day and (sub)second parts are added to the AliTimestamp.
1503 // As such this facility is valid for all AD dates in the Gregorian calendar.
1504
1505  Double_t jd=GetJD(y,1,1,0,0,0,0);
1506  SetJD(jd);
1507
1508  Int_t mjd,sec,nsec;
1509  GetMJD(mjd,sec,nsec);
1510  SetMJD(mjd,0,0,0);
1511  Add(d,s,ns,ps);
1512 }
1513 ///////////////////////////////////////////////////////////////////////////
1514 void AliTimestamp::GetUT(Int_t& hh,Int_t& mm,Int_t& ss,Int_t& ns,Int_t& ps)
1515 {
1516 // Provide the corrresponding UT as hh:mm:ss:ns:ps.
1517 // This facility is based on the MJD, so the TTimeStamp limitations
1518 // do not apply here.
1519
1520  Int_t mjd,sec,nsec,psec;
1521
1522  GetMJD(mjd,sec,nsec);
1523  psec=GetPs();
1524
1525  hh=sec/3600;
1526  sec=sec%3600;
1527  mm=sec/60;
1528  ss=sec%60;
1529  ns=nsec;
1530  ps=psec;
1531 }
1532 ///////////////////////////////////////////////////////////////////////////
1533 Double_t AliTimestamp::GetUT()
1534 {
1535 // Provide the corrresponding UT in fractional hours.
1536 // This facility is based on the MJD, so the TTimeStamp limitations
1537 // do not apply here.
1538
1539  Int_t hh,mm,ss,ns,ps;
1540
1541  GetUT(hh,mm,ss,ns,ps);
1542
1543  Double_t ut=Convert(hh,mm,ss,ns,ps);
1544
1545  return ut;
1546 }
1547 ///////////////////////////////////////////////////////////////////////////
1548 void AliTimestamp::GetGST(Int_t& hh,Int_t& mm,Int_t& ss,Int_t& ns,Int_t& ps)
1549 {
1550 // Provide the corrresponding Greenwich Sideral Time (GST).
1551 // The algorithm used is the one described at p. 83 of the book
1552 // Astronomy Methods by Hale Bradt.
1553 // This facility is based on the MJD, so the TTimeStamp limitations
1554 // do not apply here.
1555
1556  Int_t mjd,sec,nsec,psec;
1557
1558  // The current UT based timestamp data
1559  GetMJD(mjd,sec,nsec);
1560  psec=fJps;
1561
1562  // The basis for the daily corrections in units of Julian centuries w.r.t. J2000.
1563  // Note : Epoch J2000 starts at 01-jan-2000 12:00:00 UT.
1564  Double_t tau=(GetJD()-2451545.)/36525.;
1565
1566  // Syncronise sidereal time with current timestamp
1567  AliTimestamp sid;
1568  sid.SetMJD(mjd,sec,nsec,psec);
1569
1570  // Add offset for GST start value defined as 06:41:50.54841 at 01-jan 00:00:00 UT
1571  sec=6*3600+41*60+50;
1572  nsec=548410000;
1573  psec=0;
1574  sid.Add(0,sec,nsec,psec);
1575
1576  // Daily correction for precession and polar motion 
1577  Double_t addsec=8640184.812866*tau+0.093104*pow(tau,2)-6.2e-6*pow(tau,3);
1578  sec=int(addsec);
1579  addsec-=double(sec);
1580  nsec=int(addsec*1.e9);
1581  addsec-=double(nsec)*1.e-9;
1582  psec=int(addsec*1.e12);
1583  sid.Add(0,sec,nsec,psec);
1584
1585  sid.GetMJD(mjd,sec,nsec);
1586  psec=sid.GetPs();
1587
1588  hh=sec/3600;
1589  sec=sec%3600;
1590  mm=sec/60;
1591  ss=sec%60;
1592  ns=nsec;
1593  ps=psec;
1594 }
1595 ///////////////////////////////////////////////////////////////////////////
1596 Double_t AliTimestamp::GetGST()
1597 {
1598 // Provide the corrresponding Greenwich Sideral Time (GMST)
1599 // in fractional hours.
1600 // This facility is based on the MJD, so the TTimeStamp limitations
1601 // do not apply here.
1602
1603  Int_t hh,mm,ss,ns,ps;
1604
1605  GetGST(hh,mm,ss,ns,ps);
1606
1607  Double_t gst=Convert(hh,mm,ss,ns,ps);
1608
1609  return gst;
1610 }
1611 ///////////////////////////////////////////////////////////////////////////
1612 Double_t AliTimestamp::GetJD(Double_t e,TString mode) const
1613 {
1614 // Provide the fractional Julian Date from epoch e.
1615 // The sort of epoch may be specified via the "mode" parameter.
1616 //
1617 // mode = "J" ==> Julian epoch
1618 //        "B" ==> Besselian epoch
1619 //
1620 // The default value is mode="J".
1621
1622  Double_t jd=0;
1623
1624  if (mode=="J" || mode=="j") jd=(e-2000.0)*365.25+2451545.0;
1625
1626  if (mode=="B" || mode=="b") jd=(e-1900.0)*365.242198781+2415020.31352;
1627
1628  return jd;
1629 }
1630 ///////////////////////////////////////////////////////////////////////////
1631 Double_t AliTimestamp::GetMJD(Double_t e,TString mode) const
1632 {
1633 // Provide the fractional Modified Julian Date from epoch e.
1634 // The sort of epoch may be specified via the "mode" parameter.
1635 //
1636 // mode = "J" ==> Julian epoch
1637 //        "B" ==> Besselian epoch
1638 //
1639 // The default value is mode="J".
1640
1641  Double_t mjd=GetJD(e,mode)-2400000.5;
1642
1643  return mjd;
1644 }
1645 ///////////////////////////////////////////////////////////////////////////
1646 Double_t AliTimestamp::GetTJD(Double_t e,TString mode) const
1647 {
1648 // Provide the fractional Truncated Julian Date from epoch e.
1649 // The sort of epoch may be specified via the "mode" parameter.
1650 //
1651 // mode = "J" ==> Julian epoch
1652 //        "B" ==> Besselian epoch
1653 //
1654 // The default value is mode="J".
1655
1656  Double_t tjd=GetJD(e,mode)-2440000.5;
1657
1658  return tjd;
1659 }
1660 ///////////////////////////////////////////////////////////////////////////