Skip to content

Commit

Permalink
added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
xanthospap committed Oct 17, 2023
1 parent 84c024d commit 984a974
Show file tree
Hide file tree
Showing 18 changed files with 329 additions and 316 deletions.
6 changes: 3 additions & 3 deletions src/dat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,16 @@ int dso::dat(dso::modified_julian_day mjd, int &extra_sec_in_day) noexcept {
[&](const mjd_dat::change &c) {
return mjd >= dso::modified_julian_day(c.mjd);
});

/* extra seconds in day */
extra_sec_in_day = 0;

/* check to see if given MJD is a leap-second day (i.e. has more seconds) */
if (it != mjd_dat::changes.rend() && it != mjd_dat::changes.rbegin()) {
/* given MJD is on a leap-insertion date (i.e. day prior to next leap) */
if (mjd == dso::modified_julian_day((it-1)->mjd-1)) {
if (mjd == dso::modified_julian_day((it - 1)->mjd - 1)) {
/* DAT at next period */
int next_leap = (it-1)->delat;
int next_leap = (it - 1)->delat;
extra_sec_in_day = next_leap - it->delat;
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/datetime_tops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#define __DSO_DATETIME_GENERIC_TEMPLATE_OPERATIONS_HPP__

#include "dtconcepts.hpp"
#include <type_traits>
#include <limits>
#include <type_traits>

namespace dso {

Expand Down Expand Up @@ -56,7 +56,6 @@ constexpr bool operator==(DType a, DType b) noexcept {
return a.__member_const_ref__() == b.__member_const_ref__();
}


/** Overload bool operator '!=' for datetime fundamental types.
* This function will be resolved for any type DType, which
* 1. has a member (variable) DType::is_dt_fundamental_type set to true, and
Expand Down Expand Up @@ -415,6 +414,6 @@ constexpr Strg cast_to(Ssrc s) noexcept {
return Strg(numerator / Ssrc::template sec_factor<long>());
}

}/* namespace dso */
} /* namespace dso */

#endif
106 changes: 59 additions & 47 deletions src/dtcalendar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
#ifndef __DTCALENDAR_NGPT__HPP__
#define __DTCALENDAR_NGPT__HPP__

#include "dtfund.hpp"
#include "dtconcepts.hpp"
#include "dtfund.hpp"
#include <cassert>
#include <cmath>
#include <stdexcept>
#include <type_traits>
#include <cmath>

namespace dso {

Expand Down Expand Up @@ -90,34 +90,23 @@ struct RawDatetimeDifference {
* A datetime_interval represents a time (datetime) interval or period, i.e.
* 5 days, 12 hours and 49 seconds. We assume a continuous time scale, no leap
* seconds are taken into consideration --this is only an interval not an
* actual datetime instance--).
* actual datetime instance--.
* A datetime_interval instance can only have positive (or zero) values (for
* both its members).
* both of its members). However, seperate field is stored (i.e. \p m_sign) to
* hold 'sign' information, so that a datetime_interval instance can be easily
* used with a datetime instance. That means that e.g. 'adding' a negative
* interval, will extend the datetime in the past.
*
* A datetime_interval instance has two fundamental parts (members):
* - a day part (i.e. holding the days), and
* - a time part (i.e. holding any type S i.e. any second type)
* - a sign (i.e. an integer)
*
* The purpose of this class is to work together with the datetime class.
*
* @tparam S Any class of 'second type', i.e. any class S that has a (static)
* member variable S::is_of_sec_type set to true. This can be
* dso::seconds, dso::milliseconds, dso::microseconds.
*
*
* @note - Any instance of the class has two members, m_days an integer
* representing the (MJ) days and m_secs, an instance of type S,
* representing the fractional day part. However, the parts may be
* mixed (!), that is if e.g. S is dso::seconds, the m_secs part may
* actualy have any value, including ones larger than 86400. That is
* to say that an instance can be constructed as:
* \code{.cpp}
* datetime_interval<seconds> d {modified_julian_day(1),
* seconds(90000)};
* \endcode
* Should the user want the "normalization" of the instance (that is
* remove whole days from the m_secs part and add them to the m_days
* part), call the function datetime_interval::normalize().
*/
#if __cplusplus >= 202002L
template <gconcepts::is_sec_dt S>
Expand All @@ -130,15 +119,28 @@ class datetime_interval {

public:
/** Default constructor (everything set to 0). */
explicit constexpr datetime_interval() noexcept
: m_days(0), m_secs(0){};
explicit constexpr datetime_interval() noexcept : m_days(0), m_secs(0){};

/** Constructor from number of days and number of *seconds. The sign of the
* interval is taken from \p days. The number of days and number of *seconds
* of the interval, are considered positive (i.e. absolute values of input
* parameters).
/** Constructor from number of days and number of *seconds.
*
* The sign of the interval is extracted from \p days. The number of days
* and number of *seconds of the interval, are considered positive (i.e.
* absolute values of input parameters).
* For example to construct an interval of 2days + 2sec, use:
* datetime_interval<sec> interval(2, seconds(2));
* If you want to mark this interval as 'negative' (normally for algebraic
* operations with a datetime isntance), use:
* datetime_interval<sec> interval(-2, seconds(2));
* If you want to mark a 'negative' interval but the number of days is zero,
* then you should use:
* datetime_interval<sec> interval(0, seconds(-2));
* or
* datetime_interval<sec> interval(seconds(-2));
* and **NOT**
* datetime_interval<sec> interval(-0, seconds(2));
* since there is no 'signed 0' value.
*
* @warning It is not possible to differentiate between -0 and +1. Hence,
* @warning It is not possible to differentiate between -0 and +0. Hence,
* to construct an interval of 0 days and 1 secs (S), use:
* datetime_interval(S(-1)) and **NOT**
* datetime_interval(-0, S(1))
Expand All @@ -149,8 +151,8 @@ class datetime_interval {
normalize();
};

/** Constructor from number of *seconds. The sign of the interval is taken
* from \p secs. The number of *seconds of the interval is considered
/** Constructor from number of *seconds. The sign of the interval is taken
* from \p secs. The number of *seconds of the interval is considered
* positive (i.e. absolute values of input parameter).
*/
constexpr datetime_interval(S secs) noexcept
Expand Down Expand Up @@ -180,21 +182,23 @@ class datetime_interval {
DaysIntType days() const noexcept { return m_days; }

/** return number of *secs in interval, always positive */
S/*ecIntType*/ sec() const noexcept { return S(m_secs); }
S sec() const noexcept { return S(m_secs); }

/** return number of *secs in interval, signed (not including whole days) */
S /*ecIntType*/ signed_sec() const noexcept {
return S(std::copysign(m_secs, m_sign));
}
S signed_sec() const noexcept { return S(std::copysign(m_secs, m_sign)); }

/** return the sign of the interval */
int sign() const noexcept { return m_sign; }

S/*ecIntType*/ unsigned_total_sec() const noexcept {
/** Return the interval (days+*seconds) in seconds type S, ignoring sign */
S unsigned_total_sec() const noexcept {
return S(m_secs + S::max_in_day * m_days);
}

S/*ecIntType*/ signed_total_sec() const noexcept {
/** Return the interval (days+*seconds) in seconds type S, using a negative
* value if the instance is marked as 'negative'
*/
S signed_total_sec() const noexcept {
return S(std::copysign(unsigned_total_sec().as_underlying_type(), m_sign));
}

Expand All @@ -213,11 +217,11 @@ class datetime_interval {
* - a date part (i.e. holding the year/month/day), and
* - a time part (i.e. holding hours/minutes/ *seconds)
*
* A datetime holds both a date and a time (i.e. of day). The date is stored
* A datetime holds both a date and a time (i.e. of day). The date is stored
* as a Modified Julian Day (i.e. dso::modified_julian_day). The time of day
* can be stored via any class of 'second type', i.e. dso::seconds,
* dso::milliseconds, or dso::microseconds). Every method in the class will
* (including constructors) will take provisions such that the *seconds are
* dso::milliseconds, or dso::microseconds). Every method in the class will
* (including constructors) will take provisions such that the *seconds are
* in fact *seconds of day (i.e. do not surpass one day).
* Never use negative times; they actually have no physical meaning. Besides
* that, they can cause UB.
Expand Down Expand Up @@ -431,7 +435,7 @@ class datetime {
*/

/** Operator '+' where the right-hand-side is an interval.
* Note that the addition here is algebraic, i.e. the interval is added to
* Note that the addition here is algebraic, i.e. the interval is added to
* or subtracted from the instance, depending on its sign.
* Hence, an interval of e.g. (- 2 days, 30 sec) will actually be subtracted
* from the instance, not added to it.
Expand All @@ -445,7 +449,7 @@ class datetime {
}

/** Add a time interval to a datetime instance.
* Note that the addition here is algebraic, i.e. the interval is added to
* Note that the addition here is algebraic, i.e. the interval is added to
* or subtracted from the instance, depending on its sign.
* Hence, an interval of e.g. (- 2 days, 30 sec) will actually be subtracted
* from the instance, not added to it.
Expand All @@ -462,21 +466,29 @@ class datetime {
/* big date at d1, small at d2 */
auto d1 = *this;
auto d2 = dt;
int sgn=1;
if (m_mjd < dt.m_mjd) {
int sgn = 1;
if (*this < dt) {
d1 = d2;
d2 = *this;
sgn = -1;
}
/* seconds, could be negative */
SecIntType secs =
d1.sec().as_underlying_type() - d2.sec().as_underlying_type();
if (secs < 0) {
d1.m_mjd -= 1;
secs = S::max_in_day + secs;
}
/* so handle negative seconds */
// if (secs < 0) {
// d1.m_mjd -= 1;
// secs = S::max_in_day + secs;
// }
/* branchless TODO which is faster ? */
d1.m_mjd = d1.m_mjd - modified_julian_day(1 * (secs < 0));
secs = secs + S::max_in_day * (secs < 0);
DaysIntType days =
d1.imjd().as_underlying_type() - d2.imjd().as_underlying_type();
return datetime_interval<S>(days*sgn, S(secs));
/* note that id days are 0 and the sign is negative, it must be applied to
* the seconds part */
return datetime_interval<S>(days * sgn,
S(std::copysign(secs, (days == 0) * sgn)));
}

/** Cast to any datetime<T> instance, regardless of what T is
Expand Down Expand Up @@ -682,7 +694,7 @@ class datetime {

modified_julian_day m_mjd; /** Modified Julian Day */
S m_sec; /** Time of day in S precision. */
}; /* datetime<S> */
}; /* datetime<S> */

/// Difference between two dates in MJdays and T.
/// Diff is dt1 - dt2
Expand Down
50 changes: 25 additions & 25 deletions src/dtfund.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ inline constexpr double jd2epj(double dj1, double dj2) noexcept {

/** @brief Modified Julian Date to Julian Epoch
*
* Convert a Modified Julian date to a Julian Epoch. The MJD can be given as a
* single value (i.e. in parameter \p mjd0) or can be split into two parts,
* (e.g. the first being the intergal part of MJD and the second be fractional
* Convert a Modified Julian date to a Julian Epoch. The MJD can be given as a
* single value (i.e. in parameter \p mjd0) or can be split into two parts,
* (e.g. the first being the intergal part of MJD and the second be fractional
* day).
*
* @see jd2epj
Expand All @@ -148,7 +148,7 @@ inline constexpr double jd2epj(double dj1, double dj2) noexcept {
* @param[in] mjd1 Second part of MJD (if any), such that MJD = mjd0 + mjd1
* @return The input date as Julian Epoch.
*/
inline constexpr double mjd2epj(double mjd0, double mjd1=0e0) noexcept {
inline constexpr double mjd2epj(double mjd0, double mjd1 = 0e0) noexcept {
return 2000e0 + ((mjd0 - J2000_MJD) / DAYS_IN_JULIAN_YEAR +
mjd1 / DAYS_IN_JULIAN_YEAR);
}
Expand All @@ -164,7 +164,7 @@ inline constexpr double epj2mjd(double epj) noexcept {
return J2000_MJD + (epj - 2000e0) * DAYS_IN_JULIAN_YEAR;
}
} /* namespace core */

/** @brief For a given UTC date, calculate delta(AT) = TAI-UTC.
*
* The day of month is actually not needed, since all leap second insertions
Expand Down Expand Up @@ -707,37 +707,37 @@ class ymd_date {
constexpr bool is_valid() const noexcept {
return __dom.is_valid(__year, __month);
}

/** operator '==' for ymd_date instances */
bool operator==(const ymd_date &d) const noexcept {
return ((__year == d.yr()) && (__dom == d.dm()) && (__month==d.mn()));
return ((__year == d.yr()) && (__dom == d.dm()) && (__month == d.mn()));
}

/** operator '!=' for ymd_date instances */
bool operator!=(const ymd_date &d) const noexcept {
return !(this->operator==(d));
}

/** @brief Transform to year and day-of-year
* The function will first check that the instance is a valid date, before
* performing the transformation (to year and day of year). This is done
* because an invalid ymd_date can result in a seamingly valid ydoy_date
* The function will first check that the instance is a valid date, before
* performing the transformation (to year and day of year). This is done
* because an invalid ymd_date can result in a seamingly valid ydoy_date
* (e.g. constructing a 29/2 date on a non-leap year).
*/
ydoy_date to_ydoy() const;

/** get/set year */
constexpr year &yr() noexcept {return __year;}
constexpr year &yr() noexcept { return __year; }
/** get/set month */
constexpr month &mn() noexcept {return __month;}
constexpr month &mn() noexcept { return __month; }
/** get/set day of month */
constexpr day_of_month &dm() noexcept {return __dom;}
constexpr day_of_month &dm() noexcept { return __dom; }
/** get year */
constexpr year yr() const noexcept {return __year;}
constexpr year yr() const noexcept { return __year; }
/** get month */
constexpr month mn() const noexcept {return __month;}
constexpr month mn() const noexcept { return __month; }
/** get day of month */
constexpr day_of_month dm() const noexcept {return __dom;}
constexpr day_of_month dm() const noexcept { return __dom; }

private:
year __year; /** the year */
Expand All @@ -762,8 +762,8 @@ class ydoy_date {
constexpr ydoy_date(year y = year{}, day_of_year d = day_of_year{}) noexcept
: __year(y), __doy(d) {}

/** @brief Constructor from a Year/Month/DayOfMonth instance
* In case the input argument \p ymd is not a valid date, the constructor
/** @brief Constructor from a Year/Month/DayOfMonth instance
* In case the input argument \p ymd is not a valid date, the constructor
* will throw.
*/
ydoy_date(const ymd_date &ymd)
Expand All @@ -781,20 +781,20 @@ class ydoy_date {
bool operator==(const ydoy_date &d) const noexcept {
return (__year == d.yr()) && (__doy == d.dy());
}

/** operator '!=' for ydoy_date instances */
bool operator!=(const ydoy_date &d) const noexcept {
return !(this->operator==(d));
}

/** get/set year */
year &yr() noexcept {return __year;}
year &yr() noexcept { return __year; }
/** get/set day of year */
day_of_year &dy() noexcept {return __doy;}
day_of_year &dy() noexcept { return __doy; }
/** get year */
constexpr year yr() const noexcept {return __year;}
constexpr year yr() const noexcept { return __year; }
/** get day of year */
constexpr day_of_year dy() const noexcept {return __doy;}
constexpr day_of_year dy() const noexcept { return __doy; }

private:
year __year; /** the year */
Expand Down
2 changes: 1 addition & 1 deletion src/hms_time.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @file
* A class to represent hours/minutes/seconds, i.e. a time instance.
* A class to represent hours/minutes/seconds, i.e. a time instance.
*/
#ifndef __DSO_DATETIME_HMSTIME_HPP__
#define __DSO_DATETIME_HMSTIME_HPP__
Expand Down
6 changes: 3 additions & 3 deletions src/tpdate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ struct TwoPartJulianDate {
double d0, d1;
};

/** Given an MJD, turn it to a JD and return it split in a convinient way
* The way the (returned) JD is split is determined by the template parameter
* \p S.
/** Given an MJD, turn it to a JD and return it split in a convinient way
* The way the (returned) JD is split is determined by the template parameter
* \p S.
*/
template <JdSplitMethod S = JdSplitMethod::J2000>
TwoPartJulianDate jd_split(double mjd, double fday) noexcept {
Expand Down
Loading

0 comments on commit 984a974

Please sign in to comment.