<commit_before>// @(#)root/base:$Id$
// Author: <NAME>   30/9/2001

/*************************************************************************
 * Copyright (C) 1995-2002, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/** \class TTimeStamp
\ingroup Base

The TTimeStamp encapsulates seconds and ns since EPOCH

This extends (and isolates) struct timespec
~~~ {.cpp}
   struct timespec
      {
         time_t   tv_sec;   // seconds
         long     tv_nsec;  // nanoseconds
      }
   time_t seconds is relative to Jan 1, 1970 00:00:00 UTC
~~~
No accounting of leap seconds is made.

Due to ROOT/CINT limitations TTimeStamp does not explicitly
hold a timespec struct; attempting to do so means the Streamer
must be hand written.  Instead we have chosen to simply contain
similar fields within the private area of this class.

NOTE: the use of time_t (and its default implementation as a 32 int)
      implies overflow conditions occurs somewhere around
      `Jan 18, 19:14:07, 2038`.
      If this experiment is still going when it becomes significant
      someone will have to deal with it.
*/

#include "TTimeStamp.h"
#include "TMath.h"
#include "TString.h"
#include "TError.h"
#include "Riostream.h"
#ifdef R__WIN32
#include "Windows4Root.h"
#else
#include <unistd.h>
#include <sys/time.h>
#endif
#include "TVirtualMutex.h"

ClassImp(TTimeStamp);


TVirtualMutex *gTimeMutex = 0; // local mutex

////////////////////////////////////////////////////////////////////////////////
/// Write time stamp to std::ostream.

std::ostream& operator<<(std::ostream& os, const TTimeStamp& ts)
{
   if (os.good()) {
      if (os.tie()) os.tie()->flush(); // instead of opfx
      os << ts.AsString("c");
   }
   // instead of os.osfx()
   if (os.flags() & std::ios::unitbuf) os.flush();
   return os;
}

////////////////////////////////////////////////////////////////////////////////
/// Read time stamp from TBuffer.

TBuffer &operator>>(TBuffer &buf, TTimeStamp &ts)
{
   ts.Streamer(buf);
   return buf;
}

////////////////////////////////////////////////////////////////////////////////
/// Write time stamp to TBuffer.

TBuffer &operator<<(TBuffer &buf, const TTimeStamp &ts)
{
   ((TTimeStamp&)ts).Streamer(buf);
   return buf;
}

////////////////////////////////////////////////////////////////////////////////
/// Default ctor. Create a TTimeStamp and set it to the current time
/// (as best possible). The nanosecond part is faked so that subsequent
/// calls simply add 1 to ensure that sequential calls are distinct
/// (and sortable).

TTimeStamp::TTimeStamp()
{
   Set();
}

////////////////////////////////////////////////////////////////////////////////
/// Create a TTimeStamp and set it to the specified year, month,
/// day, time, hour, minute, second and nanosec.
/// If !isUTC then it is assumed to be the standard local time zone.
///
/// If local time is PST then one can use
/// ~~~ {.cpp}
///    TTimeStamp(year,month,day,hour,min,sec,nsec,kFALSE,0);
/// ~~~
/// or
/// ~~~ {.cpp}
///    Int_t secOffset = 8*60*60;
///    TTimeStamp timeStamp(year,month,day,hour,min,sec,nsec,kTRUE,8*60*60);
/// ~~~

TTimeStamp::TTimeStamp(UInt_t year, UInt_t month,
                       UInt_t day,  UInt_t hour,
                       UInt_t min,  UInt_t sec,
                       UInt_t nsec,
                       Bool_t isUTC, Int_t secOffset)
{
   Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
}

////////////////////////////////////////////////////////////////////////////////
/// Create a TTimeStamp and set it to the specified date, time, nanosec.
/// If !isUTC then it is assumed to be the standard local time zone.
///
/// \warning Watch out! C++ overload resolution often chooses the constructor
/// `TTimeStamp(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate)`
/// instead of this one. Your best bet is to explicitly pass UInt_t values instead
/// of Int_t values. When calling with integer literals, pass for instance
/// ~~~ {.cpp}
/// TTimeStamp timeStamp(20150610u,80448u,0u)
/// ~~~
/// to disambiguate.

