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