/* * Copyright (C) 2005-2019 by Centre National d'Etudes Spatiales (CNES) * * This file is licensed under MIT license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef ossimTimeUtilities_h #define ossimTimeUtilities_h #include "ossim/ossimStringUtilities.h" #include "ossim/ossimOperatorUtilities.h" #include "ossimPluginConstants.h" #include #include class ossimDate; namespace ossimplugins { namespace time { // class ModifiedJulianDate; // class Duration; namespace details { class DayFrac { public: typedef double scalar_type; // DayFrac(DayFrac const&) = default; // DayFrac(DayFrac &&) = default; // DayFrac& operator=(DayFrac const&) = default; // DayFrac& operator=(DayFrac &&) = default; double as_day_frac() const { return m_day_frac; } std::ostream & display(std::ostream & os) const { return os << m_day_frac; } std::istream & read (std::istream & is) { return is >> m_day_frac; } protected: /**@name Construction/destruction */ //@{ /** Initialization constructor. */ explicit DayFrac() {} // = default; explicit DayFrac(double day_frac) : m_day_frac(day_frac) {} /** Protected destructor. */ ~DayFrac() {}// = default; //@} /**@name Operations */ //@{ void add(DayFrac const& rhs) { m_day_frac += rhs.m_day_frac; } void sub(DayFrac const& rhs) { m_day_frac -= rhs.m_day_frac; } void mult(scalar_type coeff) { m_day_frac *= coeff; } void div(scalar_type coeff) { assert(coeff && "Cannot divide by 0"); m_day_frac /= coeff; } template friend scalar_type ratio_(V const& lhs, V const& rhs) { return lhs.as_day_frac() / rhs.as_day_frac(); } template friend U& operator+=(U & u, V const& v) { u.add(v); return u; } template friend U& operator-=(U & u, V const& v) { u.sub(v); return u; } template static U diff(V const& lhs, V const& rhs) { U const res(lhs.as_day_frac() - rhs.as_day_frac()); return res; } template friend U& operator*=(U & u, scalar_type const& v) { u.mult(v); return u; } template friend U& operator/=(U & u, scalar_type const& v) { u.div(v); return u; } template friend bool operator<(T const& lhs, T const& rhs) { return lhs.as_day_frac() < rhs.as_day_frac(); } template friend bool operator==(T const& lhs, T const& rhs) { return lhs.as_day_frac() == rhs.as_day_frac(); } //@} private: double m_day_frac; }; } /** * Duration abstraction. * * Values of this class represent time interval. * *

