////////////////////////////////////////////////////////////////////
/// \class RAT::DS::UniversalTime
///
/// \brief This class represents a time in the SNO+ Universal time system
///
/// \author Phil G Jones
///
/// REVISION HISTORY:\n
/// 2013-1-21 : P. Jones - New file as part of ds review.
///
/// \details Universal time is the time elapsed since the start of the
/// SNO+ epoch, t0, which is midnight on 01 Jan 2010 (GMT).
///
////////////////////////////////////////////////////////////////////
#ifndef __RAT_DS_UniversalTime__
#define __RAT_DS_UniversalTime__
#include
#include
namespace RAT
{
namespace DS
{
class UniversalTime : public TObject
{
public:
/// Construct the class
UniversalTime() : TObject(), days(0), seconds(0), nanoSeconds(0) { };
/// Construct the class with relevant timing values
///
/// @param[in] days_ since t0
/// @param[in] seconds_ since t0
/// @param[in] nanoSeconds_ since t0
UniversalTime( const UInt_t days_, const UInt_t seconds_, const UInt_t nanoSeconds_ );
/// Get the days
///
/// @return days
UInt_t GetDays() const { return days; }
/// Get the seconds
///
/// @return seconds
UInt_t GetSeconds() const { return seconds; }
/// Get the nano seconds
///
/// @return nano seconds
Double_t GetNanoSeconds() const { return nanoSeconds; }
/// Get the time as a std time structure
///
/// @param[in] snoPlus should the (default) snoplus (true) or sno (false) offset be used?
/// @return the time as a time structure
inline std::tm GetTime( const Bool_t snoPlus=true ) const;
/// Add a universal time to this
///
/// @param[in] rhs to add
/// @return reference to this
inline UniversalTime& operator+=( const UniversalTime& rhs );
/// Add a universal time
///
/// @param[in] rhs to add
/// @return new universal time
UniversalTime operator+( const UniversalTime& rhs ) const { return UniversalTime(*this) += rhs; }
/// Subtract a universal time to this
///
/// @param[in] rhs to subtract
/// @return reference to this
inline UniversalTime& operator-=( const UniversalTime& rhs );
/// Subtract a universal time
///
/// @param[in] rhs to subtract
/// @return new universal time
UniversalTime operator-( const UniversalTime& rhs ) const { return UniversalTime(*this) -= rhs; }
/// Check if this time is the same as another
///
/// @param[in] rhs to test
/// @return true if they are the same
Bool_t operator==( const UniversalTime& rhs ) const { return days == rhs.days && seconds == rhs.seconds && nanoSeconds == rhs.nanoSeconds; }
/// Check if this time is NOT the same as another
///
/// @param[in] rhs to test
/// @return true if they are NOT the same
Bool_t operator!=( const UniversalTime& rhs ) const { return !(*this == rhs ); }
/// Check if this time is less than (before) another
///
/// @param[in] rhs to test
/// @return true if this is less than (before) rhs
inline Bool_t operator<( const UniversalTime& rhs ) const;
/// Check if this time is less than (before) or equal to another
///
/// @param[in] rhs to test
/// @return true if this is less than (before) or equal to rhs
Bool_t operator<=( const UniversalTime& rhs ) const { return *this < rhs || *this == rhs; }
/// Check if this time is greater than (before) another
///
/// @param[in] rhs to test
/// @return true if this is greater than (before) rhs
Bool_t operator>( const UniversalTime& rhs ) const { return !(*this <= rhs); }
/// Check if this time is greater than (before) or equal to another
///
/// @param[in] rhs to test
/// @return true if this is greater than (before) or equal to rhs
Bool_t operator>=( const UniversalTime& rhs ) const { return *this > rhs || *this == rhs; }
// This ROOT macro adds dictionary methods to this class.
// The number should be incremented whenever this class's members are changed.
// It assumes this class has no virtual methods, use ClassDef if change this.
ClassDefNV( UniversalTime, 1 );
protected:
/// Normalises the time i.e. ensures that nanoSeconds < 1 second and seconds < 1 day
inline void Normalise();
UInt_t days; ///< Universal time i.e. relative to the world (days since SNO+ day0)
UInt_t seconds; ///< Universal time i.e. relative to the world (secs)
Double_t nanoSeconds; ///< Universal time i.e. relative to the world (nsecs)
};
inline
UniversalTime::UniversalTime( const UInt_t days_, const UInt_t seconds_, const UInt_t nanoSeconds_ )
: TObject(), days(days_), seconds(seconds_), nanoSeconds(nanoSeconds_)
{
Normalise();
}
inline std::tm
UniversalTime::GetTime( const Bool_t snoPlus ) const
{
std::tm time;
time.tm_sec = seconds;
time.tm_min = 0;
time.tm_hour = 0;
time.tm_mday = 1 + days;
time.tm_mon = 0;
if( snoPlus ) // SNO+ starts at 2010, SNO at 1996, tm_year is years since 1900
time.tm_year = 110;
else
time.tm_year = 96;
time.tm_isdst = 0;
mktime(&time); // Normalises i.e. deals with roll-overs etc...
return time;
}
inline UniversalTime&
UniversalTime::operator+=( const UniversalTime& rhs )
{
nanoSeconds += rhs.nanoSeconds;
seconds += rhs.seconds;
days += rhs.days;
Normalise();
return *this;
}
inline UniversalTime&
UniversalTime::operator-=( const UniversalTime& rhs )
{
nanoSeconds -= rhs.nanoSeconds;
seconds -= rhs.seconds;
days -= rhs.days;
Normalise();
return *this;
}
inline Bool_t
UniversalTime::operator<( const UniversalTime& rhs ) const
{
if( days > rhs.days ) return false;
else if( days == rhs.days && seconds > rhs.seconds ) return false;
else if( days == rhs.days && seconds == rhs.seconds && nanoSeconds >= rhs.nanoSeconds ) return false;
return true;
}
inline void
UniversalTime::Normalise()
{
const int overflowSeconds = static_cast( nanoSeconds / 1e9 ); // Floors
seconds += overflowSeconds;
nanoSeconds -= overflowSeconds * 1e9;
const int overflowDays = static_cast( seconds / ( 60.0 * 60.0 * 24.0 ) );
days += overflowDays;
seconds -= overflowDays * 60.0 * 60.0 * 24.0;
}
} // namespace DS
} // namespace RAT
#endif