Commit 9abfea67dddb583ee55400af6857430c3e8f68a2

Authored by Jürgen Knödlseder
1 parent 89829f97

Add leap second handling to convert() and set() methods and add corresponding unit tests.

The convert() and set() methods now support time references given in the UTC time system. Using convert() one can now extract for example MJD in the UTC time system. All this needs still to be documented.
include/GTime.hpp
... ... @@ -36,7 +36,7 @@
36 36 /***********************************************************************//**
37 37 * @class GTime
38 38 *
39   - * @brief Handles times in a system independent way
  39 + * @brief Time class
40 40 *
41 41 * The GTime class stores a time value in seconds in a GammaLib native time
42 42 * reference system. The GammaLib native time reference (i.e. time=0) is
... ... @@ -68,8 +68,8 @@ public:
68 68 // Constructors and destructors
69 69 GTime(void);
70 70 GTime(const GTime& time);
71   - explicit GTime(const double& time, const std::string& unit = "sec");
72   - explicit GTime(const double& time, const GTimeReference& ref);
  71 + GTime(const double& time, const std::string& unit = "sec");
  72 + GTime(const double& time, const GTimeReference& ref);
73 73 virtual ~GTime(void);
74 74  
75 75 // Operators
... ... @@ -104,7 +104,7 @@ protected:
104 104 int days_in_year(const int& year) const;
105 105  
106 106 // Protected data members
107   - double m_time; //!< Time in seconds in native reference
  107 + double m_time; //!< Time in seconds in native reference (TT)
108 108 };
109 109  
110 110  
... ...
pyext/GTime.i
... ... @@ -32,10 +32,7 @@
32 32 /***********************************************************************//**
33 33 * @class GTime
34 34 *
35   - * @brief Class that handles times in a system independent way
36   - *
37   - * The GTime class stores a time value in seconds and its MJD reference in
38   - * days. The time can be retrieved in any MJD reference.
  35 + * @brief Time class
39 36 ***************************************************************************/
40 37 class GTime : public GBase {
41 38  
... ... @@ -43,13 +40,14 @@ public:
43 40 // Constructors and destructors
44 41 GTime(void);
45 42 GTime(const GTime& time);
46   - explicit GTime(const double& time, const std::string& unit = "sec");
47   - explicit GTime(const double& time, const GTimeReference& ref);
  43 + GTime(const double& time, const std::string& unit = "sec");
  44 + GTime(const double& time, const GTimeReference& ref);
48 45 virtual ~GTime(void);
49 46  
50 47 // Methods
51 48 void clear(void);
52 49 GTime* clone(void) const;
  50 + std::string classname(void) const;
53 51 double jd(void) const;
54 52 double mjd(void) const;
55 53 const double& secs(void) const;
... ...
src/obs/GTime.cpp
... ... @@ -90,14 +90,14 @@ GTime::GTime(const GTime&amp; time)
90 90 /***********************************************************************//**
91 91 * @brief Time constructor
92 92 *
93   - * @param[in] time Time value (seconds or days).
  93 + * @param[in] time Time value in TT (seconds or days).
94 94 * @param[in] unit Time unit (default: "secs").
95 95 *
96 96 * @exception GException::time_invalid_unit
97 97 * Invalid time unit specified.
98 98 *
99 99 * Constructs a GTime object by setting the time in the native reference
100   - * in units of seconds (default) or days.
  100 + * in the TT time system in units of seconds (default) or days.
101 101 ***************************************************************************/
102 102 GTime::GTime(const double& time, const std::string& unit)
103 103 {
... ... @@ -296,9 +296,9 @@ std::string GTime::utc(void) const
296 296 // argument is given in the UTC system but upon start we're in the TAI
297 297 // system
298 298 double leaps = leap_seconds(mjd) * gammalib::sec2day;
299   - leaps = leap_seconds(mjd - leaps) * gammalib::sec2day;
300   - leaps = leap_seconds(mjd - leaps) * gammalib::sec2day;
301   - mjd -= leaps;
  299 + leaps = leap_seconds(mjd - leaps) * gammalib::sec2day;
  300 + leaps = leap_seconds(mjd - leaps) * gammalib::sec2day;
  301 + mjd -= leaps;
302 302  
303 303 // Split in day and fraction
304 304 int day = (int)mjd;
... ... @@ -367,13 +367,10 @@ std::string GTime::utc(void) const
367 367 *
368 368 * Convert the time from the native reference system into the specified
369 369 * reference system.
370   - *
371   - * @todo Implement TT-UTC conversion if required. This requires
372   - * implementation of leap seconds.
373 370 ***************************************************************************/
374 371 double GTime::convert(const GTimeReference& ref) const
375 372 {
376   - // Retrieve time in native reference (seconds)
  373 + // Retrieve time in native reference (TT in seconds)
377 374 double time = m_time;
378 375  
379 376 // Compute time offset in seconds
... ... @@ -382,6 +379,25 @@ double GTime::convert(const GTimeReference&amp; ref) const
382 379 // Add time offset in seconds
383 380 time += offset;
384 381  
  382 + // Subtract leap seconds in case that time is requested in UTC time
  383 + // system
  384 + if (gammalib::toupper(ref.timesys()) == "UTC") {
  385 +
  386 + // Get MJD in TAI time system
  387 + double mjd = this->mjd() - gammalib::tai2tt * gammalib::sec2day;
  388 +
  389 + // Get leap seconds (repeat is a kluge to converge as the
  390 + // argument is given in the UTC system but upon start we're in the TAI
  391 + // system
  392 + double leaps = leap_seconds(mjd);
  393 + leaps = leap_seconds(mjd - leaps * gammalib::sec2day);
  394 + leaps = leap_seconds(mjd - leaps * gammalib::sec2day);
  395 +
  396 + // Subtract leap seconds and TAI offset
  397 + time -= (leaps + gammalib::tai2tt);
  398 +
  399 + } // endif: UTC time system has been requested
  400 +
385 401 // Convert to specified time unit
386 402 double to_unit = ref.unitseconds();
387 403 if (to_unit != 1.0) {
... ... @@ -556,9 +572,6 @@ void GTime::utc(const std::string&amp; time)
556 572 * @param[in] ref Reference system.
557 573 *
558 574 * Set the time to a value given in a specific reference system.
559   - *
560   - * @todo Implement TT-UTC conversion if required. This requires
561   - * implementation of leap seconds.
562 575 ***************************************************************************/
563 576 void GTime::set(const double& time, const GTimeReference& ref)
564 577 {
... ... @@ -571,6 +584,15 @@ void GTime::set(const double&amp; time, const GTimeReference&amp; ref)
571 584 // Subtract time offset in seconds
572 585 m_time -= offset;
573 586  
  587 + // Add leap seconds in case that time was given in UTC time system
  588 + if (gammalib::toupper(ref.timesys()) == "UTC") {
  589 +
  590 + // Add leap seconds and offset between TAI and TT time system
  591 + m_time += leap_seconds(this->mjd());
  592 + m_time += gammalib::tai2tt;
  593 +
  594 + } // endif: Time was given in UTC time system
  595 +
574 596 // Return
575 597 return;
576 598 }
... ...
test/test_GObservation.cpp
... ... @@ -557,6 +557,23 @@ void TestGObservation::test_time(void)
557 557 time.set(12.3, GTimeReference(0.0, "secs", "TT", "LOCAL"));
558 558 test_value(time.secs(), 12.3 - mjd_ref*86400.0);
559 559  
  560 + // Test conversion to different time systems
  561 + time.utc("2005-10-08T14:30:25");
  562 + test_value(time.convert(GTimeReference(0.0, "days", "TT", "LOCAL")),
  563 + 53651.60519889, 1.0e-6);
  564 + test_value(time.convert(GTimeReference(0.0, "days", "UTC", "LOCAL")),
  565 + 53651.60445602, 1.0e-6);
  566 +
  567 + // Test setting to different time systems
  568 + time.set(53651.60519889, GTimeReference(0.0, "days", "TT", "LOCAL"));
  569 + test_assert(time.utc() == "2005-10-08T14:30:25",
  570 + "GTime::utc(): 2005-10-08T14:30:25 expected, "+
  571 + time.utc()+" found.");
  572 + time.set(53651.60445602, GTimeReference(0.0, "days", "UTC", "LOCAL"));
  573 + test_assert(time.utc() == "2005-10-08T14:30:25",
  574 + "GTime::utc(): 2005-10-08T14:30:25 expected, "+
  575 + time.utc()+" found.");
  576 +
560 577 // Test operators
561 578 GTime a(13.72);
562 579 GTime b(6.28);
... ...