10-may-2005 NvE Support for timestamps introduced in AliTrack and AliPosition.
[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 // // Some practical conversion facilities
100 // // Note : They don't influence the actual date/time settings
101 // //        and as such can also be invoked as AliTimestamp::Convert(...) etc...
102 // Int_t y=1921;
103 // Int_t m=7;
104 // Int_t d=21;
105 // Int_t hh=15;
106 // Int_t mm=23;
107 // Int_t ss=47;
108 // Int_t ns=811743;
109 // Double_t jdate=t.GetJD(y,m,d,hh,mm,ss,ns);
110 //
111 // Int_t days,secs,nsecs;
112 // Double_t date=421.1949327;
113 // t.Convert(date,days,secs,nsecs);
114 //
115 // days=875;
116 // secs=23;
117 // nsecs=9118483;
118 // date=t.Convert(days,secs,nsecs);
119 //
120 // Double_t mjdate=40563.823744;
121 // Double_t epoch=t.GetJE(mjdate,"mjd");
122 //
123 //--- Author: Nick van Eijndhoven 28-jan-2005 Utrecht University.
124 //- Modified: NvE $Date$ Utrecht University.
125 ///////////////////////////////////////////////////////////////////////////
126
127 #include "AliTimestamp.h"
128 #include "Riostream.h"
129
130 ClassImp(AliTimestamp) // Class implementation to enable ROOT I/O
131  
132 AliTimestamp::AliTimestamp() : TTimeStamp()
133 {
134 // Default constructor
135 // Creation of an AliTimestamp object and initialisation of parameters.
136 // All attributes are initialised to the current date/time as specified
137 // in the docs of TTimeStamp.
138
139  FillJulian();
140  fJps=0;
141 }
142 ///////////////////////////////////////////////////////////////////////////
143 AliTimestamp::AliTimestamp(TTimeStamp& t) : TTimeStamp(t)
144 {
145 // Creation of an AliTimestamp object and initialisation of parameters.
146 // All attributes are initialised to the values of the input TTimeStamp.
147
148  FillJulian();
149  fJps=0;
150 }
151 ///////////////////////////////////////////////////////////////////////////
152 AliTimestamp::~AliTimestamp()
153 {
154 // Destructor to delete dynamically allocated memory.
155 }
156 ///////////////////////////////////////////////////////////////////////////
157 AliTimestamp::AliTimestamp(const AliTimestamp& t) : TTimeStamp(t)
158 {
159 // Copy constructor
160
161  fMJD=t.fMJD;
162  fJsec=t.fJsec;
163  fJns=t.fJns;
164  fJps=t.fJps;
165  fCalcs=t.fCalcs;
166  fCalcns=t.fCalcns;
167 }
168 ///////////////////////////////////////////////////////////////////////////
169 void AliTimestamp::Date(Int_t mode)
170 {
171 // Print date/time info.
172 //
173 // mode = 1 ==> Only the TTimeStamp yy-mm-dd hh:mm:ss:ns info is printed
174 //        2 ==> Only the Julian parameter info is printed
175 //        3 ==> Both the TTimeStamp and Julian parameter info is printed
176 //
177 // The default is mode=3.
178 //
179 // Note : In case the (M/T)JD falls outside the TTimeStamp range,
180 //        the TTimeStamp info will not be printed.
181
182   Int_t mjd,mjsec,mjns;
183   GetMJD(mjd,mjsec,mjns);
184
185  if ((mode==1 || mode==3) && mjd>=40587) cout << " " << AsString() << endl;
186  if (mode==2 || mode==3)
187  {
188   Int_t jd,jsec,jns;
189   GetJD(jd,jsec,jns);
190   Int_t tjd,tjsec,tjns;
191   GetTJD(tjd,tjsec,tjns);
192   cout << " Julian Epoch : " << setprecision(25) << GetJE() << endl;
193   cout << " JD : " << jd << " sec : " << jsec << " ns : " << jns
194        << " Fractional : " << setprecision(25) << GetJD() << endl;
195   cout << " MJD : " << mjd << "  sec : " << mjsec << " ns : " << mjns
196        << " Fractional : " << setprecision(25) << GetMJD() << endl;
197   cout << " TJD : " << tjd << "  sec : " << tjsec << " ns : " << tjns
198        << " Fractional : " << setprecision(25) << GetTJD() << endl;
199  }
200 }
201 ///////////////////////////////////////////////////////////////////////////
202 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
203 {
204 // Provide the (fractional) Julian Date (JD) corresponding to the UT date
205 // and time in the Gregorian calendar as specified by the input arguments.
206 //
207 // The input arguments represent the following :
208 // y  : year in UT (e.g. 1952, 2003 etc...)
209 // m  : month in UT (1=jan  2=feb etc...)
210 // d  : day in UT (1-31)
211 // hh : elapsed hours in UT (0-23) 
212 // mm : elapsed minutes in UT (0-59)
213 // ss : elapsed seconds in UT (0-59)
214 // ns : remaining fractional elapsed second of UT in nanosecond
215 //
216 // This algorithm is valid for all AD dates in the Gregorian calendar
217 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
218 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
219 //
220 // In case of invalid input, a value of -1 is returned.
221 //
222 // Note :
223 // ------
224 // This memberfunction only provides the JD corresponding to the
225 // UT input arguments. It does NOT set the corresponding Julian parameters
226 // for the current AliTimestamp instance.
227 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
228 // To set the Julian parameters for the current AliTimestamp instance,
229 // please use the corresponding SET() memberfunctions of either AliTimestamp
230 // or TTimeStamp. 
231
232  if (y<0 || m<1 || m>12 || d<1 || d>31) return -1;
233  if (hh<0 || hh>23 || mm<0 || mm>59 || ss<0 || ss>59 || ns<0 || ns>1e9) return -1;
234
235  // The UT daytime in fractional hours
236  Double_t ut=double(hh)+double(mm)/60.+(double(ss)+double(ns)*1.e-9)/3600.;
237
238  Double_t JD=0;
239  
240  JD=367*y-int(7*(y+int((m+9)/12))/4)
241     -int(3*(int((y+(m-9)/7)/100)+1)/4)
242     +int(275*m/9)+d+1721028.5+ut/24.;
243
244  return JD;
245 }
246 ///////////////////////////////////////////////////////////////////////////
247 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
248 {
249 // Provide the (fractional) Modified Julian Date corresponding to the UT
250 // date and time in the Gregorian calendar as specified by the input arguments.
251 //
252 // The input arguments represent the following :
253 // y  : year in UT (e.g. 1952, 2003 etc...)
254 // m  : month in UT (1=jan  2=feb etc...)
255 // d  : day in UT (1-31)
256 // hh : elapsed hours in UT (0-23) 
257 // mm : elapsed minutes in UT (0-59)
258 // ss : elapsed seconds in UT (0-59)
259 // ns : remaining fractional elapsed second of UT in nanosecond
260 //
261 // This algorithm is valid for all AD dates in the Gregorian calendar
262 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
263 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
264 //
265 // In case of invalid input, a value of -1 is returned.
266 //
267 // Note :
268 // ------
269 // This memberfunction only provides the MJD corresponding to the
270 // UT input arguments. It does NOT set the corresponding Julian parameters
271 // for the current AliTimestamp instance.
272 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
273 // To set the Julian parameters for the current AliTimestamp instance,
274 // please use the corresponding SET() memberfunctions of either AliTimestamp
275 // or TTimeStamp.
276
277  Double_t JD=GetJD(y,m,d,hh,mm,ss,ns);
278
279  if (JD<0) return JD;
280
281  Double_t MJD=JD-2400000.5;
282
283  return MJD; 
284
285 ///////////////////////////////////////////////////////////////////////////
286 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
287 {
288 // Provide the (fractional) Truncated Julian Date corresponding to the UT
289 // date and time in the Gregorian calendar as specified by the input arguments.
290 //
291 // The input arguments represent the following :
292 // y  : year in UT (e.g. 1952, 2003 etc...)
293 // m  : month in UT (1=jan  2=feb etc...)
294 // d  : day in UT (1-31)
295 // hh : elapsed hours in UT (0-23) 
296 // mm : elapsed minutes in UT (0-59)
297 // ss : elapsed seconds in UT (0-59)
298 // ns : remaining fractional elapsed second of UT in nanosecond
299 //
300 // This algorithm is valid for all AD dates in the Gregorian calendar
301 // following the recipe of R.W. Sinnott Sky & Telescope 82, (aug. 1991) 183.
302 // See also http://scienceworld.wolfram.com/astronomy/JulianDate.html
303 //
304 // In case of invalid input, a value of -1 is returned.
305 //
306 // Note :
307 // ------
308 // This memberfunction only provides the TJD corresponding to the
309 // UT input arguments. It does NOT set the corresponding Julian parameters
310 // for the current AliTimestamp instance.
311 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
312 // To set the Julian parameters for the current AliTimestamp instance,
313 // please use the corresponding SET() memberfunctions of either AliTimestamp
314 // or TTimeStamp.
315
316  Double_t JD=GetJD(y,m,d,hh,mm,ss,ns);
317
318  if (JD<0) return JD;
319
320  Double_t TJD=JD-2440000.5;
321
322  return TJD; 
323
324 ///////////////////////////////////////////////////////////////////////////
325 Double_t AliTimestamp::GetJE(Double_t date,TString mode) const
326 {
327 // Provide the Julian Epoch (JE) corresponding to the specified date.
328 // The argument "mode" indicates the type of the argument "date".
329 //
330 // Available modes are :
331 // mode = "jd"  ==> date represents the Julian Date
332 //      = "mjd" ==> date represents the Modified Julian Date
333 //      = "tjd" ==> date represents the Truncated Julian Date
334 //
335 // The default is mode="jd".
336 //
337 // In case of invalid input, a value of -99999 is returned.
338 //
339 // Note :
340 // ------
341 // This memberfunction only provides the JE corresponding to the
342 // input arguments. It does NOT set the corresponding Julian parameters
343 // for the current AliTimestamp instance.
344 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
345 // To set the Julian parameters for the current AliTimestamp instance,
346 // please use the corresponding SET() memberfunctions of either AliTimestamp
347 // or TTimeStamp.
348
349  if ((mode != "jd") && (mode != "mjd") && (mode != "tjd")) return -99999;
350
351  Double_t jd=date;
352  if (mode=="mjd") jd=date+2400000.5;
353  if (mode=="tjd") jd=date+2440000.5;
354
355  Double_t je=2000.+(jd-2451545.)/365.25;
356
357  return je;
358 }
359 ///////////////////////////////////////////////////////////////////////////
360 void AliTimestamp::Convert(Double_t date,Int_t& days,Int_t& secs,Int_t& ns) const
361 {
362 // Convert date as fractional day count into integer days, secs and ns.
363 //
364 // Note : Due to computer accuracy the ns value may become inaccurate.
365 //
366 // The arguments represent the following :
367 // date : The input date as fractional day count
368 // days : Number of elapsed days
369 // secs : Remaining number of elapsed seconds
370 // ns   : Remaining fractional elapsed second in nanoseconds
371 //
372 // Note :
373 // ------
374 // This memberfunction only converts the input date into the corresponding
375 // integer parameters. It does NOT set the corresponding Julian parameters
376 // for the current AliTimestamp instance.
377 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
378 // To set the Julian parameters for the current AliTimestamp instance,
379 // please use the corresponding SET() memberfunctions of either AliTimestamp
380 // or TTimeStamp.
381  
382  days=int(date);
383  date=date-double(days);
384  Int_t daysecs=24*3600;
385  date=date*double(daysecs);
386  secs=int(date);
387  date=date-double(secs);
388  ns=int(date*1.e9);
389 }
390 ///////////////////////////////////////////////////////////////////////////
391 Double_t AliTimestamp::Convert(Int_t days,Int_t secs,Int_t ns) const
392 {
393 // Convert date in integer days, secs and ns into fractional day count. 
394 //
395 // Note : Due to computer accuracy the ns precision may be lost.
396 //
397 // The input arguments represent the following :
398 // days : Number of elapsed days
399 // secs : Remaining number of elapsed seconds
400 // ns   : Remaining fractional elapsed second in nanoseconds
401 //
402 // Note :
403 // ------
404 // This memberfunction only converts the input integer parameters into the
405 // corresponding fractional day count. It does NOT set the corresponding
406 // Julian parameters for the current AliTimestamp instance.
407 // As such the TTimeStamp limitations do NOT apply to this memberfunction.
408 // To set the Julian parameters for the current AliTimestamp instance,
409 // please use the corresponding SET() memberfunctions of either AliTimestamp
410 // or TTimeStamp.
411
412  Double_t frac=double(secs)+double(ns)*1.e-9;
413  Int_t daysecs=24*3600;
414  frac=frac/double(daysecs);
415  Double_t date=double(days)+frac;
416  return date;
417 }
418 ///////////////////////////////////////////////////////////////////////////
419 void AliTimestamp::FillJulian()
420 {
421 // Calculation and setting of the Julian date/time parameters corresponding
422 // to the current TTimeStamp date/time parameters.
423
424  UInt_t y,m,d,hh,mm,ss;
425
426  GetDate(kTRUE,0,&y,&m,&d);
427  GetTime(kTRUE,0,&hh,&mm,&ss);
428  Int_t ns=GetNanoSec();
429
430  Double_t mjd=GetMJD(y,m,d,hh,mm,ss,ns);
431
432  fMJD=int(mjd);
433  fJsec=GetSec()%(24*3600); // Daytime in elapsed seconds
434  fJns=ns;                  // Remaining fractional elapsed second in nanoseconds
435
436  // Store the TTimeStamp seconds and nanoseconds values
437  // for which this Julian calculation was performed.
438  fCalcs=GetSec();
439  fCalcns=GetNanoSec();
440 }
441 ///////////////////////////////////////////////////////////////////////////
442 void AliTimestamp::GetMJD(Int_t& mjd,Int_t& sec, Int_t& ns)
443 {
444 // Provide the Modified Julian Date (MJD) and time corresponding to the
445 // currently stored AliTimestamp date/time parameters.
446 //
447 // The returned arguments represent the following :
448 // mjd : The modified Julian date.
449 // sec : The number of seconds elapsed within the MJD.
450 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
451
452  if (fCalcs != GetSec() || fCalcns != GetNanoSec()) FillJulian();
453
454  mjd=fMJD;
455  sec=fJsec;
456  ns=fJns;
457 }
458 ///////////////////////////////////////////////////////////////////////////
459 Double_t AliTimestamp::GetMJD()
460 {
461 // Provide the (fractional) Modified Julian Date (MJD) corresponding to the
462 // currently stored AliTimestamp date/time parameters.
463 //
464 // Due to computer accuracy the ns precision may be lost.
465 // It is advised to use the (mjd,sec,ns) getter instead.
466
467  Int_t mjd=0;
468  Int_t sec=0;
469  Int_t ns=0;
470  GetMJD(mjd,sec,ns);
471
472  Double_t date=Convert(mjd,sec,ns);
473
474  return date;
475 }
476 ///////////////////////////////////////////////////////////////////////////
477 void AliTimestamp::GetTJD(Int_t& tjd,Int_t& sec, Int_t& ns)
478 {
479 // Provide the Truncated Julian Date (TJD) and time corresponding to the
480 // currently stored AliTimestamp date/time parameters.
481 //
482 // The returned arguments represent the following :
483 // tjd : The modified Julian date.
484 // sec : The number of seconds elapsed within the MJD.
485 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
486
487  Int_t mjd=0;
488  GetMJD(mjd,sec,ns);
489
490  tjd=mjd-40000;
491 }
492 ///////////////////////////////////////////////////////////////////////////
493 Double_t AliTimestamp::GetTJD()
494 {
495 // Provide the (fractional) Truncated Julian Date (TJD) corresponding to the
496 // currently stored AliTimestamp date/time parameters.
497 //
498 // Due to computer accuracy the ns precision may be lost.
499 // It is advised to use the (mjd,sec,ns) getter instead.
500
501  Int_t tjd=0;
502  Int_t sec=0;
503  Int_t ns=0;
504  GetTJD(tjd,sec,ns);
505
506  Double_t date=Convert(tjd,sec,ns);
507
508  return date;
509 }
510 ///////////////////////////////////////////////////////////////////////////
511 void AliTimestamp::GetJD(Int_t& jd,Int_t& sec, Int_t& ns)
512 {
513 // Provide the Julian Date (JD) and time corresponding to the currently
514 // stored AliTimestamp date/time parameters.
515 //
516 // The returned arguments represent the following :
517 // jd  : The Julian date.
518 // sec : The number of seconds elapsed within the JD.
519 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
520
521  Int_t mjd=0;
522  GetMJD(mjd,sec,ns);
523
524  jd=mjd+2400000;
525  sec+=12*3600;
526  if (sec >= 24*3600)
527  {
528   sec-=24*3600;
529   jd+=1;
530  }
531 }
532 ///////////////////////////////////////////////////////////////////////////
533 Double_t AliTimestamp::GetJD()
534 {
535 // Provide the (fractional) Julian Date (JD) corresponding to the currently
536 // stored AliTimestamp date/time parameters.
537 //
538 // Due to computer accuracy the ns precision may be lost.
539 // It is advised to use the (jd,sec,ns) getter instead.
540
541  Int_t jd=0;
542  Int_t sec=0;
543  Int_t ns=0;
544  GetJD(jd,sec,ns);
545
546  Double_t date=Convert(jd,sec,ns);
547
548  return date;
549 }
550 ///////////////////////////////////////////////////////////////////////////
551 Double_t AliTimestamp::GetJE()
552 {
553 // Provide the Julian Epoch (JE) corresponding to the currently stored
554 // AliTimestamp date/time parameters.
555
556  Double_t jd=GetJD();
557  Double_t je=GetJE(jd);
558  return je;
559 }
560 ///////////////////////////////////////////////////////////////////////////
561 void AliTimestamp::SetMJD(Int_t mjd,Int_t sec,Int_t ns,Int_t ps)
562 {
563 // Set the Modified Julian Date (MJD) and time and update the TTimeStamp
564 // parameters accordingly (if possible).
565 //
566 // Note :
567 // ------
568 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
569 // which corresponds to the start of MJD=40587.
570 // Using the corresponding MJD of this EPOCH allows construction of
571 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
572 // Obviously this TTimeStamp implementation would prevent usage of MJD values
573 // smaller than 40587.
574 // However, this AliTimestamp facility provides support for the full range
575 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
576 // is restricted to the values allowed by the TTimeStamp implementation.
577 // For these earlier MJD values, the standard TTimeStamp parameters will
578 // be set corresponding to the start of the TTimeStamp EPOCH.  
579 // This implies that for these earlier MJD values the TTimeStamp parameters
580 // do not match the Julian parameters of AliTimestamp.  
581 //
582 // The input arguments represent the following :
583 // mjd : The modified Julian date.
584 // sec : The number of seconds elapsed within the MJD.
585 // ns  : The remaining fractional number of seconds (in ns) elapsed within the MJD.
586 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the MJD.
587 //
588 // Note : ps=0 is the default value.
589
590  if (sec<0 || sec>=24*3600 || ns<0 || ns>=1e9 || ps<0 || ps>=1000)
591  {
592   cout << " *AliTimestamp::SetMJD* Invalid input."
593        << " sec : " << sec << " ns : " << ns << endl; 
594   return;
595  }
596
597  fMJD=mjd;
598  fJsec=sec;
599  fJns=ns;
600  fJps=ps;
601
602  Int_t epoch=40587;
603  
604  if (mjd<epoch)
605  {
606   Set(0,kFALSE,0,kFALSE);
607  }
608  else
609  {
610   // The elapsed time since start of EPOCH
611   Int_t days=mjd-epoch;
612   UInt_t secs=days*24*3600;
613   secs+=sec;
614   Set(secs,kFALSE,0,kFALSE);
615   Int_t date=GetDate();
616   Int_t time=GetTime();
617   Set(date,time,ns,kTRUE,0);
618  }
619
620  // Denote that the Julian and TTimeStamp parameters are synchronised,
621  // even in the case the MJD falls outside the TTimeStamp validity range.
622  // The latter still allows retrieval of Julian parameters for these
623  // earlier times.
624  fCalcs=GetSec();
625  fCalcns=GetNanoSec();
626 }
627 ///////////////////////////////////////////////////////////////////////////
628 void AliTimestamp::SetMJD(Double_t mjd)
629 {
630 // Set the Modified Julian Date (MJD) and time and update the TTimeStamp
631 // parameters accordingly (if possible).
632 //
633 // Note :
634 // ------
635 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
636 // which corresponds to the start of MJD=40587.
637 // Using the corresponding MJD of this EPOCH allows construction of
638 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
639 // Obviously this TTimeStamp implementation would prevent usage of MJD values
640 // smaller than 40587.
641 // However, this AliTimestamp facility provides support for the full range
642 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
643 // is restricted to the values allowed by the TTimeStamp implementation.
644 // For these earlier MJD values, the standard TTimeStamp parameters will
645 // be set corresponding to the start of the TTimeStamp EPOCH.  
646 // This implies that for these earlier MJD values the TTimeStamp parameters
647 // do not match the Julian parameters of AliTimestamp.  
648 //
649 // Due to computer accuracy the ns precision may be lost.
650 // It is advised to use the (mjd,sec,ns) setting instead.
651 //
652 // The input argument represents the following :
653 // mjd : The modified Julian date as fractional day count.
654
655  Int_t days=0;
656  Int_t secs=0;
657  Int_t ns=0;
658  Convert(mjd,days,secs,ns);
659  SetMJD(days,secs,ns);
660 }
661 ///////////////////////////////////////////////////////////////////////////
662 void AliTimestamp::SetJD(Int_t jd,Int_t sec,Int_t ns,Int_t ps)
663 {
664 // Set the Julian Date (JD) and time and update the TTimeStamp
665 // parameters accordingly (if possible).
666 //
667 // Note :
668 // ------
669 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
670 // which corresponds to JD=2440587.5 or the start of MJD=40587.
671 // Using the corresponding MJD of this EPOCH allows construction of
672 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
673 // Obviously this TTimeStamp implementation would prevent usage of values
674 // smaller than JD=2440587.5.
675 // However, this AliTimestamp facility provides support for the full range
676 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
677 // is restricted to the values allowed by the TTimeStamp implementation.
678 // For these earlier JD values, the standard TTimeStamp parameters will
679 // be set corresponding to the start of the TTimeStamp EPOCH.  
680 // This implies that for these earlier (M)JD values the TTimeStamp parameters
681 // do not match the Julian parameters of AliTimestamp.  
682 //
683 // The input arguments represent the following :
684 // jd  : The Julian date.
685 // sec : The number of seconds elapsed within the JD.
686 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
687 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the JD.
688 //
689 // Note : ps=0 is the default value.
690
691  Int_t mjd=jd-2400000;
692  sec-=12*3600;
693  if (sec<0)
694  {
695   sec+=24*3600;
696   mjd-=1;
697  }
698
699  SetMJD(mjd,sec,ns,ps);
700 }
701 ///////////////////////////////////////////////////////////////////////////
702 void AliTimestamp::SetJD(Double_t jd)
703 {
704 // Set the Julian Date (JD) and time and update the TTimeStamp
705 // parameters accordingly (if possible).
706 //
707 // Note :
708 // ------
709 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
710 // which corresponds to JD=2440587.5 or the start of MJD=40587.
711 // Using the corresponding MJD of this EPOCH allows construction of
712 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
713 // Obviously this TTimeStamp implementation would prevent usage of values
714 // smaller than JD=2440587.5.
715 // However, this AliTimestamp facility provides support for the full range
716 // of (M)JD values, but the setting of the corresponding TTimeStamp parameters
717 // is restricted to the values allowed by the TTimeStamp implementation.
718 // For these earlier JD values, the standard TTimeStamp parameters will
719 // be set corresponding to the start of the TTimeStamp EPOCH.  
720 // This implies that for these earlier (M)JD values the TTimeStamp parameters
721 // do not match the Julian parameters of AliTimestamp.  
722 //
723 // Due to computer accuracy the ns precision may be lost.
724 // It is advised to use the (jd,sec,ns) setting instead.
725 //
726 // The input argument represents the following :
727 // jd : The Julian date as fractional day count.
728
729  Int_t days=0;
730  Int_t secs=0;
731  Int_t ns=0;
732  Convert(jd,days,secs,ns);
733
734  SetJD(days,secs,ns);
735 }
736 ///////////////////////////////////////////////////////////////////////////
737 void AliTimestamp::SetTJD(Int_t tjd,Int_t sec,Int_t ns,Int_t ps)
738 {
739 // Set the Truncated Julian Date (TJD) and time and update the TTimeStamp
740 // parameters accordingly (if possible).
741 //
742 // Note :
743 // ------
744 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
745 // which corresponds to JD=2440587.5 or the start of TJD=587.
746 // Using the corresponding MJD of this EPOCH allows construction of
747 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
748 // Obviously this TTimeStamp implementation would prevent usage of values
749 // smaller than TJD=587.
750 // However, this AliTimestamp facility provides support for the full range
751 // of (T)JD values, but the setting of the corresponding TTimeStamp parameters
752 // is restricted to the values allowed by the TTimeStamp implementation.
753 // For these earlier JD values, the standard TTimeStamp parameters will
754 // be set corresponding to the start of the TTimeStamp EPOCH.  
755 // This implies that for these earlier (T)JD values the TTimeStamp parameters
756 // do not match the Julian parameters of AliTimestamp.  
757 //
758 // The input arguments represent the following :
759 // tjd : The Truncated Julian date.
760 // sec : The number of seconds elapsed within the JD.
761 // ns  : The remaining fractional number of seconds (in ns) elapsed within the JD.
762 // ps  : The remaining fractional number of nanoseconds (in ps) elapsed within the JD.
763 //
764 // Note : ps=0 is the default value.
765
766  Int_t mjd=tjd+40000;
767
768  SetMJD(mjd,sec,ns);
769 }
770 ///////////////////////////////////////////////////////////////////////////
771 void AliTimestamp::SetTJD(Double_t tjd)
772 {
773 // Set the Truncated Julian Date (TJD) and time and update the TTimeStamp
774 // parameters accordingly (if possible).
775 //
776 // Note :
777 // ------
778 // The TTimeStamp EPOCH starts at 01-jan-1970 00:00:00 UTC
779 // which corresponds to JD=2440587.5 or the start of TJD=587.
780 // Using the corresponding MJD of this EPOCH allows construction of
781 // the yy-mm-dd hh:mm:ss:ns TTimeStamp from a given input MJD and time.
782 // Obviously this TTimeStamp implementation would prevent usage of values
783 // smaller than TJD=587.
784 // However, this AliTimestamp facility provides support for the full range
785 // of (T)JD values, but the setting of the corresponding TTimeStamp parameters
786 // is restricted to the values allowed by the TTimeStamp implementation.
787 // For these earlier JD values, the standard TTimeStamp parameters will
788 // be set corresponding to the start of the TTimeStamp EPOCH.  
789 // This implies that for these earlier (T)JD values the TTimeStamp parameters
790 // do not match the Julian parameters of AliTimestamp.  
791 //
792 // Due to computer accuracy the ns precision may be lost.
793 // It is advised to use the (jd,sec,ns) setting instead.
794 //
795 // The input argument represents the following :
796 // tjd : The Truncated Julian date as fractional day count.
797
798  Int_t days=0;
799  Int_t secs=0;
800  Int_t ns=0;
801  Convert(tjd,days,secs,ns);
802
803  SetTJD(days,secs,ns);
804 }
805 ///////////////////////////////////////////////////////////////////////////
806 Int_t AliTimestamp::GetPicoSec() const
807 {
808 // Provide remaining fractional number of nanoseconds in picoseconds.
809 // This memberfunction supports time of flight analysis for particle physics
810 // experiments.
811
812  return fJps; 
813 }
814 ///////////////////////////////////////////////////////////////////////////
815 Int_t AliTimestamp::GetDifference(AliTimestamp& t,Int_t& d,Int_t& s,Int_t& ns,Int_t& ps) const
816 {
817 // Provide the time difference w.r.t the AliTimestamp specified on the input.
818 // This memberfunction supports both very small (i.e. time of flight analysis
819 // for particle physics experiments) and very long (i.e. investigation of
820 // astrophysical phenomena) timescales.
821 //
822 // The time difference is returned via the following output arguments :
823 // d  : elapsed number of days
824 // s  : remaining elapsed number of seconds
825 // ns : remaining elapsed number of nanoseconds
826 // ps : remaining elapsed number of picoseconds
827 //
828 // The integer return argument indicates whether the AliTimestamp specified
829 // on the input argument occurred earlier (-1), simultaneously (0) or later (1).
830
831  Int_t tmjd=0;
832  Int_t tsec=0;
833  Int_t tnsec=0;
834  t.GetMJD(tmjd,tsec,tnsec);
835  Int_t tpsec=t.GetPicoSec();
836
837  // Convert all stamps to seconds, nanoseconds and picoseconds
838  // to simplify the algebra.
839  tsec+=tmjd*24*3600;
840  Int_t sec=fJsec+fMJD*24*3600;
841
842  d=0;
843  s=tsec-sec;
844  ns=tnsec-fJns;
845  ps=tpsec-fJps;
846
847  if (!d && !s && !ns && !ps) return 0;
848
849  Int_t sign=0;
850
851  if (s>0) sign=1;
852  if (s<0) sign=-1;
853
854  if (!sign && ns>0) sign=1; 
855  if (!sign && ns<0) sign=-1;
856
857  if (!sign && ps>0) sign=1; 
858  if (!sign && ps<0) sign=-1;
859
860  // In case the input stamp was earlier, take the reverse difference
861  // to simplify the algebra.
862  if (sign<0)
863  {
864   s=-s;
865   ns=-ns;
866   ps=-ps;
867  }
868
869  // Here we always have a positive time difference
870  // and can now unambiguously correct for other negative values
871  // and determine the resulting daycount.
872  if (ps<0)
873  {
874   ns-=1;
875   ps+=1000;
876  }
877
878  if (ns<0)
879  {
880   s-=1;
881   ns+=1e9;
882  }
883
884  d=s/(24*3600);
885  s=s%(24*3600);
886
887  return sign;
888 }
889 ///////////////////////////////////////////////////////////////////////////