]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliTimestamp.cxx
17-may-2005 NvE Functionality of AliTimestamp extended w.r.t. treatment of time inter...
[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 year count since
39 // midnight (UT) on 01-jan at the start of the Gregorian year count.
40 // A year is defined to be 365.25 days, so the integer part of JE corresponds
41 // to the usual Gregorian year count.
42 // So, 01-jan-1965 00:00:00 UT corresponds to JE=1965.0
43 //
44 // Because of the fact that the Julian date indicators are all w.r.t. UT
45 // they provide an absolute timescale irrespective of timezone or daylight
46 // saving time (DST).
47 //
48 // This AliTimestamp facility allows for picosecond precision, in view
49 // of time of flight analyses for particle physics experiments.
50 // For normal date/time indication the standard nanosecond precision
51 // will in general be sufficient.
52 // Note that when the fractional JD, MJD and TJD counts are used instead
53 // of the integer (days,sec,ns) specification, the nanosecond precision
54 // may be lost due to computer accuracy w.r.t. floating point operations.
55 //
56 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
57 // which corresponds to JD=2440587.5 or the start of MJD=40587 or TJD=587.
58 // Using the corresponding MJD of this EPOCH allows construction of
59 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input (M/T)JD and time.
60 // Obviously this TTimeStamp implementation would prevent usage of values
61 // smaller than JD=2440587.5 or MJD=40587 or TJD=587.
62 // However, this AliTimestamp facility provides support for the full range
63 // of (M/T)JD values, but the setting of the corresponding TTimeStamp parameters
64 // is restricted to the values allowed by the TTimeStamp implementation.
65 // For these earlier (M/T)JD values, the standard TTimeStamp parameters will
66 // be set corresponding to the start of the TTimeStamp EPOCH.
67 // This implies that for these earlier (M/T)JD values the TTimeStamp parameters
68 // do not match the Julian parameters of AliTimestamp.
69 // As such the standard TTimeStamp parameters do not appear on the print output
70 // when invoking the Date() memberfunction for these earlier (M/T)JD values.  
71 //
72 // Examples :
73 // ==========
74 //
75 // Note : All TTimeStamp functionality is available as well.
76 //
77 // AliTimestamp t;
78 //
79 // t.Date();
80 // 
81 // // Retrieve Julian Date
82 // Int_t jd,jsec,jns;
83 // t.GetJD(jd,jsec,jns);
84 //
85 // // Retrieve fractional Truncated Julian Date
86 // Double_t tjd=t.GetTJD();
87 //
88 // // Retrieve fractional Julian Epoch
89 // Double_t je=t.GetJE();
90 //
91 // // Set to a specific Modified Julian Date
92 // Int_t mjd=50537;
93 // Int_t mjsec=1528;
94 // Int_t mjns=185643;
95 // t.SetMJD(mjd,mjsec,mjns);
96 //
97 // t.Date();
98 //
99 // // Time intervals for e.g. trigger or TOF analysis
100 // AliEvent evt;
101 // AliTimestamp hit((AliTimestamp)evt);
102 // hit.Add(0,0,2,173);
103 // Double_t dt=evt.GetDifference(hit,"ps");
104 // Int_t d,s,ns,ps;
105 // evt.GetDifference(hit,d,s,ns,ps);
106 //
107 // // Some practical conversion facilities
108 // // Note : They don't influence the actual date/time settings
109 // //        and as such can also be invoked as AliTimestamp::Convert(...) etc...
110 // Int_t y=1921;
111 // Int_t m=7;
112 // Int_t d=21;
113 // Int_t hh=15;
114 // Int_t mm=23;
115 // Int_t ss=47;
116 // Int_t ns=811743;
117 // Double_t jdate=t.GetJD(y,m,d,hh,mm,ss,ns);
118 //
119 // Int_t days,secs,nsecs;
120 // Double_t date=421.1949327;
121 // t.Convert(date,days,secs,nsecs);
122 //
123 // days=875;
124 // secs=23;
125 // nsecs=9118483;
126 // date=t.Convert(days,secs,nsecs);
127 //
128 // Double_t mjdate=40563.823744;
129 // Double_t epoch=t.GetJE(mjdate,"mjd");
130 //
131 //--- Author: Nick van Eijndhoven 28-jan-2005 Utrecht University.
132 //- Modified: NvE $Date$ Utrecht University.
133 ///////////////////////////////////////////////////////////////////////////
134
135 #include "AliTimestamp.h"
136 #include "Riostream.h"
137
138 ClassImp(AliTimestamp) // Class implementation to enable ROOT I/O
139  
140 AliTimestamp::AliTimestamp() : TTimeStamp()
141 {
142 // Default constructor
143 // Creation of an AliTimestamp object and initialisation of parameters.
144 // All attributes are initialised to the current date/time as specified
145 // in the docs of TTimeStamp.
146
147  FillJulian();
148  fJps=0;
149 }
150 ///////////////////////////////////////////////////////////////////////////
151 AliTimestamp::AliTimestamp(TTimeStamp& t) : TTimeStamp(t)
152 {
153 // Creation of an AliTimestamp object and initialisation of parameters.
154 // All attributes are initialised to the values of the input TTimeStamp.
155
156  FillJulian();
157  fJps=0;
158 }
159 ///////////////////////////////////////////////////////////////////////////
160 AliTimestamp::~AliTimestamp()
161 {
162 // Destructor to delete dynamically allocated memory.
163 }
164 ///////////////////////////////////////////////////////////////////////////
165 AliTimestamp::AliTimestamp(const AliTimestamp& t) : TTimeStamp(t)
166 {
167 // Copy constructor
168
169  fMJD=t.fMJD;
170  fJsec=t.fJsec;
171  fJns=t.fJns;
172  fJps=t.fJps;
173  fCalcs=t.fCalcs;
174  fCalcns=t.fCalcns;
175 }
176 ///////////////////////////////////////////////////////////////////////////
177 void AliTimestamp::Date(Int_t mode)
178 {
179 // Print date/time info.
180 //
181 // mode = 1 ==> Only the TTimeStamp yy-mm-dd hh:mm:ss:ns info is printed
182 //        2 ==> Only the Julian parameter info is printed
183 //        3 ==> Both the TTimeStamp and Julian parameter info is printed
184 //
185 // The default is mode=3.
186 //
187 // Note : In case the (M/T)JD falls outside the TTimeStamp range,
188 //        the TTimeStamp info will not be printed.
189
190   Int_t mjd,mjsec,mjns;
191   GetMJD(mjd,mjsec,mjns);
192
193  if ((mode==1 || mode==3) && mjd>=40587) cout << " " << AsString() << endl;
194  if (mode==2 || mode==3)
195  {
196   Int_t jd,jsec,jns;
197   GetJD(jd,jsec,jns);
198   Int_t tjd,tjsec,tjns;
199   GetTJD(tjd,tjsec,tjns);
200   cout << " Julian Epoch : " << setprecision(25) << GetJE() << endl;
201   cout << " JD : " << jd << " sec : " << jsec << " ns : " << jns << " ps : " << fJps
202        << " Fractional : " << setprecision(25) << GetJD() << endl;
203   cout << " MJD : " << mjd << "  sec : " << mjsec << " ns : " << mjns << " ps : " << fJps
204        << " Fractional : " << setprecision(25) << GetMJD() << endl;
205   cout << " TJD : " << tjd << "  sec : " << tjsec << " ns : " << tjns << " ps : " << fJps
206        << " Fractional : " << setprecision(25) << GetTJD() << endl;
207  }
208 }
209 ///////////////////////////////////////////////////////////////////////////
210 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
211 {
212 // Provide the (fractional) Julian Date (JD) corresponding to the UT date
213 // and time in the Gregorian calendar as specified by the input arguments.
214 //
215 // The input arguments represent the following :
216 // y  : year in UT (e.g. 1952, 2003 etc...)
217 // m  : month in UT (1=jan  2=feb etc...)
218 // d  : day in UT (1-31)
219 // hh : elapsed hours in UT (0-23) 
220 // mm : elapsed minutes in UT (0-59)
221 // ss : elapsed seconds in UT (0-59)
222 // ns : remaining fractional elapsed second of UT in nanosecond
223 //
224 // This algorithm is valid for all AD dates in the Gregorian calendar
225 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
226 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
227 //
228 // In case of invalid input, a value of -1 is returned.
229 //
230 // Note :
231 // ------
232 // This memberfunction only provides the JD corresponding to the
233 // UT input arguments. It does NOT set the corresponding Julian parameters
234 // for the current AliTimestamp instance.
235 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
236 // To set the Julian parameters for the current AliTimestamp instance,
237 // please use the corresponding SET() memberfunctions of either AliTimestamp
238 // or TTimeStamp. 
239
240  if (y<0 || m<1 || m>12 || d<1 || d>31) return -1;
241  if (hh<0 || hh>23 || mm<0 || mm>59 || ss<0 || ss>59 || ns<0 || ns>1e9) return -1;
242
243  // The UT daytime in fractional hours
244  Double_t ut=double(hh)+double(mm)/60.+(double(ss)+double(ns)*1.e-9)/3600.;
245
246  Double_t JD=0;
247  
248  JD=367*y-int(7*(y+int((m+9)/12))/4)
249     -int(3*(int((y+(m-9)/7)/100)+1)/4)
250     +int(275*m/9)+d+1721028.5+ut/24.;
251
252  return JD;
253 }
254 ///////////////////////////////////////////////////////////////////////////
255 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
256 {
257 // Provide the (fractional) Modified Julian Date corresponding to the UT
258 // date and time in the Gregorian calendar as specified by the input arguments.
259 //
260 // The input arguments represent the following :
261 // y  : year in UT (e.g. 1952, 2003 etc...)
262 // m  : month in UT (1=jan  2=feb etc...)
263 // d  : day in UT (1-31)
264 // hh : elapsed hours in UT (0-23) 
265 // mm : elapsed minutes in UT (0-59)
266 // ss : elapsed seconds in UT (0-59)
267 // ns : remaining fractional elapsed second of UT in nanosecond
268 //
269 // This algorithm is valid for all AD dates in the Gregorian calendar
270 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
271 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
272 //
273 // In case of invalid input, a value of -1 is returned.
274 //
275 // Note :
276 // ------
277 // This memberfunction only provides the MJD corresponding to the
278 // UT input arguments. It does NOT set the corresponding Julian parameters
279 // for the current AliTimestamp instance.
280 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
281 // To set the Julian parameters for the current AliTimestamp instance,
282 // please use the corresponding SET() memberfunctions of either AliTimestamp
283 // or TTimeStamp.
284
285  Double_t JD=GetJD(y,m,d,hh,mm,ss,ns);
286
287  if (JD<0) return JD;
288
289  Double_t MJD=JD-2400000.5;
290
291  return MJD; 
292
293 ///////////////////////////////////////////////////////////////////////////
294 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
295 {
296 // Provide the (fractional) Truncated Julian Date corresponding to the UT
297 // date and time in the Gregorian calendar as specified by the input arguments.
298 //
299 // The input arguments represent the following :
300 // y  : year in UT (e.g. 1952, 2003 etc...)
301 // m  : month in UT (1=jan  2=feb etc...)
302 // d  : day in UT (1-31)
303 // hh : elapsed hours in UT (0-23) 
304 // mm : elapsed minutes in UT (0-59)
305 // ss : elapsed seconds in UT (0-59)
306 // ns : remaining fractional elapsed second of UT in nanosecond
307 //
308 // This algorithm is valid for all AD dates in the Gregorian calendar
309 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
310 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
311 //
312 // In case of invalid input, a value of -1 is returned.
313 //
314 // Note :
315 // ------
316 // This memberfunction only provides the TJD corresponding to the
317 // UT input arguments. It does NOT set the corresponding Julian parameters
318 // for the current AliTimestamp instance.
319 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
320 // To set the Julian parameters for the current AliTimestamp instance,
321 // please use the corresponding SET() memberfunctions of either AliTimestamp
322 // or TTimeStamp.
323
324  Double_t JD=GetJD(y,m,d,hh,mm,ss,ns);
325
326  if (JD<0) return JD;
327
328  Double_t TJD=JD-2440000.5;
329
330  return TJD; 
331
332 ///////////////////////////////////////////////////////////////////////////
333 Double_t AliTimestamp::GetJE(Double_t date,TString mode) const
334 {
335 // Provide the Julian Epoch (JE) corresponding to the specified date.
336 // The argument "mode" indicates the type of the argument "date".
337 //
338 // Available modes are :
339 // mode = "jd"  ==> date represents the Julian Date
340 //      = "mjd" ==> date represents the Modified Julian Date
341 //      = "tjd" ==> date represents the Truncated Julian Date
342 //
343 // The default is mode="jd".
344 //
345 // In case of invalid input, a value of -99999 is returned.
346 //
347 // Note :
348 // ------
349 // This memberfunction only provides the JE corresponding to the
350 // input arguments. It does NOT set the corresponding Julian parameters
351 // for the current AliTimestamp instance.
352 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
353 // To set the Julian parameters for the current AliTimestamp instance,
354 // please use the corresponding SET() memberfunctions of either AliTimestamp
355 // or TTimeStamp.
356
357  if ((mode != "jd") && (mode != "mjd") && (mode != "tjd")) return -99999;
358
359  Double_t jd=date;
360  if (mode=="mjd") jd=date+2400000.5;
361  if (mode=="tjd") jd=date+2440000.5;
362
363  Double_t je=2000.+(jd-2451545.)/365.25;
364
365  return je;
366 }
367 ///////////////////////////////////////////////////////////////////////////
368 void AliTimestamp::Convert(Double_t date,Int_t& days,Int_t& secs,Int_t& ns) const
369 {
370 // Convert date as fractional day count into integer days, secs and ns.
371 //
372 // Note : Due to computer accuracy the ns value may become inaccurate.
373 //
374 // The arguments represent the following :
375 // date : The input date as fractional day count
376 // days : Number of elapsed days
377 // secs : Remaining number of elapsed seconds
378 // ns   : Remaining fractional elapsed second in nanoseconds
379 //
380 // Note :
381 // ------
382 // This memberfunction only converts the input date into the corresponding
383 // integer parameters. It does NOT set the corresponding Julian parameters
384 // for the current AliTimestamp instance.
385 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
386 // To set the Julian parameters for the current AliTimestamp instance,
387 // please use the corresponding SET() memberfunctions of either AliTimestamp
388 // or TTimeStamp.
389  
390  days=int(date);
391  date=date-double(days);
392  Int_t daysecs=24*3600;
393  date=date*double(daysecs);
394  secs=int(date);
395  date=date-double(secs);
396  ns=int(date*1.e9);
397 }
398 ///////////////////////////////////////////////////////////////////////////
399 Double_t AliTimestamp::Convert(Int_t days,Int_t secs,Int_t ns) const
400 {
401 // Convert date in integer days, secs and ns into fractional day count. 
402 //
403 // Note : Due to computer accuracy the ns precision may be lost.
404 //
405 // The input arguments represent the following :
406 // days : Number of elapsed days
407 // secs : Remaining number of elapsed seconds
408 // ns   : Remaining fractional elapsed second in nanoseconds
409 //
410 // Note :
411 // ------
412 // This memberfunction only converts the input integer parameters into the
413 // corresponding fractional day count. It does NOT set the corresponding
414 // Julian parameters 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  Double_t frac=double(secs)+double(ns)*1.e-9;
421  Int_t daysecs=24*3600;
422  frac=frac/double(daysecs);
423  Double_t date=double(days)+frac;
424  return date;
425 }
426 ///////////////////////////////////////////////////////////////////////////
427 void AliTimestamp::FillJulian()
428 {
429 // Calculation and setting of the Julian date/time parameters corresponding
430 // to the current TTimeStamp date/time parameters.
431
432  UInt_t y,m,d,hh,mm,ss;
433
434  GetDate(kTRUE,0,&y,&m,&d);
435  GetTime(kTRUE,0,&hh,&mm,&ss);
436  Int_t ns=GetNanoSec();
437
438  Double_t mjd=GetMJD(y,m,d,hh,mm,ss,ns);
439
440  fMJD=int(mjd);
441  fJsec=GetSec()%(24*3600); // Daytime in elapsed seconds
442  fJns=ns;                  // Remaining fractional elapsed second in nanoseconds
443
444  // Store the TTimeStamp seconds and nanoseconds values
445  // for which this Julian calculation was performed.
446  fCalcs=GetSec();
447  fCalcns=GetNanoSec();
448 }
449 ///////////////////////////////////////////////////////////////////////////
450 void AliTimestamp::GetMJD(Int_t& mjd,Int_t& sec, Int_t& ns)
451 {
452 // Provide the Modified Julian Date (MJD) and time corresponding to the
453 // currently stored AliTimestamp date/time parameters.
454 //
455 // The returned arguments represent the following :
456 // mjd : The modified Julian date.
457 // sec : The number of seconds elapsed within the MJD.
458 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
459
460  if (fCalcs != GetSec() || fCalcns != GetNanoSec()) FillJulian();
461
462  mjd=fMJD;
463  sec=fJsec;
464  ns=fJns;
465 }
466 ///////////////////////////////////////////////////////////////////////////
467 Double_t AliTimestamp::GetMJD()
468 {
469 // Provide the (fractional) Modified Julian Date (MJD) corresponding to the
470 // currently stored AliTimestamp date/time parameters.
471 //
472 // Due to computer accuracy the ns precision may be lost.
473 // It is advised to use the (mjd,sec,ns) getter instead.
474
475  Int_t mjd=0;
476  Int_t sec=0;
477  Int_t ns=0;
478  GetMJD(mjd,sec,ns);
479
480  Double_t date=Convert(mjd,sec,ns);
481
482  return date;
483 }
484 ///////////////////////////////////////////////////////////////////////////
485 void AliTimestamp::GetTJD(Int_t& tjd,Int_t& sec, Int_t& ns)
486 {
487 // Provide the Truncated Julian Date (TJD) and time corresponding to the
488 // currently stored AliTimestamp date/time parameters.
489 //
490 // The returned arguments represent the following :
491 // tjd : The modified Julian date.
492 // sec : The number of seconds elapsed within the MJD.
493 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
494
495  Int_t mjd=0;
496  GetMJD(mjd,sec,ns);
497
498  tjd=mjd-40000;
499 }
500 ///////////////////////////////////////////////////////////////////////////
501 Double_t AliTimestamp::GetTJD()
502 {
503 // Provide the (fractional) Truncated Julian Date (TJD) corresponding to the
504 // currently stored AliTimestamp date/time parameters.
505 //
506 // Due to computer accuracy the ns precision may be lost.
507 // It is advised to use the (mjd,sec,ns) getter instead.
508
509  Int_t tjd=0;
510  Int_t sec=0;
511  Int_t ns=0;
512  GetTJD(tjd,sec,ns);
513
514  Double_t date=Convert(tjd,sec,ns);
515
516  return date;
517 }
518 ///////////////////////////////////////////////////////////////////////////
519 void AliTimestamp::GetJD(Int_t& jd,Int_t& sec, Int_t& ns)
520 {
521 // Provide the Julian Date (JD) and time corresponding to the currently
522 // stored AliTimestamp date/time parameters.
523 //
524 // The returned arguments represent the following :
525 // jd  : The Julian date.
526 // sec : The number of seconds elapsed within the JD.
527 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
528
529  Int_t mjd=0;
530  GetMJD(mjd,sec,ns);
531
532  jd=mjd+2400000;
533  sec+=12*3600;
534  if (sec >= 24*3600)
535  {
536   sec-=24*3600;
537   jd+=1;
538  }
539 }
540 ///////////////////////////////////////////////////////////////////////////
541 Double_t AliTimestamp::GetJD()
542 {
543 // Provide the (fractional) Julian Date (JD) corresponding to the currently
544 // stored AliTimestamp date/time parameters.
545 //
546 // Due to computer accuracy the ns precision may be lost.
547 // It is advised to use the (jd,sec,ns) getter instead.
548
549  Int_t jd=0;
550  Int_t sec=0;
551  Int_t ns=0;
552  GetJD(jd,sec,ns);
553
554  Double_t date=Convert(jd,sec,ns);
555
556  return date;
557 }
558 ///////////////////////////////////////////////////////////////////////////
559 Double_t AliTimestamp::GetJE()
560 {
561 // Provide the Julian Epoch (JE) corresponding to the currently stored
562 // AliTimestamp date/time parameters.
563
564  Double_t jd=GetJD();
565  Double_t je=GetJE(jd);
566  return je;
567 }
568 ///////////////////////////////////////////////////////////////////////////
569 void AliTimestamp::SetMJD(Int_t mjd,Int_t sec,Int_t ns,Int_t ps)
570 {
571 // Set the Modified Julian Date (MJD) and time and update the TTimeStamp
572 // parameters accordingly (if possible).
573 //
574 // Note :
575 // ------
576 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
577 // which corresponds to the start of MJD=40587.
578 // Using the corresponding MJD of this EPOCH allows construction of
579 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
580 // Obviously this TTimeStamp implementation would prevent usage of MJD values
581 // smaller than 40587.
582 // However, this AliTimestamp facility provides support for the full range
583 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
584 // is restricted to the values allowed by the TTimeStamp implementation.
585 // For these earlier MJD values, the standard TTimeStamp parameters will
586 // be set corresponding to the start of the TTimeStamp EPOCH.  
587 // This implies that for these earlier MJD values the TTimeStamp parameters
588 // do not match the Julian parameters of AliTimestamp.  
589 //
590 // The input arguments represent the following :
591 // mjd : The modified Julian date.
592 // sec : The number of seconds elapsed within the MJD.
593 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
594 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the MJD.
595 //
596 // Note : ps=0 is the default value.
597
598  if (sec<0 || sec>=24*3600 || ns<0 || ns>=1e9 || ps<0 || ps>=1000)
599  {
600   cout << " *AliTimestamp::SetMJD* Invalid input."
601        << " sec : " << sec << " ns : " << ns << endl; 
602   return;
603  }
604
605  fMJD=mjd;
606  fJsec=sec;
607  fJns=ns;
608  fJps=ps;
609
610  Int_t epoch=40587;
611  
612  if (mjd<epoch)
613  {
614   Set(0,kFALSE,0,kFALSE);
615  }
616  else
617  {
618   // The elapsed time since start of EPOCH
619   Int_t days=mjd-epoch;
620   UInt_t secs=days*24*3600;
621   secs+=sec;
622   Set(secs,kFALSE,0,kFALSE);
623   Int_t date=GetDate();
624   Int_t time=GetTime();
625   Set(date,time,ns,kTRUE,0);
626  }
627
628  // Denote that the Julian and TTimeStamp parameters are synchronised,
629  // even in the case the MJD falls outside the TTimeStamp validity range.
630  // The latter still allows retrieval of Julian parameters for these
631  // earlier times.
632  fCalcs=GetSec();
633  fCalcns=GetNanoSec();
634 }
635 ///////////////////////////////////////////////////////////////////////////
636 void AliTimestamp::SetMJD(Double_t mjd)
637 {
638 // Set the Modified Julian Date (MJD) and time and update the TTimeStamp
639 // parameters accordingly (if possible).
640 //
641 // Note :
642 // ------
643 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
644 // which corresponds to the start of MJD=40587.
645 // Using the corresponding MJD of this EPOCH allows construction of
646 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
647 // Obviously this TTimeStamp implementation would prevent usage of MJD values
648 // smaller than 40587.
649 // However, this AliTimestamp facility provides support for the full range
650 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
651 // is restricted to the values allowed by the TTimeStamp implementation.
652 // For these earlier MJD values, the standard TTimeStamp parameters will
653 // be set corresponding to the start of the TTimeStamp EPOCH.  
654 // This implies that for these earlier MJD values the TTimeStamp parameters
655 // do not match the Julian parameters of AliTimestamp.  
656 //
657 // Due to computer accuracy the ns precision may be lost.
658 // It is advised to use the (mjd,sec,ns) setting instead.
659 //
660 // The input argument represents the following :
661 // mjd : The modified Julian date as fractional day count.
662
663  Int_t days=0;
664  Int_t secs=0;
665  Int_t ns=0;
666  Convert(mjd,days,secs,ns);
667  SetMJD(days,secs,ns);
668 }
669 ///////////////////////////////////////////////////////////////////////////
670 void AliTimestamp::SetJD(Int_t jd,Int_t sec,Int_t ns,Int_t ps)
671 {
672 // Set the Julian Date (JD) and time and update the TTimeStamp
673 // parameters accordingly (if possible).
674 //
675 // Note :
676 // ------
677 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
678 // which corresponds to JD=2440587.5 or the start of MJD=40587.
679 // Using the corresponding MJD of this EPOCH allows construction of
680 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
681 // Obviously this TTimeStamp implementation would prevent usage of values
682 // smaller than JD=2440587.5.
683 // However, this AliTimestamp facility provides support for the full range
684 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
685 // is restricted to the values allowed by the TTimeStamp implementation.
686 // For these earlier JD values, the standard TTimeStamp parameters will
687 // be set corresponding to the start of the TTimeStamp EPOCH.  
688 // This implies that for these earlier (M)JD values the TTimeStamp parameters
689 // do not match the Julian parameters of AliTimestamp.  
690 //
691 // The input arguments represent the following :
692 // jd  : The Julian date.
693 // sec : The number of seconds elapsed within the JD.
694 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
695 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the JD.
696 //
697 // Note : ps=0 is the default value.
698
699  Int_t mjd=jd-2400000;
700  sec-=12*3600;
701  if (sec<0)
702  {
703   sec+=24*3600;
704   mjd-=1;
705  }
706
707  SetMJD(mjd,sec,ns,ps);
708 }
709 ///////////////////////////////////////////////////////////////////////////
710 void AliTimestamp::SetJD(Double_t jd)
711 {
712 // Set the Julian Date (JD) and time and update the TTimeStamp
713 // parameters accordingly (if possible).
714 //
715 // Note :
716 // ------
717 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
718 // which corresponds to JD=2440587.5 or the start of MJD=40587.
719 // Using the corresponding MJD of this EPOCH allows construction of
720 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
721 // Obviously this TTimeStamp implementation would prevent usage of values
722 // smaller than JD=2440587.5.
723 // However, this AliTimestamp facility provides support for the full range
724 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
725 // is restricted to the values allowed by the TTimeStamp implementation.
726 // For these earlier JD values, the standard TTimeStamp parameters will
727 // be set corresponding to the start of the TTimeStamp EPOCH.  
728 // This implies that for these earlier (M)JD values the TTimeStamp parameters
729 // do not match the Julian parameters of AliTimestamp.  
730 //
731 // Due to computer accuracy the ns precision may be lost.
732 // It is advised to use the (jd,sec,ns) setting instead.
733 //
734 // The input argument represents the following :
735 // jd : The Julian date as fractional day count.
736
737  Int_t days=0;
738  Int_t secs=0;
739  Int_t ns=0;
740  Convert(jd,days,secs,ns);
741
742  SetJD(days,secs,ns);
743 }
744 ///////////////////////////////////////////////////////////////////////////
745 void AliTimestamp::SetTJD(Int_t tjd,Int_t sec,Int_t ns,Int_t ps)
746 {
747 // Set the Truncated Julian Date (TJD) and time and update the TTimeStamp
748 // parameters accordingly (if possible).
749 //
750 // Note :
751 // ------
752 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
753 // which corresponds to JD=2440587.5 or the start of TJD=587.
754 // Using the corresponding MJD of this EPOCH allows construction of
755 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
756 // Obviously this TTimeStamp implementation would prevent usage of values
757 // smaller than TJD=587.
758 // However, this AliTimestamp facility provides support for the full range
759 // of (T)JD values, but the setting of the corresponding TTimeStamp parameters
760 // is restricted to the values allowed by the TTimeStamp implementation.
761 // For these earlier JD values, the standard TTimeStamp parameters will
762 // be set corresponding to the start of the TTimeStamp EPOCH.  
763 // This implies that for these earlier (T)JD values the TTimeStamp parameters
764 // do not match the Julian parameters of AliTimestamp.  
765 //
766 // The input arguments represent the following :
767 // tjd : The Truncated Julian date.
768 // sec : The number of seconds elapsed within the JD.
769 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
770 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the JD.
771 //
772 // Note : ps=0 is the default value.
773
774  Int_t mjd=tjd+40000;
775
776  SetMJD(mjd,sec,ns);
777 }
778 ///////////////////////////////////////////////////////////////////////////
779 void AliTimestamp::SetTJD(Double_t tjd)
780 {
781 // Set the Truncated Julian Date (TJD) and time and update the TTimeStamp
782 // parameters accordingly (if possible).
783 //
784 // Note :
785 // ------
786 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
787 // which corresponds to JD=2440587.5 or the start of TJD=587.
788 // Using the corresponding MJD of this EPOCH allows construction of
789 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
790 // Obviously this TTimeStamp implementation would prevent usage of values
791 // smaller than TJD=587.
792 // However, this AliTimestamp facility provides support for the full range
793 // of (T)JD values, but the setting of the corresponding TTimeStamp parameters
794 // is restricted to the values allowed by the TTimeStamp implementation.
795 // For these earlier JD values, the standard TTimeStamp parameters will
796 // be set corresponding to the start of the TTimeStamp EPOCH.  
797 // This implies that for these earlier (T)JD values the TTimeStamp parameters
798 // do not match the Julian parameters of AliTimestamp.  
799 //
800 // Due to computer accuracy the ns precision may be lost.
801 // It is advised to use the (jd,sec,ns) setting instead.
802 //
803 // The input argument represents the following :
804 // tjd : The Truncated Julian date as fractional day count.
805
806  Int_t days=0;
807  Int_t secs=0;
808  Int_t ns=0;
809  Convert(tjd,days,secs,ns);
810
811  SetTJD(days,secs,ns);
812 }
813 ///////////////////////////////////////////////////////////////////////////
814 void AliTimestamp::SetNs(Int_t ns)
815 {
816 // Set the remaining fractional number of seconds in nanosecond precision.
817 // Notes :
818 // -------
819 // 1) The allowed range for the argument "ns" is [0,99999999].
820 //    Outside that range no action is performed.
821 // 2) The ns fraction can also be entered directly via SetMJD() etc...
822 // 3) For additional accuracy see SetPs().
823
824  if (ns>=0 && ns<=99999999) fJns=ns; 
825 }
826 ///////////////////////////////////////////////////////////////////////////
827 Int_t AliTimestamp::GetNs() const
828 {
829 // Provide the remaining fractional number of seconds in nanosecond precision.
830 // This function allows trigger/timing analysis for (astro)particle physics
831 // experiments.
832 // Note : For additional accuracy see also GetPs().
833
834  return fJns; 
835 }
836 ///////////////////////////////////////////////////////////////////////////
837 void AliTimestamp::SetPs(Int_t ps)
838 {
839 // Set the remaining fractional number of nanoseconds in picoseconds.
840 // Notes :
841 // -------
842 // 1) The allowed range for the argument "ps" is [0,999].
843 //    Outside that range no action is performed.
844 // 2) The ps fraction can also be entered directly via SetMJD() etc...
845
846  if (ps>=0 && ps<=999) fJps=ps; 
847 }
848 ///////////////////////////////////////////////////////////////////////////
849 Int_t AliTimestamp::GetPs() const
850 {
851 // Provide remaining fractional number of nanoseconds in picoseconds.
852 // This function allows time of flight analysis for particle physics
853 // experiments.
854
855  return fJps; 
856 }
857 ///////////////////////////////////////////////////////////////////////////
858 void AliTimestamp::Add(Int_t d,Int_t s,Int_t ns,Int_t ps)
859 {
860 // Add (or subtract) a certain time difference to the current timestamp.
861 //
862 // The time difference is entered via the following output arguments :
863 // d  : elapsed number of days
864 // s  : remaining elapsed number of seconds
865 // ns : remaining elapsed number of nanoseconds
866 // ps : remaining elapsed number of picoseconds
867 //
868 // Note : ps=0 is the default value.
869
870  Int_t days=fMJD;
871  Int_t secs=fJsec;
872  Int_t nsec=fJns;
873  Int_t psec=fJps;
874
875  psec+=ps;
876  if (psec<0)
877  {
878   nsec-=1;
879   psec+=1000;
880  }
881  if (psec>999)
882  {
883   nsec+=1;
884   psec-=1000;
885  }
886
887  nsec+=ns;
888  if (nsec<0)
889  {
890   secs-=1;
891   nsec+=1000000000;
892  }
893  if (nsec>999999999)
894  {
895   secs+=1;
896   nsec-=1000000000;
897  }
898
899  secs+=s;
900  if (secs<0)
901  {
902   days-=1;
903   secs+=24*3600;
904  }
905  if (secs>=24*3600)
906  {
907   days+=1;
908   secs-=24*3600;
909  }
910
911  days+=d;
912
913  fMJD=days;
914  fJsec=secs;
915  fJns=nsec;
916  fJps=psec;
917 }
918 ///////////////////////////////////////////////////////////////////////////
919 Int_t AliTimestamp::GetDifference(AliTimestamp& t,Int_t& d,Int_t& s,Int_t& ns,Int_t& ps) const
920 {
921 // Provide the time difference w.r.t the AliTimestamp specified on the input.
922 // This memberfunction supports both very small (i.e. time of flight analysis
923 // for particle physics experiments) and very long (i.e. investigation of
924 // astrophysical phenomena) timescales.
925 //
926 // The time difference is returned via the following output arguments :
927 // d  : elapsed number of days
928 // s  : remaining elapsed number of seconds
929 // ns : remaining elapsed number of nanoseconds
930 // ps : remaining elapsed number of picoseconds
931 //
932 // Note :
933 // ------
934 // The calculated time difference is the absolute value of the time interval.
935 // This implies that the values of d, s, ns and ps are always positive or zero.
936 //
937 // The integer return argument indicates whether the AliTimestamp specified
938 // on the input argument occurred earlier (-1), simultaneously (0) or later (1).
939
940  d=t.fMJD-fMJD;
941  s=t.fJsec-fJsec;
942  ns=t.fJns-fJns;
943  ps=t.fJps-fJps;
944
945  if (!d && !s && !ns && !ps) return 0;
946
947  Int_t sign=0;
948
949  if (d>0) sign=1;
950  if (d<0) sign=-1;
951
952  if (!sign && s>0) sign=1;
953  if (!sign && s<0) sign=-1;
954
955  if (!sign && ns>0) sign=1; 
956  if (!sign && ns<0) sign=-1;
957
958  if (!sign && ps>0) sign=1; 
959  if (!sign && ps<0) sign=-1;
960
961  // In case the input stamp was earlier, take the reverse difference
962  // to simplify the algebra.
963  if (sign<0)
964  {
965   d=-d;
966   s=-s;
967   ns=-ns;
968   ps=-ps;
969  }
970
971  // Here we always have a positive time difference
972  // and can now unambiguously correct for other negative values.
973  if (ps<0)
974  {
975   ns-=1;
976   ps+=1000;
977  }
978
979  if (ns<0)
980  {
981   s-=1;
982   ns+=1000000000;
983  }
984
985  if (s<0)
986  {
987   d-=1;
988   s+=24*3600;
989  }
990
991  return sign;
992 }
993 ///////////////////////////////////////////////////////////////////////////
994 Double_t AliTimestamp::GetDifference(AliTimestamp& t,TString u,Int_t mode) const
995 {
996 // Provide the time difference w.r.t the AliTimestamp specified on the input
997 // argument in the units as specified by the TString argument.
998 // A positive return value means that the AliTimestamp specified on the input
999 // argument occurred later, whereas a negative return value indicates an
1000 // earlier occurence. 
1001 //  
1002 // The units may be specified as :
1003 // u = "d"  ==> Time difference returned as (fractional) day count
1004 //     "s"  ==> Time difference returned as (fractional) second count
1005 //     "ns" ==> Time difference returned as (fractional) nanosecond count
1006 //     "ps" ==> Time difference returned as picosecond count
1007 //
1008 // It may be clear that for a time difference of several days, the picosecond
1009 // and even the nanosecond accuracy may be lost.
1010 // To cope with this, the "mode" argument has been introduced to allow 
1011 // timestamp comparison on only the specified units.
1012 //
1013 // The following operation modes are supported :
1014 // mode = 1 : Full time difference is returned in specified units
1015 //        2 : Time difference is returned in specified units by
1016 //            neglecting the elapsed time for the larger units than the
1017 //            ones specified.
1018 //        3 : Time difference is returned in specified units by only
1019 //            comparing the timestamps on the level of the specified units.
1020 //
1021 // Example :
1022 // ---------
1023 // AliTimestamp t1; // Corresponding to days=3, secs=501, ns=31, ps=7 
1024 // AliTimestamp t2; // Corresponding to days=5, secs=535, ns=12, ps=15
1025 //
1026 // The statement : Double_t val=t1.GetDifference(t2,....)
1027 // would return the following values :
1028 // val=(2*24*3600)+34-(19*1e-9)+(8*1e-12) for u="s" and mode=1
1029 // val=34-(19*1e-9)+(8*1e-12)             for u="s" and mode=2
1030 // val=34                                 for u="s" and mode=3
1031 // val=-19                                for u="ns" and mode=3
1032 //
1033 // The default is mode=1.
1034
1035  if (mode<1 || mode>3) return 0;
1036
1037  Double_t dt=0;
1038
1039  Int_t dd=t.fMJD-fMJD;
1040  Int_t ds=t.fJsec-fJsec;
1041  Int_t dns=t.fJns-fJns;
1042  Int_t dps=t.fJps-fJps;
1043
1044  // Time difference for the specified units only
1045  if (mode==3)
1046  {
1047   if (u=="d") dt=dd;
1048   if (u=="s") dt=ds;
1049   if (u=="ns") dt=dns;
1050   if (u=="ps") dt=dps;
1051   return dt;
1052  }
1053
1054  // Suppress elapsed time for the larger units than specified
1055  if (mode==2)
1056  {
1057   if (u=="s") dd=0;
1058   if (u=="ns")
1059   {
1060    dd=0;
1061    ds=0;
1062   }
1063   if (u=="ps")
1064   {
1065    dd=0;
1066    ds=0;
1067    dns=0;
1068   }
1069  }
1070
1071  // Compute the time difference as requested 
1072  if (u=="s" || u=="d")
1073  {
1074   // The time difference in (fractional) seconds
1075   dt=double(dd*24*3600+ds)+(double(dns)*1e-9)+(double(dps)*1e-12);
1076   if (u=="d") dt=dt/double(24*3600);
1077  }
1078  if (u=="ns") dt=(double(dd*24*3600+ds)*1e9)+double(dns)+(double(dps)*1e-3);
1079  if (u=="ps") dt=(double(dd*24*3600+ds)*1e12)+(double(dns)*1e3)+double(dps);
1080
1081  return dt;
1082 }
1083 ///////////////////////////////////////////////////////////////////////////