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