TTimeStamp::TTimeStamp(UInt_t date, UInt_t time,
                       UInt_t nsec,
                       Bool_t isUTC, Int_t secOffset)
{
   Set(date, time, nsec, isUTC, secOffset);
}

////////////////////////////////////////////////////////////////////////////////
/// Create a TTimeStamp and set it to tloc which must be a time_t value
/// returned by time(). This value is the number of seconds since the EPOCH
/// (i.e. 00:00:00 on Jan 1m 1970). If dosDate is true then the input
/// is a dosDate value.

TTimeStamp::TTimeStamp(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate)
{
   Set(tloc, isUTC, secOffset, dosDate);
}

////////////////////////////////////////////////////////////////////////////////
/// Return Greenwich mean sidereal time (GMST) in hour-angle. Return value
/// will always be between 0 and 24 (hours). Sidereal time is most accurately
/// calculated from UT1. If fSec and fNanoSec are in UTC (which they are by
/// default), the optional argument UT1Offset can be supplied (in
/// milliseconds). If UT1Offset is not supplied, conversion has maximum error
/// of 1s. If offset is supplied error can be reduced to us level. Values for
/// UT1Offset can be found in IERS Bulletin B:
/// ftp://ftp.iers.org/products/eop/bulletinb/format_2009/
/// The conversion to sidereal time used here is given by
/// Aoki et. al. Astron. Astrophys. 105, 359-362 (1982)
/// http://adsabs.harvard.edu/abs/1982A%26A...105..359A

Double_t TTimeStamp::AsGMST(Double_t UT1Offset) const
{
   Double_t D = (AsJulianDate() + UT1Offset/86400000.0) - 2451545.0;
   Double_t D_r = D - fmod(2.0*D+1.0, 2.0)/2.0;
   Double_t T = D_r/36525.0;
   Double_t sidereal = (24110.54841 + 8640184.812866*T + 0.093142*T*T
      - 0.0000062*T*T*T + (D - D_r)*86400.0*1.002737909350795)/3600.0;
   Double_t rval = fmod(sidereal, 24.0);
   return rval < 0 ? rval + 24.0 : rval;
}

////////////////////////////////////////////////////////////////////////////////
/// Return Greenwich apparent sidereal time (GAST) in hour-angle. Return
/// value will always be between 0 and 24 (hours). Sidereal time is most
/// accurately calculated from UT1. If fSec and fNanoSec are in UTC (which
/// they are by default), the optional argument UT1Offset can be supplied (in
/// milliseconds). If UT1Offset is not supplied, conversion has maximum error
/// of 1s. If offset is supplied error can be reduced to us level. Values for
/// UT1Offset can be found in IERS Bulletin B:
/// ftp://ftp.iers.org/products/eop/bulletinb/format_2009/
/// Equation of the equinoxes is given by USNO:
/// http://aa.usno.navy.mil/faq/docs/GAST.php

