]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliTimestamp.cxx
bba3c90db1b0f6847d5640aece2b368249aa72c0
[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 #include <cmath>
170
171 ClassImp(AliTimestamp) // Class implementation to enable ROOT I/O
172  
173 AliTimestamp::AliTimestamp() : TTimeStamp()
174 {
175 // Default constructor
176 // Creation of an AliTimestamp object and initialisation of parameters.
177 // All attributes are initialised to the current date/time as specified
178 // in the docs of TTimeStamp.
179
180  FillJulian();
181  fJps=0;
182 }
183 ///////////////////////////////////////////////////////////////////////////
184 AliTimestamp::AliTimestamp(TTimeStamp& t) : TTimeStamp(t)
185 {
186 // Creation of an AliTimestamp object and initialisation of parameters.
187 // All attributes are initialised to the values of the input TTimeStamp.
188
189  FillJulian();
190  fJps=0;
191 }
192 ///////////////////////////////////////////////////////////////////////////
193 AliTimestamp::~AliTimestamp()
194 {
195 // Destructor to delete dynamically allocated memory.
196 }
197 ///////////////////////////////////////////////////////////////////////////
198 AliTimestamp::AliTimestamp(const AliTimestamp& t) : TTimeStamp(t)
199 {
200 // Copy constructor
201
202  fMJD=t.fMJD;
203  fJsec=t.fJsec;
204  fJns=t.fJns;
205  fJps=t.fJps;
206  fCalcs=t.fCalcs;
207  fCalcns=t.fCalcns;
208 }
209 ///////////////////////////////////////////////////////////////////////////
210 void AliTimestamp::Date(Int_t mode)
211 {
212 // Print date/time info.
213 //
214 // mode = 1 ==> Only the TTimeStamp yy-mm-dd hh:mm:ss:ns and GMST info is printed
215 //        2 ==> Only the Julian parameter info is printed
216 //        3 ==> Both the TTimeStamp, GMST and Julian parameter info is printed
217 //
218 // The default is mode=3.
219 //
220 // Note : In case the (M/T)JD falls outside the TTimeStamp range,
221 //        the TTimeStamp info will be replaced by UT hh:mm:ss:ns:ps info.
222
223  Int_t mjd,mjsec,mjns,mjps;
224  GetMJD(mjd,mjsec,mjns);
225  mjps=GetPs();
226
227  Int_t hh,mm,ss,ns,ps;
228  
229  if (mode==1 || mode==3)
230  {
231   if (mjd>=40587 && (mjd<65442 || (mjd==65442 && mjsec<8047)))
232   {
233    cout << " " << AsString() << endl;
234   }
235   else
236   {
237    GetUT(hh,mm,ss,ns,ps);
238    cout << " UT : " << setfill('0') << setw(2) << hh << ":"
239                     << setw(2) << mm << ":" << setw(2) << ss
240                     << " ns : " << ns << " ps : " << ps << " ";
241   }
242   GetGST(hh,mm,ss,ns,ps);
243   cout << " GST : " << setfill('0') << setw(2) << hh << ":"
244                     << setw(2) << mm << ":" << setw(2) << ss
245                     << " ns : " << ns << " ps : " << ps << endl;
246  }
247  if (mode==2 || mode==3)
248  {
249   Int_t jd,jsec,jns;
250   GetJD(jd,jsec,jns);
251   Int_t tjd,tjsec,tjns;
252   GetTJD(tjd,tjsec,tjns);
253   cout << " Julian Epoch : " << setprecision(25) << GetJE()
254        << " Besselian Epoch : " << setprecision(25) << GetBE() << endl;
255   cout << " JD : " << jd << " sec : " << jsec << " ns : " << jns << " ps : " << fJps
256        << " Fractional : " << setprecision(25) << GetJD() << endl;
257   cout << " MJD : " << mjd << "  sec : " << mjsec << " ns : " << mjns << " ps : " << fJps
258        << " Fractional : " << setprecision(25) << GetMJD() << endl;
259   cout << " TJD : " << tjd << "  sec : " << tjsec << " ns : " << tjns << " ps : " << fJps
260        << " Fractional : " << setprecision(25) << GetTJD() << endl;
261  }
262 }
263 ///////////////////////////////////////////////////////////////////////////
264 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
265 {
266 // Provide the (fractional) Julian Date (JD) corresponding to the UT date
267 // and time in the Gregorian calendar as specified by the input arguments.
268 //
269 // The input arguments represent the following :
270 // y  : year in UT (e.g. 1952, 2003 etc...)
271 // m  : month in UT (1=jan  2=feb etc...)
272 // d  : day in UT (1-31)
273 // hh : elapsed hours in UT (0-23) 
274 // mm : elapsed minutes in UT (0-59)
275 // ss : elapsed seconds in UT (0-59)
276 // ns : remaining fractional elapsed second of UT in nanosecond
277 //
278 // This algorithm is valid for all AD dates in the Gregorian calendar
279 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
280 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
281 //
282 // In case of invalid input, a value of -1 is returned.
283 //
284 // Note :
285 // ------
286 // This memberfunction only provides the JD corresponding to the
287 // UT input arguments. It does NOT set the corresponding Julian parameters
288 // for the current AliTimestamp instance.
289 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
290 // To set the Julian parameters for the current AliTimestamp instance,
291 // please use the corresponding SET() memberfunctions of either AliTimestamp
292 // or TTimeStamp. 
293
294  if (y<0 || m<1 || m>12 || d<1 || d>31) return -1;
295  if (hh<0 || hh>23 || mm<0 || mm>59 || ss<0 || ss>59 || ns<0 || ns>1e9) return -1;
296
297  // The UT daytime in fractional hours
298  Double_t ut=double(hh)+double(mm)/60.+(double(ss)+double(ns)*1.e-9)/3600.;
299
300  Double_t JD=0;
301  
302  JD=367*y-int(7*(y+int((m+9)/12))/4)
303     -int(3*(int((y+(m-9)/7)/100)+1)/4)
304     +int(275*m/9)+d+1721028.5+ut/24.;
305
306  return JD;
307 }
308 ///////////////////////////////////////////////////////////////////////////
309 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
310 {
311 // Provide the (fractional) Modified Julian Date corresponding to the UT
312 // date and time in the Gregorian calendar as specified by the input arguments.
313 //
314 // The input arguments represent the following :
315 // y  : year in UT (e.g. 1952, 2003 etc...)
316 // m  : month in UT (1=jan  2=feb etc...)
317 // d  : day in UT (1-31)
318 // hh : elapsed hours in UT (0-23) 
319 // mm : elapsed minutes in UT (0-59)
320 // ss : elapsed seconds in UT (0-59)
321 // ns : remaining fractional elapsed second of UT in nanosecond
322 //
323 // This algorithm is valid for all AD dates in the Gregorian calendar
324 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
325 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
326 //
327 // In case of invalid input, a value of -1 is returned.
328 //
329 // Note :
330 // ------
331 // This memberfunction only provides the MJD corresponding to the
332 // UT input arguments. It does NOT set the corresponding Julian parameters
333 // for the current AliTimestamp instance.
334 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
335 // To set the Julian parameters for the current AliTimestamp instance,
336 // please use the corresponding SET() memberfunctions of either AliTimestamp
337 // or TTimeStamp.
338
339  Double_t JD=GetJD(y,m,d,hh,mm,ss,ns);
340
341  if (JD<0) return JD;
342
343  Double_t MJD=JD-2400000.5;
344
345  return MJD; 
346
347 ///////////////////////////////////////////////////////////////////////////
348 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
349 {
350 // Provide the (fractional) Truncated Julian Date corresponding to the UT
351 // date and time in the Gregorian calendar as specified by the input arguments.
352 //
353 // The input arguments represent the following :
354 // y  : year in UT (e.g. 1952, 2003 etc...)
355 // m  : month in UT (1=jan  2=feb etc...)
356 // d  : day in UT (1-31)
357 // hh : elapsed hours in UT (0-23) 
358 // mm : elapsed minutes in UT (0-59)
359 // ss : elapsed seconds in UT (0-59)
360 // ns : remaining fractional elapsed second of UT in nanosecond
361 //
362 // This algorithm is valid for all AD dates in the Gregorian calendar
363 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
364 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
365 //
366 // In case of invalid input, a value of -1 is returned.
367 //
368 // Note :
369 // ------
370 // This memberfunction only provides the TJD corresponding to the
371 // UT input arguments. It does NOT set the corresponding Julian parameters
372 // for the current AliTimestamp instance.
373 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
374 // To set the Julian parameters for the current AliTimestamp instance,
375 // please use the corresponding SET() memberfunctions of either AliTimestamp
376 // or TTimeStamp.
377
378  Double_t JD=GetJD(y,m,d,hh,mm,ss,ns);
379
380  if (JD<0) return JD;
381
382  Double_t TJD=JD-2440000.5;
383
384  return TJD; 
385
386 ///////////////////////////////////////////////////////////////////////////
387 Double_t AliTimestamp::GetJE(Double_t date,TString mode) const
388 {
389 // Provide the Julian Epoch (JE) corresponding to the specified date.
390 // The argument "mode" indicates the type of the argument "date".
391 //
392 // Available modes are :
393 // mode = "jd"  ==> date represents the Julian Date
394 //      = "mjd" ==> date represents the Modified Julian Date
395 //      = "tjd" ==> date represents the Truncated Julian Date
396 //
397 // The default is mode="jd".
398 //
399 // In case of invalid input, a value of -99999 is returned.
400 //
401 // Note :
402 // ------
403 // This memberfunction only provides the JE corresponding to the
404 // input arguments. It does NOT set the corresponding Julian parameters
405 // for the current AliTimestamp instance.
406 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
407 // To set the Julian parameters for the current AliTimestamp instance,
408 // please use the corresponding SET() memberfunctions of either AliTimestamp
409 // or TTimeStamp.
410
411  if ((mode != "jd") && (mode != "mjd") && (mode != "tjd")) return -99999;
412
413  Double_t jd=date;
414  if (mode=="mjd") jd=date+2400000.5;
415  if (mode=="tjd") jd=date+2440000.5;
416
417  Double_t je=2000.+(jd-2451545.)/365.25;
418
419  return je;
420 }
421 ///////////////////////////////////////////////////////////////////////////
422 Double_t AliTimestamp::GetBE(Double_t date,TString mode) const
423 {
424 // Provide the Besselian Epoch (JE) corresponding to the specified date.
425 // The argument "mode" indicates the type of the argument "date".
426 //
427 // Available modes are :
428 // mode = "jd"  ==> date represents the Julian Date
429 //      = "mjd" ==> date represents the Modified Julian Date
430 //      = "tjd" ==> date represents the Truncated Julian Date
431 //
432 // The default is mode="jd".
433 //
434 // In case of invalid input, a value of -99999 is returned.
435 //
436 // Note :
437 // ------
438 // This memberfunction only provides the BE corresponding to the
439 // input arguments. It does NOT set the corresponding Julian parameters
440 // for the current AliTimestamp instance.
441 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
442 // To set the Julian parameters for the current AliTimestamp instance,
443 // please use the corresponding SET() memberfunctions of either AliTimestamp
444 // or TTimeStamp.
445
446  if ((mode != "jd") && (mode != "mjd") && (mode != "tjd")) return -99999;
447
448  Double_t jd=date;
449  if (mode=="mjd") jd=date+2400000.5;
450  if (mode=="tjd") jd=date+2440000.5;
451
452  Double_t be=1900.+(jd-2415020.31352)/365.242198781;
453
454  return be;
455 }
456 ///////////////////////////////////////////////////////////////////////////
457 void AliTimestamp::Convert(Double_t date,Int_t& days,Int_t& secs,Int_t& ns) const
458 {
459 // Convert date as fractional day count into integer days, secs and ns.
460 //
461 // Note : Due to computer accuracy the ns value may become inaccurate.
462 //
463 // The arguments represent the following :
464 // date : The input date as fractional day count
465 // days : Number of elapsed days
466 // secs : Remaining number of elapsed seconds
467 // ns   : Remaining fractional elapsed second in nanoseconds
468 //
469 // Note :
470 // ------
471 // This memberfunction only converts the input date into the corresponding
472 // integer parameters. It does NOT set the corresponding Julian parameters
473 // for the current AliTimestamp instance.
474 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
475 // To set the Julian parameters for the current AliTimestamp instance,
476 // please use the corresponding SET() memberfunctions of either AliTimestamp
477 // or TTimeStamp.
478  
479  days=int(date);
480  date=date-double(days);
481  Int_t daysecs=24*3600;
482  date=date*double(daysecs);
483  secs=int(date);
484  date=date-double(secs);
485  ns=int(date*1.e9);
486 }
487 ///////////////////////////////////////////////////////////////////////////
488 Double_t AliTimestamp::Convert(Int_t days,Int_t secs,Int_t ns) const
489 {
490 // Convert date in integer days, secs and ns into fractional day count. 
491 //
492 // Note : Due to computer accuracy the ns precision may be lost.
493 //
494 // The input arguments represent the following :
495 // days : Number of elapsed days
496 // secs : Remaining number of elapsed seconds
497 // ns   : Remaining fractional elapsed second in nanoseconds
498 //
499 // Note :
500 // ------
501 // This memberfunction only converts the input integer parameters into the
502 // corresponding fractional day count. It does NOT set the corresponding
503 // Julian parameters for the current AliTimestamp instance.
504 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
505 // To set the Julian parameters for the current AliTimestamp instance,
506 // please use the corresponding SET() memberfunctions of either AliTimestamp
507 // or TTimeStamp.
508
509  Double_t frac=double(secs)+double(ns)*1.e-9;
510  Int_t daysecs=24*3600;
511  frac=frac/double(daysecs);
512  Double_t date=double(days)+frac;
513  return date;
514 }
515 ///////////////////////////////////////////////////////////////////////////
516 void AliTimestamp::Convert(Double_t h,Int_t& hh,Int_t& mm,Int_t& ss,Int_t& ns,Int_t& ps) const
517 {
518 // Convert fractional hour count h into hh:mm:ss:ns:ps.
519 //
520 // Note : Due to computer accuracy the ps value may become inaccurate.
521 //
522 // Note :
523 // ------
524 // This memberfunction only converts the input "h" into the corresponding
525 // integer parameters. It does NOT set the corresponding Julian parameters
526 // for the current AliTimestamp instance.
527 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
528 // To set the Julian parameters for the current AliTimestamp instance,
529 // please use the corresponding SET() memberfunctions of either AliTimestamp
530 // or TTimeStamp.
531  
532  hh=int(h);
533  h=h-double(hh);
534  h=h*3600.;
535  ss=int(h);
536  h=h-double(ss);
537  h=h*1.e9;
538  ns=int(h);
539  h=h-double(ns);
540  h=h*1000.;
541  ps=int(h);
542 }
543 ///////////////////////////////////////////////////////////////////////////
544 Double_t AliTimestamp::Convert(Int_t hh,Int_t mm,Int_t ss,Int_t ns,Int_t ps) const
545 {
546 // Convert hh:mm:ss:ns:ps into fractional hour count. 
547 //
548 // Note : Due to computer accuracy the ps precision may be lost.
549 //
550 // Note :
551 // ------
552 // This memberfunction only converts the input integer parameters into the
553 // corresponding fractional hour count. It does NOT set the corresponding
554 // Julian parameters for the current AliTimestamp instance.
555 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
556 // To set the Julian parameters for the current AliTimestamp instance,
557 // please use the corresponding SET() memberfunctions of either AliTimestamp
558 // or TTimeStamp.
559
560  Double_t h=hh;
561  h+=double(mm)/60.+(double(ss)+double(ns)*1.e-9+double(ps)*1.e-12)/3600.;
562
563  return h;
564 }
565 ///////////////////////////////////////////////////////////////////////////
566 void AliTimestamp::FillJulian()
567 {
568 // Calculation and setting of the Julian date/time parameters corresponding
569 // to the current TTimeStamp date/time parameters.
570
571  UInt_t y,m,d,hh,mm,ss;
572
573  GetDate(kTRUE,0,&y,&m,&d);
574  GetTime(kTRUE,0,&hh,&mm,&ss);
575  Int_t ns=GetNanoSec();
576
577  Double_t mjd=GetMJD(y,m,d,hh,mm,ss,ns);
578
579  fMJD=int(mjd);
580  fJsec=GetSec()%(24*3600); // Daytime in elapsed seconds
581  fJns=ns;                  // Remaining fractional elapsed second in nanoseconds
582
583  // Store the TTimeStamp seconds and nanoseconds values
584  // for which this Julian calculation was performed.
585  fCalcs=GetSec();
586  fCalcns=GetNanoSec();
587 }
588 ///////////////////////////////////////////////////////////////////////////
589 void AliTimestamp::GetMJD(Int_t& mjd,Int_t& sec,Int_t& ns)
590 {
591 // Provide the Modified Julian Date (MJD) and time corresponding to the
592 // currently stored AliTimestamp date/time parameters.
593 //
594 // The returned arguments represent the following :
595 // mjd : The modified Julian date.
596 // sec : The number of seconds elapsed within the MJD.
597 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
598
599  if (fCalcs != GetSec() || fCalcns != GetNanoSec()) FillJulian();
600
601  mjd=fMJD;
602  sec=fJsec;
603  ns=fJns;
604 }
605 ///////////////////////////////////////////////////////////////////////////
606 Double_t AliTimestamp::GetMJD()
607 {
608 // Provide the (fractional) Modified Julian Date (MJD) corresponding to the
609 // currently stored AliTimestamp date/time parameters.
610 //
611 // Due to computer accuracy the ns precision may be lost.
612 // It is advised to use the (mjd,sec,ns) getter instead.
613
614  Int_t mjd=0;
615  Int_t sec=0;
616  Int_t ns=0;
617  GetMJD(mjd,sec,ns);
618
619  Double_t date=Convert(mjd,sec,ns);
620
621  return date;
622 }
623 ///////////////////////////////////////////////////////////////////////////
624 void AliTimestamp::GetTJD(Int_t& tjd,Int_t& sec, Int_t& ns)
625 {
626 // Provide the Truncated Julian Date (TJD) and time corresponding to the
627 // currently stored AliTimestamp date/time parameters.
628 //
629 // The returned arguments represent the following :
630 // tjd : The modified Julian date.
631 // sec : The number of seconds elapsed within the MJD.
632 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
633
634  Int_t mjd=0;
635  GetMJD(mjd,sec,ns);
636
637  tjd=mjd-40000;
638 }
639 ///////////////////////////////////////////////////////////////////////////
640 Double_t AliTimestamp::GetTJD()
641 {
642 // Provide the (fractional) Truncated Julian Date (TJD) corresponding to the
643 // currently stored AliTimestamp date/time parameters.
644 //
645 // Due to computer accuracy the ns precision may be lost.
646 // It is advised to use the (mjd,sec,ns) getter instead.
647
648  Int_t tjd=0;
649  Int_t sec=0;
650  Int_t ns=0;
651  GetTJD(tjd,sec,ns);
652
653  Double_t date=Convert(tjd,sec,ns);
654
655  return date;
656 }
657 ///////////////////////////////////////////////////////////////////////////
658 void AliTimestamp::GetJD(Int_t& jd,Int_t& sec, Int_t& ns)
659 {
660 // Provide the Julian Date (JD) and time corresponding to the currently
661 // stored AliTimestamp date/time parameters.
662 //
663 // The returned arguments represent the following :
664 // jd  : The Julian date.
665 // sec : The number of seconds elapsed within the JD.
666 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
667
668  Int_t mjd=0;
669  GetMJD(mjd,sec,ns);
670
671  jd=mjd+2400000;
672  sec+=12*3600;
673  if (sec >= 24*3600)
674  {
675   sec-=24*3600;
676   jd+=1;
677  }
678 }
679 ///////////////////////////////////////////////////////////////////////////
680 Double_t AliTimestamp::GetJD()
681 {
682 // Provide the (fractional) Julian Date (JD) corresponding to the currently
683 // stored AliTimestamp date/time parameters.
684 //
685 // Due to computer accuracy the ns precision may be lost.
686 // It is advised to use the (jd,sec,ns) getter instead.
687
688  Int_t jd=0;
689  Int_t sec=0;
690  Int_t ns=0;
691  GetJD(jd,sec,ns);
692
693  Double_t date=Convert(jd,sec,ns);
694
695  return date;
696 }
697 ///////////////////////////////////////////////////////////////////////////
698 Double_t AliTimestamp::GetJE()
699 {
700 // Provide the Julian Epoch (JE) corresponding to the currently stored
701 // AliTimestamp date/time parameters.
702
703  Double_t jd=GetJD();
704  Double_t je=GetJE(jd);
705  return je;
706 }
707 ///////////////////////////////////////////////////////////////////////////
708 Double_t AliTimestamp::GetBE()
709 {
710 // Provide the Besselian Epoch (BE) corresponding to the currently stored
711 // AliTimestamp date/time parameters.
712
713  Double_t jd=GetJD();
714  Double_t be=GetBE(jd);
715  return be;
716 }
717 ///////////////////////////////////////////////////////////////////////////
718 void AliTimestamp::SetMJD(Int_t mjd,Int_t sec,Int_t ns,Int_t ps)
719 {
720 // Set the Modified Julian Date (MJD) and time and update the TTimeStamp
721 // parameters accordingly (if possible).
722 //
723 // Note :
724 // ------
725 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
726 // which corresponds to the start of MJD=40587.
727 // Using the corresponding MJD of this EPOCH allows construction of
728 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
729 // Obviously this TTimeStamp implementation would prevent usage of MJD values
730 // smaller than 40587.
731 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
732 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
733 // However, this AliTimestamp facility provides support for the full range
734 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
735 // is restricted to the values allowed by the TTimeStamp implementation.
736 // For these earlier/later MJD values, the standard TTimeStamp parameters will
737 // be set corresponding to the start of the TTimeStamp EPOCH.  
738 // This implies that for these earlier/later MJD values the TTimeStamp parameters
739 // do not match the Julian parameters of AliTimestamp.  
740 //
741 // The input arguments represent the following :
742 // mjd : The modified Julian date.
743 // sec : The number of seconds elapsed within the MJD.
744 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
745 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the MJD.
746 //
747 // Note : ps=0 is the default value.
748
749  if (sec<0 || sec>=24*3600 || ns<0 || ns>=1e9 || ps<0 || ps>=1000)
750  {
751   cout << " *AliTimestamp::SetMJD* Invalid input."
752        << " sec : " << sec << " ns : " << ns << endl; 
753   return;
754  }
755
756  fMJD=mjd;
757  fJsec=sec;
758  fJns=ns;
759  fJps=ps;
760
761  Int_t epoch=40587; // MJD of the start of the epoch
762  Int_t limit=65442; // MJD of the latest possible TTimeStamp date/time
763  
764  Int_t date,time;
765  if (mjd<epoch || (mjd>=limit && sec>=8047))
766  {
767   Set(0,kFALSE,0,kFALSE);
768   date=GetDate();
769   time=GetTime();
770   Set(date,time,0,kTRUE,0);
771  }
772  else
773  {
774   // The elapsed time since start of EPOCH
775   Int_t days=mjd-epoch;
776   UInt_t secs=days*24*3600;
777   secs+=sec;
778   Set(secs,kFALSE,0,kFALSE);
779   date=GetDate();
780   time=GetTime();
781   Set(date,time,ns,kTRUE,0);
782  }
783
784  // Denote that the Julian and TTimeStamp parameters are synchronised,
785  // even in the case the MJD falls outside the TTimeStamp validity range.
786  // The latter still allows retrieval of Julian parameters for these
787  // earlier times.
788  fCalcs=GetSec();
789  fCalcns=GetNanoSec();
790 }
791 ///////////////////////////////////////////////////////////////////////////
792 void AliTimestamp::SetMJD(Double_t mjd)
793 {
794 // Set the Modified Julian Date (MJD) and time and update the TTimeStamp
795 // parameters accordingly (if possible).
796 //
797 // Note :
798 // ------
799 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
800 // which corresponds to the start of MJD=40587.
801 // Using the corresponding MJD of this EPOCH allows construction of
802 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
803 // Obviously this TTimeStamp implementation would prevent usage of MJD values
804 // smaller than 40587.
805 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
806 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
807 // However, this AliTimestamp facility provides support for the full range
808 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
809 // is restricted to the values allowed by the TTimeStamp implementation.
810 // For these earlier/later MJD values, the standard TTimeStamp parameters will
811 // be set corresponding to the start of the TTimeStamp EPOCH.  
812 // This implies that for these earlier/later MJD values the TTimeStamp parameters
813 // do not match the Julian parameters of AliTimestamp.  
814 //
815 // Due to computer accuracy the ns precision may be lost.
816 // It is advised to use the (mjd,sec,ns) setting instead.
817 //
818 // The input argument represents the following :
819 // mjd : The modified Julian date as fractional day count.
820
821  Int_t days=0;
822  Int_t secs=0;
823  Int_t ns=0;
824  Convert(mjd,days,secs,ns);
825  SetMJD(days,secs,ns);
826 }
827 ///////////////////////////////////////////////////////////////////////////
828 void AliTimestamp::SetJD(Int_t jd,Int_t sec,Int_t ns,Int_t ps)
829 {
830 // Set the Julian Date (JD) and time and update the TTimeStamp
831 // parameters accordingly (if possible).
832 //
833 // Note :
834 // ------
835 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
836 // which corresponds to JD=2440587.5 or the start of MJD=40587.
837 // Using the corresponding MJD of this EPOCH allows construction of
838 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
839 // Obviously this TTimeStamp implementation would prevent usage of values
840 // smaller than JD=2440587.5.
841 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
842 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
843 // However, this AliTimestamp facility provides support for the full range
844 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
845 // is restricted to the values allowed by the TTimeStamp implementation.
846 // For these earlier/later JD values, the standard TTimeStamp parameters will
847 // be set corresponding to the start of the TTimeStamp EPOCH.  
848 // This implies that for these earlier/later (M)JD values the TTimeStamp parameters
849 // do not match the Julian parameters of AliTimestamp.  
850 //
851 // The input arguments represent the following :
852 // jd  : The Julian date.
853 // sec : The number of seconds elapsed within the JD.
854 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
855 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the JD.
856 //
857 // Note : ps=0 is the default value.
858
859  Int_t mjd=jd-2400000;
860  sec-=12*3600;
861  if (sec<0)
862  {
863   sec+=24*3600;
864   mjd-=1;
865  }
866
867  SetMJD(mjd,sec,ns,ps);
868 }
869 ///////////////////////////////////////////////////////////////////////////
870 void AliTimestamp::SetJD(Double_t jd)
871 {
872 // Set the Julian Date (JD) and time and update the TTimeStamp
873 // parameters accordingly (if possible).
874 //
875 // Note :
876 // ------
877 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
878 // which corresponds to JD=2440587.5 or the start of MJD=40587.
879 // Using the corresponding MJD of this EPOCH allows construction of
880 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
881 // Obviously this TTimeStamp implementation would prevent usage of values
882 // smaller than JD=2440587.5.
883 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
884 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
885 // However, this AliTimestamp facility provides support for the full range
886 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
887 // is restricted to the values allowed by the TTimeStamp implementation.
888 // For these earlier/later JD values, the standard TTimeStamp parameters will
889 // be set corresponding to the start of the TTimeStamp EPOCH.  
890 // This implies that for these earlier/later (M)JD values the TTimeStamp parameters
891 // do not match the Julian parameters of AliTimestamp.  
892 //
893 // Due to computer accuracy the ns precision may be lost.
894 // It is advised to use the (jd,sec,ns) setting instead.
895 //
896 // The input argument represents the following :
897 // jd : The Julian date as fractional day count.
898
899  Int_t days=0;
900  Int_t secs=0;
901  Int_t ns=0;
902  Convert(jd,days,secs,ns);
903
904  SetJD(days,secs,ns);
905 }
906 ///////////////////////////////////////////////////////////////////////////
907 void AliTimestamp::SetTJD(Int_t tjd,Int_t sec,Int_t ns,Int_t ps)
908 {
909 // Set the Truncated Julian Date (TJD) and time and update the TTimeStamp
910 // parameters accordingly (if possible).
911 //
912 // Note :
913 // ------
914 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
915 // which corresponds to JD=2440587.5 or the start of TJD=587.
916 // Using the corresponding MJD of this EPOCH allows construction of
917 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
918 // Obviously this TTimeStamp implementation would prevent usage of values
919 // smaller than TJD=587.
920 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
921 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
922 // However, this AliTimestamp facility provides support for the full range
923 // of (T)JD values, but the setting of the corresponding TTimeStamp parameters
924 // is restricted to the values allowed by the TTimeStamp implementation.
925 // For these earlier/later JD values, the standard TTimeStamp parameters will
926 // be set corresponding to the start of the TTimeStamp EPOCH.  
927 // This implies that for these earlier/later (T)JD values the TTimeStamp parameters
928 // do not match the Julian parameters of AliTimestamp.  
929 //
930 // The input arguments represent the following :
931 // tjd : The Truncated Julian date.
932 // sec : The number of seconds elapsed within the JD.
933 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
934 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the JD.
935 //
936 // Note : ps=0 is the default value.
937
938  Int_t mjd=tjd+40000;
939
940  SetMJD(mjd,sec,ns,ps);
941 }
942 ///////////////////////////////////////////////////////////////////////////
943 void AliTimestamp::SetTJD(Double_t tjd)
944 {
945 // Set the Truncated Julian Date (TJD) and time and update the TTimeStamp
946 // parameters accordingly (if possible).
947 //
948 // Note :
949 // ------
950 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
951 // which corresponds to JD=2440587.5 or the start of TJD=587.
952 // Using the corresponding MJD of this EPOCH allows construction of
953 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
954 // Obviously this TTimeStamp implementation would prevent usage of values
955 // smaller than TJD=587.
956 // Furthermore, due to a limitation on the "seconds since the EPOCH start" count
957 // in TTimeStamp, the latest accessible date/time is 19-jan-2038 02:14:08 UTC.
958 // However, this AliTimestamp facility provides support for the full range
959 // of (T)JD values, but the setting of the corresponding TTimeStamp parameters
960 // is restricted to the values allowed by the TTimeStamp implementation.
961 // For these earlier/later JD values, the standard TTimeStamp parameters will
962 // be set corresponding to the start of the TTimeStamp EPOCH.  
963 // This implies that for these earlier/later (T)JD values the TTimeStamp parameters
964 // do not match the Julian parameters of AliTimestamp.  
965 //
966 // Due to computer accuracy the ns precision may be lost.
967 // It is advised to use the (jd,sec,ns) setting instead.
968 //
969 // The input argument represents the following :
970 // tjd : The Truncated Julian date as fractional day count.
971
972  Int_t days=0;
973  Int_t secs=0;
974  Int_t ns=0;
975  Convert(tjd,days,secs,ns);
976
977  SetTJD(days,secs,ns);
978 }
979 ///////////////////////////////////////////////////////////////////////////
980 void AliTimestamp::SetNs(Int_t ns)
981 {
982 // Set the remaining fractional number of seconds in nanosecond precision.
983 // Notes :
984 // -------
985 // 1) The allowed range for the argument "ns" is [0,99999999].
986 //    Outside that range no action is performed.
987 // 2) The ns fraction can also be entered directly via SetMJD() etc...
988 // 3) For additional accuracy see SetPs().
989
990  if (ns>=0 && ns<=99999999) fJns=ns; 
991 }
992 ///////////////////////////////////////////////////////////////////////////
993 Int_t AliTimestamp::GetNs() const
994 {
995 // Provide the remaining fractional number of seconds in nanosecond precision.
996 // This function allows trigger/timing analysis for (astro)particle physics
997 // experiments.
998 // Note : For additional accuracy see also GetPs().
999
1000  return fJns; 
1001 }
1002 ///////////////////////////////////////////////////////////////////////////
1003 void AliTimestamp::SetPs(Int_t ps)
1004 {
1005 // Set the remaining fractional number of nanoseconds in picoseconds.
1006 // Notes :
1007 // -------
1008 // 1) The allowed range for the argument "ps" is [0,999].
1009 //    Outside that range no action is performed.
1010 // 2) The ps fraction can also be entered directly via SetMJD() etc...
1011
1012  if (ps>=0 && ps<=999) fJps=ps; 
1013 }
1014 ///////////////////////////////////////////////////////////////////////////
1015 Int_t AliTimestamp::GetPs() const
1016 {
1017 // Provide remaining fractional number of nanoseconds in picoseconds.
1018 // This function allows time of flight analysis for particle physics
1019 // experiments.
1020
1021  return fJps; 
1022 }
1023 ///////////////////////////////////////////////////////////////////////////
1024 void AliTimestamp::Add(Int_t d,Int_t s,Int_t ns,Int_t ps)
1025 {
1026 // Add (or subtract) a certain time difference to the current timestamp.
1027 // Subtraction can be achieved by entering negative values as input arguments.
1028 //
1029 // The time difference is entered via the following input arguments :
1030 //
1031 // d  : elapsed number of days
1032 // s  : (remaining) elapsed number of seconds
1033 // ns : (remaining) elapsed number of nanoseconds
1034 // ps : (remaining) elapsed number of picoseconds
1035 //
1036 // The specified d, s, ns and ps values will be used in an additive
1037 // way to determine the time difference.
1038 // So, specification of d=1, s=100, ns=0, ps=0 will result in the
1039 // same time difference addition as d=0, s=24*3600+100, ns=0, ps=0.
1040 // However, by making use of the latter the user should take care
1041 // of possible integer overflow problems in the input arguments,
1042 // which obviously will provide incorrect results. 
1043 //
1044 // Note : ps=0 is the default value.
1045
1046  Int_t days=0;
1047  Int_t secs=0;
1048  Int_t nsec=0;
1049  // Use Get functions to ensure updated Julian parameters. 
1050  GetMJD(days,secs,nsec);
1051  Int_t psec=GetPs();
1052
1053  psec+=ps%1000;
1054  nsec+=ps/1000;
1055  while (psec<0)
1056  {
1057   nsec-=1;
1058   psec+=1000;
1059  }
1060  while (psec>999)
1061  {
1062   nsec+=1;
1063   psec-=1000;
1064  }
1065
1066  nsec+=ns%1000000000;
1067  secs+=ns/1000000000;
1068  while (nsec<0)
1069  {
1070   secs-=1;
1071   nsec+=1000000000;
1072  }
1073  while (nsec>999999999)
1074  {
1075   secs+=1;
1076   nsec-=1000000000;
1077  }
1078
1079  secs+=s%(24*3600);
1080  days+=s/(24*3600);
1081  while (secs<0)
1082  {
1083   days-=1;
1084   secs+=24*3600;
1085  }
1086  while (secs>=24*3600)
1087  {
1088   days+=1;
1089   secs-=24*3600;
1090  }
1091
1092  days+=d;
1093
1094  SetMJD(days,secs,nsec,psec);
1095 }
1096 ///////////////////////////////////////////////////////////////////////////
1097 Int_t AliTimestamp::GetDifference(AliTimestamp* t,Int_t& d,Int_t& s,Int_t& ns,Int_t& ps)
1098 {
1099 // Provide the time difference w.r.t the AliTimestamp specified on the input.
1100 // This memberfunction supports both very small (i.e. time of flight analysis
1101 // for particle physics experiments) and very long (i.e. investigation of
1102 // astrophysical phenomena) timescales.
1103 //
1104 // The time difference is returned via the following output arguments :
1105 // d  : elapsed number of days
1106 // s  : remaining elapsed number of seconds
1107 // ns : remaining elapsed number of nanoseconds
1108 // ps : remaining elapsed number of picoseconds
1109 //
1110 // Note :
1111 // ------
1112 // The calculated time difference is the absolute value of the time interval.
1113 // This implies that the values of d, s, ns and ps are always positive or zero.
1114 //
1115 // The integer return argument indicates whether the AliTimestamp specified
1116 // on the input argument occurred earlier (-1), simultaneously (0) or later (1).
1117
1118  if (!t) return 0;
1119
1120  // Ensure updated Julian parameters for this AliTimestamp instance 
1121  if (fCalcs != GetSec() || fCalcns != GetNanoSec()) FillJulian();
1122
1123  // Use Get functions to ensure updated Julian parameters. 
1124  t->GetMJD(d,s,ns);
1125  ps=t->GetPs();
1126
1127  d-=fMJD;
1128  s-=fJsec;
1129  ns-=fJns;
1130  ps-=fJps;
1131
1132  if (!d && !s && !ns && !ps) return 0;
1133
1134  Int_t sign=0;
1135
1136  if (d>0) sign=1;
1137  if (d<0) sign=-1;
1138
1139  if (!sign && s>0) sign=1;
1140  if (!sign && s<0) sign=-1;
1141
1142  if (!sign && ns>0) sign=1; 
1143  if (!sign && ns<0) sign=-1;
1144
1145  if (!sign && ps>0) sign=1; 
1146  if (!sign && ps<0) sign=-1;
1147
1148  // In case the input stamp was earlier, take the reverse difference
1149  // to simplify the algebra.
1150  if (sign<0)
1151  {
1152   d=-d;
1153   s=-s;
1154   ns=-ns;
1155   ps=-ps;
1156  }
1157
1158  // Here we always have a positive time difference
1159  // and can now unambiguously correct for other negative values.
1160  if (ps<0)
1161  {
1162   ns-=1;
1163   ps+=1000;
1164  }
1165
1166  if (ns<0)
1167  {
1168   s-=1;
1169   ns+=1000000000;
1170  }
1171
1172  if (s<0)
1173  {
1174   d-=1;
1175   s+=24*3600;
1176  }
1177
1178  return sign;
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  return GetDifference(&t,d,s,ns,ps);
1203 }
1204 ///////////////////////////////////////////////////////////////////////////
1205 Double_t AliTimestamp::GetDifference(AliTimestamp* t,TString u,Int_t mode)
1206 {
1207 // Provide the time difference w.r.t the AliTimestamp specified on the input
1208 // argument in the units as specified by the TString argument.
1209 // A positive return value means that the AliTimestamp specified on the input
1210 // argument occurred later, whereas a negative return value indicates an
1211 // earlier occurence. 
1212 //  
1213 // The units may be specified as :
1214 // u = "d"  ==> Time difference returned as (fractional) day count
1215 //     "s"  ==> Time difference returned as (fractional) second count
1216 //     "ns" ==> Time difference returned as (fractional) nanosecond count
1217 //     "ps" ==> Time difference returned as picosecond count
1218 //
1219 // It may be clear that for a time difference of several days, the picosecond
1220 // and even the nanosecond accuracy may be lost.
1221 // To cope with this, the "mode" argument has been introduced to allow 
1222 // timestamp comparison on only the specified units.
1223 //
1224 // The following operation modes are supported :
1225 // mode = 1 : Full time difference is returned in specified units
1226 //        2 : Time difference is returned in specified units by
1227 //            neglecting the elapsed time for the larger units than the
1228 //            ones specified.
1229 //        3 : Time difference is returned in specified units by only
1230 //            comparing the timestamps on the level of the specified units.
1231 //
1232 // Example :
1233 // ---------
1234 // AliTimestamp t1; // Corresponding to days=3, secs=501, ns=31, ps=7 
1235 // AliTimestamp t2; // Corresponding to days=5, secs=535, ns=12, ps=15
1236 //
1237 // The statement : Double_t val=t1.GetDifference(t2,....)
1238 // would return the following values :
1239 // val=(2*24*3600)+34-(19*1e-9)+(8*1e-12) for u="s" and mode=1
1240 // val=34-(19*1e-9)+(8*1e-12)             for u="s" and mode=2
1241 // val=34                                 for u="s" and mode=3
1242 // val=-19                                for u="ns" and mode=3
1243 //
1244 // The default is mode=1.
1245
1246  if (!t || mode<1 || mode>3) return 0;
1247
1248  Double_t dt=0;
1249
1250  // Ensure updated Julian parameters for this AliTimestamp instance 
1251  if (fCalcs != GetSec() || fCalcns != GetNanoSec()) FillJulian();
1252
1253  Int_t dd=0;
1254  Int_t ds=0;
1255  Int_t dns=0;
1256  Int_t dps=0;
1257
1258  // Use Get functions to ensure updated Julian parameters. 
1259  t->GetMJD(dd,ds,dns);
1260  dps=t->GetPs();
1261
1262  dd-=fMJD;
1263  ds-=fJsec;
1264  dns-=fJns;
1265  dps-=fJps;
1266
1267  // Time difference for the specified units only
1268  if (mode==3)
1269  {
1270   if (u=="d") dt=dd;
1271   if (u=="s") dt=ds;
1272   if (u=="ns") dt=dns;
1273   if (u=="ps") dt=dps;
1274   return dt;
1275  }
1276
1277  // Suppress elapsed time for the larger units than specified
1278  if (mode==2)
1279  {
1280   if (u=="s") dd=0;
1281   if (u=="ns")
1282   {
1283    dd=0;
1284    ds=0;
1285   }
1286   if (u=="ps")
1287   {
1288    dd=0;
1289    ds=0;
1290    dns=0;
1291   }
1292  }
1293
1294  // Compute the time difference as requested 
1295  if (u=="s" || u=="d")
1296  {
1297   // The time difference in (fractional) seconds
1298   dt=double(dd*24*3600+ds)+(double(dns)*1e-9)+(double(dps)*1e-12);
1299   if (u=="d") dt=dt/double(24*3600);
1300  }
1301  if (u=="ns") dt=(double(dd*24*3600+ds)*1e9)+double(dns)+(double(dps)*1e-3);
1302  if (u=="ps") dt=(double(dd*24*3600+ds)*1e12)+(double(dns)*1e3)+double(dps);
1303
1304  return dt;
1305 }
1306 ///////////////////////////////////////////////////////////////////////////
1307 Double_t AliTimestamp::GetDifference(AliTimestamp& t,TString u,Int_t mode)
1308 {
1309 // Provide the time difference w.r.t the AliTimestamp specified on the input
1310 // argument in the units as specified by the TString argument.
1311 // A positive return value means that the AliTimestamp specified on the input
1312 // argument occurred later, whereas a negative return value indicates an
1313 // earlier occurence. 
1314 //  
1315 // The units may be specified as :
1316 // u = "d"  ==> Time difference returned as (fractional) day count
1317 //     "s"  ==> Time difference returned as (fractional) second count
1318 //     "ns" ==> Time difference returned as (fractional) nanosecond count
1319 //     "ps" ==> Time difference returned as picosecond count
1320 //
1321 // It may be clear that for a time difference of several days, the picosecond
1322 // and even the nanosecond accuracy may be lost.
1323 // To cope with this, the "mode" argument has been introduced to allow 
1324 // timestamp comparison on only the specified units.
1325 //
1326 // The following operation modes are supported :
1327 // mode = 1 : Full time difference is returned in specified units
1328 //        2 : Time difference is returned in specified units by
1329 //            neglecting the elapsed time for the larger units than the
1330 //            ones specified.
1331 //        3 : Time difference is returned in specified units by only
1332 //            comparing the timestamps on the level of the specified units.
1333 //
1334 // Example :
1335 // ---------
1336 // AliTimestamp t1; // Corresponding to days=3, secs=501, ns=31, ps=7 
1337 // AliTimestamp t2; // Corresponding to days=5, secs=535, ns=12, ps=15
1338 //
1339 // The statement : Double_t val=t1.GetDifference(t2,....)
1340 // would return the following values :
1341 // val=(2*24*3600)+34-(19*1e-9)+(8*1e-12) for u="s" and mode=1
1342 // val=34-(19*1e-9)+(8*1e-12)             for u="s" and mode=2
1343 // val=34                                 for u="s" and mode=3
1344 // val=-19                                for u="ns" and mode=3
1345 //
1346 // The default is mode=1.
1347
1348  return GetDifference(&t,u,mode);
1349 }
1350 ///////////////////////////////////////////////////////////////////////////
1351 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)
1352 {
1353 // Set the AliTimestamp parameters corresponding to the UT date and time
1354 // in the Gregorian calendar as specified by the input arguments.
1355 // This facility is exact upto picosecond precision and as such is
1356 // for scientific observations preferable above the corresponding
1357 // Set function(s) of TTimestamp.
1358 // The latter has a random spread in the sub-second part, which
1359 // might be of use in generating distinguishable timestamps while
1360 // still keeping second precision.
1361 //
1362 // The input arguments represent the following :
1363 // y  : year in UT (e.g. 1952, 2003 etc...)
1364 // m  : month in UT (1=jan  2=feb etc...)
1365 // d  : day in UT (1-31)
1366 // hh : elapsed hours in UT (0-23) 
1367 // mm : elapsed minutes in UT (0-59)
1368 // ss : elapsed seconds in UT (0-59)
1369 // ns : remaining fractional elapsed second of UT in nanosecond
1370 // ps : remaining fractional elapsed nanosecond of UT in picosecond
1371 //
1372 // Note : ns=0 and ps=0 are the default values.
1373 //
1374 // This facility first determines the elapsed days, seconds etc...
1375 // since the beginning of the specified UT year on bais of the
1376 // input arguments. Subsequently it invokes the SetUT memberfunction
1377 // for the elapsed timespan.
1378 // As such this facility is valid for all AD dates in the Gregorian
1379 // calendar with picosecond precision.
1380
1381  Int_t day=GetDayOfYear(d,m,y);
1382  Int_t secs=hh*3600+mm*60+ss;
1383  SetUT(y,day-1,secs,ns,ps);
1384 }
1385 ///////////////////////////////////////////////////////////////////////////
1386 void AliTimestamp::SetUT(Int_t y,Int_t d,Int_t s,Int_t ns,Int_t ps)
1387 {
1388 // Set the AliTimestamp parameters corresponding to the specified elapsed
1389 // timespan since the beginning of the new UT year.
1390 // This facility is exact upto picosecond precision and as such is
1391 // for scientific observations preferable above the corresponding
1392 // Set function(s) of TTimestamp.
1393 // The latter has a random spread in the sub-second part, which
1394 // might be of use in generating distinguishable timestamps while
1395 // still keeping second precision.
1396 //
1397 // The UT year and elapsed time span is entered via the following input arguments :
1398 //
1399 // y  : year in UT (e.g. 1952, 2003 etc...)
1400 // d  : elapsed number of days 
1401 // s  : (remaining) elapsed number of seconds
1402 // ns : (remaining) elapsed number of nanoseconds
1403 // ps : (remaining) elapsed number of picoseconds
1404 //
1405 // The specified d, s, ns and ps values will be used in an additive
1406 // way to determine the elapsed timespan.
1407 // So, specification of d=1, s=100, ns=0, ps=0 will result in the
1408 // same elapsed time span as d=0, s=24*3600+100, ns=0, ps=0.
1409 // However, by making use of the latter the user should take care
1410 // of possible integer overflow problems in the input arguments,
1411 // which obviously will provide incorrect results. 
1412 //
1413 // Note : ns=0 and ps=0 are the default values.
1414 //
1415 // This facility first sets the (M)JD corresponding to the start (01-jan 00:00:00)
1416 // of the specified UT year following the recipe of R.W. Sinnott
1417 // Sky & Telescope 82, (aug. 1991) 183.
1418 // Subsequently the day and (sub)second parts are added to the AliTimestamp.
1419 // As such this facility is valid for all AD dates in the Gregorian calendar.
1420
1421  Double_t jd=GetJD(y,1,1,0,0,0,0);
1422  SetJD(jd);
1423
1424  Int_t mjd,sec,nsec;
1425  GetMJD(mjd,sec,nsec);
1426  SetMJD(mjd,0,0,0);
1427  Add(d,s,ns,ps);
1428 }
1429 ///////////////////////////////////////////////////////////////////////////
1430 void AliTimestamp::GetUT(Int_t& hh,Int_t& mm,Int_t& ss,Int_t& ns,Int_t& ps)
1431 {
1432 // Provide the corrresponding UT as hh:mm:ss:ns:ps.
1433 // This facility is based on the MJD, so the TTimeStamp limitations
1434 // do not apply here.
1435
1436  Int_t mjd,sec,nsec,psec;
1437
1438  GetMJD(mjd,sec,nsec);
1439  psec=GetPs();
1440
1441  hh=sec/3600;
1442  sec=sec%3600;
1443  mm=sec/60;
1444  ss=sec%60;
1445  ns=nsec;
1446  ps=psec;
1447 }
1448 ///////////////////////////////////////////////////////////////////////////
1449 Double_t AliTimestamp::GetUT()
1450 {
1451 // Provide the corrresponding UT in fractional hours.
1452 // This facility is based on the MJD, so the TTimeStamp limitations
1453 // do not apply here.
1454
1455  Int_t hh,mm,ss,ns,ps;
1456
1457  GetUT(hh,mm,ss,ns,ps);
1458
1459  Double_t ut=Convert(hh,mm,ss,ns,ps);
1460
1461  return ut;
1462 }
1463 ///////////////////////////////////////////////////////////////////////////
1464 void AliTimestamp::GetGST(Int_t& hh,Int_t& mm,Int_t& ss,Int_t& ns,Int_t& ps)
1465 {
1466 // Provide the corrresponding Greenwich Sideral Time (GST).
1467 // The algorithm used is the one described at p. 83 of the book
1468 // Astronomy Methods by Hale Bradt.
1469 // This facility is based on the MJD, so the TTimeStamp limitations
1470 // do not apply here.
1471
1472  Int_t mjd,sec,nsec,psec;
1473
1474  // The current UT based timestamp data
1475  GetMJD(mjd,sec,nsec);
1476  psec=fJps;
1477
1478  // The basis for the daily corrections in units of Julian centuries w.r.t. J2000.
1479  // Note : Epoch J2000 starts at 01-jan-2000 12:00:00 UT.
1480  Double_t tau=(GetJD()-2451545.)/36525.;
1481
1482  // Syncronise sidereal time with current timestamp
1483  AliTimestamp sid;
1484  sid.SetMJD(mjd,sec,nsec,psec);
1485
1486  // Add offset for GST start value defined as 06:41:50.54841 at 01-jan 00:00:00 UT
1487  sec=6*3600+41*60+50;
1488  nsec=548410000;
1489  psec=0;
1490  sid.Add(0,sec,nsec,psec);
1491
1492  // Daily correction for precession and polar motion 
1493  Double_t addsec=8640184.812866*tau+0.093104*pow(tau,2)-6.2e-6*pow(tau,3);
1494  sec=int(addsec);
1495  addsec-=double(sec);
1496  nsec=int(addsec*1.e9);
1497  addsec-=double(nsec)*1.e-9;
1498  psec=int(addsec*1.e12);
1499  sid.Add(0,sec,nsec,psec);
1500
1501  sid.GetMJD(mjd,sec,nsec);
1502  psec=sid.GetPs();
1503
1504  hh=sec/3600;
1505  sec=sec%3600;
1506  mm=sec/60;
1507  ss=sec%60;
1508  ns=nsec;
1509  ps=psec;
1510 }
1511 ///////////////////////////////////////////////////////////////////////////
1512 Double_t AliTimestamp::GetGST()
1513 {
1514 // Provide the corrresponding Greenwich Sideral Time (GMST)
1515 // in fractional hours.
1516 // This facility is based on the MJD, so the TTimeStamp limitations
1517 // do not apply here.
1518
1519  Int_t hh,mm,ss,ns,ps;
1520
1521  GetGST(hh,mm,ss,ns,ps);
1522
1523  Double_t gst=Convert(hh,mm,ss,ns,ps);
1524
1525  return gst;
1526 }
1527 ///////////////////////////////////////////////////////////////////////////
1528 Double_t AliTimestamp::GetJD(Double_t e,TString mode) const
1529 {
1530 // Provide the fractional Julian Date from epoch e.
1531 // The sort of epoch may be specified via the "mode" parameter.
1532 //
1533 // mode = "J" ==> Julian epoch
1534 //        "B" ==> Besselian epoch
1535 //
1536 // The default value is mode="J".
1537
1538  Double_t jd=0;
1539
1540  if (mode=="J" || mode=="j") jd=(e-2000.0)*365.25+2451545.0;
1541
1542  if (mode=="B" || mode=="b") jd=(e-1900.0)*365.242198781+2415020.31352;
1543
1544  return jd;
1545 }
1546 ///////////////////////////////////////////////////////////////////////////
1547 Double_t AliTimestamp::GetMJD(Double_t e,TString mode) const
1548 {
1549 // Provide the fractional Modified Julian Date from epoch e.
1550 // The sort of epoch may be specified via the "mode" parameter.
1551 //
1552 // mode = "J" ==> Julian epoch
1553 //        "B" ==> Besselian epoch
1554 //
1555 // The default value is mode="J".
1556
1557  Double_t mjd=GetJD(e,mode)-2400000.5;
1558
1559  return mjd;
1560 }
1561 ///////////////////////////////////////////////////////////////////////////
1562 Double_t AliTimestamp::GetTJD(Double_t e,TString mode) const
1563 {
1564 // Provide the fractional Truncated Julian Date from epoch e.
1565 // The sort of epoch may be specified via the "mode" parameter.
1566 //
1567 // mode = "J" ==> Julian epoch
1568 //        "B" ==> Besselian epoch
1569 //
1570 // The default value is mode="J".
1571
1572  Double_t tjd=GetJD(e,mode)-2440000.5;
1573
1574  return tjd;
1575 }
1576 ///////////////////////////////////////////////////////////////////////////