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