Double_t TTimeStamp::AsGAST(Double_t UT1Offset) const
{
   Double_t D = (AsJulianDate() + UT1Offset/86400000.0) - 2451545.0;
   Double_t epsilon = (23.4393 - 0.0000004*D)*TMath::Pi()/180.0;
   Double_t L = (280.47 + 0.98565*D)*TMath::Pi()/180.0;
   Double_t Omega = (125.04 - 0.052954*D)*TMath::Pi()/180.0;
   Double_t Deltapsi = -0.000319*TMath::Sin(Omega) - 0.000024*TMath::Sin(2.0*L);
   Double_t eqeq = Deltapsi*TMath::Cos(epsilon);
   Double_t rval = fmod(AsGMST(UT1Offset) + eqeq, 24.0);<commit_msg>Remove TMath dependencies from TTimestamp.cxx<commit_after>// @(#)root/base:$Id$
// Author: <NAME>   30/9/2001

/*************************************************************************
 * Copyright (C) 1995-2002, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/** \class TTimeStamp
\ingroup Base

The TTimeStamp encapsulates seconds and ns since EPOCH

This extends (and isolates) struct timespec
~~~ {.cpp}
   struct timespec
      {
         time_t   tv_sec;   // seconds
         long     tv_nsec;  // nanoseconds
      }
   time_t seconds is relative to Jan 1, 1970 00:00:00 UTC
~~~
No accounting of leap seconds is made.

Due to ROOT/CINT limitations TTimeStamp does not explicitly
hold a timespec struct; attempting to do so means the Streamer
must be hand written.  Instead we have chosen to simply contain
similar fields within the private area of this class.

NOTE: the use of time_t (and its default implementation as a 32 int)
      implies overflow conditions occurs somewhere around
      `Jan 18, 19:14:07, 2038`.
      If this experiment is still going when it becomes significant
      someone will have to deal with it.
*/

#include "TTimeStamp.h"
#include "TString.h"
#include "TError.h"
#include "Riostream.h"
#ifdef R__WIN32
#include "Windows4Root.h"
#else
#include <unistd.h>
#include <sys/time.h>
#endif
#include "TVirtualMutex.h"

ClassImp(TTimeStamp);


TVirtualMutex *gTimeMutex = 0; // local mutex

////////////////////////////////////////////////////////////////////////////////
/// Write time stamp to std::ostream.

std::ostream& operator<<(std::ostream& os, const TTimeStamp& ts)
{
   if (os.good()) {
      if (os.tie()) os.tie()->flush(); // instead of opfx
      os << ts.AsString("c");
   }
   // instead of os.osfx()
   if (os.flags() & std::ios::unitbuf) os.flush();
   return os;
}

////////////////////////////////////////////////////////////////////////////////
/// Read time stamp from TBuffer.

TBuffer &operator>>(TBuffer &buf, TTimeStamp &ts)
{
   ts.Streamer(buf);
   return buf;
}

////////////////////////////////////////////////////////////////////////////////
/// Write time stamp to TBuffer.

TBuffer &operator<<(TBuffer &buf, const TTimeStamp &ts)
{
   ((TTimeStamp&)ts).Streamer(buf);
   return buf;
}

////////////////////////////////////////////////////////////////////////////////
/// Default ctor. Create a TTimeStamp and set it to the current time
/// (as best possible). The nanosecond part is faked so that subsequent
/// calls simply add 1 to ensure that sequential calls are distinct
/// (and sortable).

TTimeStamp::TTimeStamp()
{
   Set();
}

////////////////////////////////////////////////////////////////////////////////
/// Create a TTimeStamp and set it to the specified year, month,
/// day, time, hour, minute, second and nanosec.
/// If !isUTC then it is assumed to be the standard local time zone.
///
/// If local time is PST then one can use
/// ~~~ {.cpp}
///    TTimeStamp(year,month,day,hour,min,sec,nsec,kFALSE,0);
/// ~~~
/// or
/// ~~~ {.cpp}
///    Int_t secOffset = 8*60*60;
///    TTimeStamp timeStamp(year,month,day,hour,min,sec,nsec,kTRUE,8*60*60);
/// ~~~

TTimeStamp::TTimeStamp(UInt_t year, UInt_t month,
                       UInt_t day,  UInt_t hour,
                       UInt_t min,  UInt_t sec,
                       UInt_t nsec,
                       Bool_t isUTC, Int_t secOffset)
{
   Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
}

////////////////////////////////////////////////////////////////////////////////
/// Create a TTimeStamp and set it to the specified date, time, nanosec.
/// If !isUTC then it is assumed to be the standard local time zone.
///
/// \warning Watch out! C++ overload resolution often chooses the constructor
/// `TTimeStamp(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate)`
/// instead of this one. Your best bet is to explicitly pass UInt_t values instead
/// of Int_t values. When calling with integer literals, pass for instance
/// ~~~ {.cpp}
/// TTimeStamp timeStamp(20150610u,80448u,0u)
/// ~~~
/// to disambiguate.

TTimeStamp::TTimeStamp(UInt_t date, UInt_t time,
                       UInt_t nsec,
                       Bool_t isUTC, Int_t secOffset)
{
   Set(date, time, nsec, isUTC, secOffset);
}

////////////////////////////////////////////////////////////////////////////////
/// Create a TTimeStamp and set it to tloc which must be a time_t value
/// returned by time(). This value is the number of seconds since the EPOCH
/// (i.e. 00:00:00 on Jan 1m 1970). If dosDate is true then the input
/// is a dosDate value.

TTimeStamp::TTimeStamp(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate)
{
   Set(tloc, isUTC, secOffset, dosDate);
}

////////////////////////////////////////////////////////////////////////////////
/// Return Greenwich mean sidereal time (GMST) in hour-angle. Return value
/// will always be between 0 and 24 (hours). Sidereal time is most accurately
/// calculated from UT1. If fSec and fNanoSec are in UTC (which they are by
/// default), the optional argument UT1Offset can be supplied (in
/// milliseconds). If UT1Offset is not supplied, conversion has maximum error
/// of 1s. If offset is supplied error can be reduced to us level. Values for
/// UT1Offset can be found in IERS Bulletin B:
/// ftp://ftp.iers.org/products/eop/bulletinb/format_2009/
/// The conversion to sidereal time used here is given by
/// Aoki et. al. Astron. Astrophys. 105, 359-362 (1982)
/// http://adsabs.harvard.edu/abs/1982A%26A...105..359A

Double_t TTimeStamp::AsGMST(Double_t UT1Offset) const
{
   Double_t D = (AsJulianDate() + UT1Offset/86400000.0) - 2451545.0;
   Double_t D_r = D - fmod(2.0*D+1.0, 2.0)/2.0;
   Double_t T = D_r/36525.0;
   Double_t sidereal = (24110.54841 + 8640184.812866*T + 0.093142*T*T
      - 0.0000062*T*T*T + (D - D_r)*86400.0*1.002737909350795)/3600.0;
   Double_t rval = fmod(sidereal, 24.0);
   return rval < 0 ? rval + 24.0 : rval;
}

////////////////////////////////////////////////////////////////////////////////
/// Return Greenwich apparent sidereal time (GAST) in hour-angle. Return
/// value will always be between 0 and 24 (hours). Sidereal time is most
/// accurately calculated from UT1. If fSec and fNanoSec are in UTC (which
/// they are by default), the optional argument UT1Offset can be supplied (in
/// milliseconds). If UT1Offset is not supplied, conversion has maximum error
/// of 1s. If offset is supplied error can be reduced to us level. Values for
/// UT1Offset can be found in IERS Bulletin B:
/// ftp://ftp.iers.org/products/eop/bulletinb/format_2009/
/// Equation of the equinoxes is given by USNO:
/// http://aa.usno.navy.mil/faq/docs/GAST.php

Double_t TTimeStamp::AsGAST(Double_t UT1Offset) const
{
   Double_t Pi = 3.14159265358979323846;
   Double_t D = (AsJulianDate() + UT1Offset/86400000.0) - 2451545.0;
   Double_t epsilon = (23.4393 - 0.0000004 * D) * Pi / 180.0;
   Double_t L = (280.47 + 0.98565 * D) * Pi / 180.0;
   Double_t Omega = (125.04 - 0.052954 * D) * Pi / 180.0;
   Double_t Deltapsi = -0.000319 * std::sin(Omega) - 0.000024 * std::sin(2.0 * L);
   Double_t eqeq = Deltapsi * std::cos(epsilon);
   Double_t rval = fmod(AsGMST(UT1Offset) + eqeq, 24.0);
{'fraction_non_alphanumeric': 0.22493887530562348, 'fraction_numerical': 0.044075860701777575, 'mean_word_length': 2.0165437512457642, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5540323', 'n_tokens_mistral': 5122, 'n_tokens_neox': 4551, 'n_words': 1515}