Semantics
*

  • Value, mathematical: it's relative position *
  • Time interval * * @see \c std::duration<> */ class Duration : public details::DayFrac , private addable , private substractable , private streamable , private multipliable2 , private dividable , private equality_comparable , private less_than_comparable { public: typedef details::DayFrac::scalar_type scalar_type; /**@name Construction/destruction */ //@{ /** Initialization constructor. */ Duration() {} // = default; explicit Duration(double day_frac) : details::DayFrac(day_frac) {} //@} double total_seconds() const { return as_day_frac() * 24 * 60 * 60; } double total_microseconds() const { return total_seconds() * 1000 * 1000; } bool is_negative() const { return as_day_frac() < 0.0; } Duration invert_sign() { return Duration(- as_day_frac()); } friend Duration abs(Duration const& d) { return Duration(std::abs(d.as_day_frac())); } }; /** * Modified JulianDate abstraction. * * Objects of this class represent points in time. * *

    Semantics
    *

  • Value, mathematical: it's an absolute position *
  • Point in time * @see \c std::time_point<> */ class ModifiedJulianDate : public details::DayFrac , private addable , private substractable , private substractable_asym , private streamable , private equality_comparable , private less_than_comparable { public: typedef details::DayFrac::scalar_type scalar_type; /**@name Construction/destruction */ //@{ /** Initialization constructor. */ ModifiedJulianDate() {} // = default; explicit ModifiedJulianDate(double day_frac) : details::DayFrac(day_frac) {} //@} using details::DayFrac::diff; }; OSSIM_PLUGINS_DLL ModifiedJulianDate toModifiedJulianDate(string_view const& utcTimeString); inline Duration microseconds(double us) { return Duration(us / (24ULL * 60 * 60 * 1000 * 1000)); } inline Duration seconds(double us) { return Duration(us / (24ULL * 60 * 60)); } OSSIM_PLUGINS_DLL std::string to_simple_string(ModifiedJulianDate const& d); OSSIM_PLUGINS_DLL std::string to_simple_string(Duration const& d); namespace details { // strptime is not portable, hence this simplified emulation OSSIM_PLUGINS_DLL ossimDate strptime(string_view const& format, string_view const& date); } // details namespace } } // ossimplugins namespace::time #if defined(USE_BOOST_TIME) # include # include // boost::posix_time::time_duration doesn't have a sufficient precision to // store things such an azimuth time interval, and yet, this IS a duration. // Hence this new class injected into boost namespace to emulate a duration // with precision behind the microsecond. // TODO: // - check whether we could have used another boost date // - move this elsewhere // - move this into another namespace namespace boost { namespace posix_time { class precise_duration; double ratio_(precise_duration const& lhs, precise_duration const& rhs); class precise_duration : private ossimplugins::addable , private ossimplugins::substractable , private ossimplugins::streamable , private ossimplugins::multipliable2 , private ossimplugins::dividable , private ossimplugins::equality_comparable , private ossimplugins::less_than_comparable , private ossimplugins::addable , private ossimplugins::substractable { public: typedef double scalar_type; /**@name Construction/destruction */ //@{ /** Initialization constructor. */ precise_duration() {} // = default; explicit precise_duration(double usec_frac) : m_usec_frac(usec_frac) {} precise_duration(time_duration const& d) : m_usec_frac(d.total_microseconds()) {} //@} double total_seconds() const { return total_microseconds() / 1000000.; } double total_microseconds() const { return m_usec_frac; } bool is_negative() const { return total_microseconds() < 0.0; } precise_duration invert_sign() { return precise_duration(- total_seconds()); } std::ostream & display(std::ostream & os) const { return os << m_usec_frac; } std::istream & read (std::istream & is) { return is >> m_usec_frac; } protected: /**@name Operations */ //@{ void add(precise_duration const& rhs) { m_usec_frac += rhs.total_microseconds(); } void sub(precise_duration const& rhs) { m_usec_frac -= rhs.total_microseconds(); } void mult(scalar_type coeff) { m_usec_frac *= coeff; } void div(scalar_type coeff) { assert(coeff && "Cannot divide by 0"); m_usec_frac /= coeff; } friend precise_duration& operator+=(precise_duration & u, precise_duration const& v) { u.add(v); return u; } friend ptime& operator+=(ptime & u, precise_duration const& v) { const time_duration d = microseconds(floor(v.total_microseconds()+0.5)); u += d; return u; } friend precise_duration& operator-=(precise_duration & u, precise_duration const& v) { u.sub(v); return u; } friend ptime& operator-=(ptime & u, precise_duration const& v) { const time_duration d = microseconds(floor(v.total_microseconds()+0.5)); u -= d; return u; } template static U diff(V const& lhs, V const& rhs) { U const res(lhs.total_microseconds() - rhs.total_microseconds()); return res; } friend precise_duration& operator*=(precise_duration & u, scalar_type const& v) { u.mult(v); return u; } friend precise_duration& operator/=(precise_duration & u, scalar_type const& v) { u.div(v); return u; } friend bool operator<(precise_duration const& lhs, precise_duration const& rhs) { return lhs.total_microseconds() < rhs.total_microseconds(); } friend bool operator==(precise_duration const& lhs, precise_duration const& rhs) { return lhs.total_microseconds() == rhs.total_microseconds(); } public: friend scalar_type ratio_(precise_duration const& lhs, precise_duration const& rhs) { return lhs.total_microseconds() / rhs.total_microseconds(); } //@} private: double m_usec_frac; }; time_duration abs(time_duration d) { if(d.is_negative()) d = d.invert_sign(); return d; } } } // boost::time namespaces #endif #endif // ossimTimeUtilities_h