Commit fddebcde authored by Cédric Traizet's avatar Cédric Traizet
Browse files

Merge branch 'refac_date_time' into 'develop'

Use std::chrono and the date library instead of boost date time

See merge request !868
parents 8749d879 d357d57e
Pipeline #9206 canceled with stages
in 51 minutes and 45 seconds
......@@ -23,12 +23,10 @@
#include "OTBMetadataExport.h"
// Use nanosecond precision in boost dates and durations
#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/config.hpp>
#include <cmath>
#include <boost/operators.hpp>
#include <chrono>
#include <string>
namespace otb
{
......@@ -37,6 +35,17 @@ namespace MetaData
namespace details
{
using InternalDurationType = std::chrono::nanoseconds;
using InternalTimePointType = std::chrono::time_point<std::chrono::system_clock, InternalDurationType>;
// the number of second's fractions per tick of InternalDurationType
constexpr double internalPeriod = static_cast<double>(InternalDurationType::period::num) / InternalDurationType::period::den;
// Standard format used when parsing dates
const std::string timePointFormat = "%Y-%m-%dT%H:%M:%S";
// Add some operators not defined in boost
// division by a scalar and ratio
template <typename T, typename R> struct dividable
{
......@@ -48,11 +57,10 @@ template <typename T, typename R> struct dividable
}
friend scalar_type operator/(T const& lhs, T const& rhs)
{
return ratio_(lhs, rhs);
return Ratio(lhs, rhs);
}
};
template <typename U, typename V> struct substractable_asym
{
friend U operator-(V const& lhs, V const& rhs)
......@@ -74,19 +82,28 @@ template <typename T> struct streamable
};
} // namespace details
class Duration;
/** \class TimePoint
*
* \brief Represents a point in Time
*
* \ingroup OTBMetadata
*/
class OTBMetadata_EXPORT TimePoint : private details::streamable<TimePoint>,
private details::substractable_asym<Duration, TimePoint>,
private boost::equality_comparable<TimePoint>,
private boost::less_than_comparable<TimePoint>
{
public:
//friend class Duration;
TimePoint() = default;
using InternalTimePointType = details::InternalTimePointType;
TimePoint(): m_Time(InternalTimePointType::min()) {}
TimePoint(InternalTimePointType const& t): m_Time(t) {}
std::ostream & Display(std::ostream & os) const { return os << m_Time; }
std::istream & Read (std::istream & is) { return is >> m_Time; }
std::ostream & Display(std::ostream & os) const;
std::istream & Read (std::istream & is, const std::string & format = details::timePointFormat);
template <typename U, typename V> static U diff(V const& lhs, V const& rhs)
{
......@@ -104,15 +121,44 @@ public:
return lhs.m_Time == rhs.m_Time;
}
/** Return the julian day corresponding to the time point */
double GetJulianDay() const;
public:
boost::posix_time::ptime m_Time;
};
/** Return the modified julian day corresponding to the time point */
double GetModifiedJulianDay() const;
/** Return the year corresponding to the time point */
int GetYear() const;
/** Return the month of the year corresponding to the time point (from 1 to 12) */
unsigned int GetMonth() const;
/** Return the calendar day corresponding to the time point (from 1 to 31) */
unsigned int GetDay() const;
/** Return the hour of the day corresponding to the time point (from 0 to 23) */
unsigned int GetHour() const;
/** Return the minute of the hour of the day corresponding to the time point (from 0 to 59) */
unsigned int GetMinute() const;
using TimeType = TimePoint;
/** Return the fractional second of the minute of the hour of the day corresponding to the time point (from 0 and inferior to 60) */
double GetSecond() const;
double ratio_(Duration const& lhs, Duration const& rhs);
friend TimePoint& operator+=(TimePoint & u, Duration const& v);
friend TimePoint& operator-=(TimePoint & u, Duration const& v);
private:
InternalTimePointType m_Time;
};
/** \class Duration
*
* \brief Represents a duration
*
* \ingroup OTBMetadata
*/
class OTBMetadata_EXPORT Duration : private details::streamable<Duration>,
private boost::addable<Duration>,
private boost::subtractable<Duration>,
......@@ -120,38 +166,39 @@ class OTBMetadata_EXPORT Duration : private details::streamable<Duration>,
private details::dividable<Duration, double>,
private boost::equality_comparable<Duration>,
private boost::less_than_comparable<Duration>,
private boost::addable<TimeType, Duration>,
private boost::subtractable<TimeType, Duration>
private boost::addable<TimePoint, Duration>,
private boost::subtractable<TimePoint, Duration>
{
public:
using InternalDurationType = boost::posix_time::time_duration;
using InternalDurationType = details::InternalDurationType;
Duration() = default;
Duration(InternalDurationType const& d): m_Duration(d) {}
static Duration Seconds(double d)
static Duration Seconds(double s)
{
return Duration(boost::posix_time::nanoseconds(static_cast<long long>(std::round(d * 1e9))));
return Duration(InternalDurationType(static_cast<InternalDurationType::rep>(std::round(s / details::internalPeriod))));
}
static Duration Nanoseconds(double d)
static Duration Miliseconds(double ms)
{
return Duration(boost::posix_time::nanoseconds(static_cast<long long>(std::round(d))));
return Duration(InternalDurationType(static_cast<InternalDurationType::rep>(std::round(ms / details::internalPeriod * 1e-3))));
}
Duration(double d): m_Duration(boost::posix_time::nanoseconds(static_cast<long long>(std::round(d)))) {}
double TotalNanoseconds() const
static Duration Microseconds(double us)
{
return m_Duration.total_nanoseconds();
return Duration(InternalDurationType(static_cast<InternalDurationType::rep>(std::round(us / details::internalPeriod * 1e-6))));
}
double TotalSeconds() const
static Duration Nanoseconds(double ns)
{
return m_Duration.total_nanoseconds() * 1e-9;
return Duration(InternalDurationType(static_cast<InternalDurationType::rep>(std::round(ns / details::internalPeriod * 1e-9))));
}
double TotalSeconds() const;
InternalDurationType::rep NumberOfTicks() const;
friend Duration& operator+=(Duration & u, Duration const& v)
{
u.m_Duration += v.m_Duration;
......@@ -166,16 +213,15 @@ public:
friend Duration& operator*=(Duration & u, double v)
{
u.m_Duration = boost::posix_time::nanoseconds(static_cast<long long>(std::round(
u.m_Duration.total_nanoseconds() * v)));
// note: don't use std::chrono::duration::operator* cause it multiplies the input by an integer value.
u.m_Duration = InternalDurationType(static_cast<InternalDurationType::rep>(std::round(u.m_Duration.count() * v)));
return u;
}
friend Duration& operator/=(Duration & u, double v)
{
u.m_Duration = boost::posix_time::nanoseconds(static_cast<long long>(std::round(
u.m_Duration.total_nanoseconds() / v)));
// note: don't use std::chrono::duration::operator/ cause it divides the input by an integer value.
u.m_Duration = InternalDurationType(static_cast<InternalDurationType::rep>(std::round(u.m_Duration.count() / v)));
return u;
}
......@@ -189,39 +235,31 @@ public:
return lhs.m_Duration == rhs.m_Duration;
}
friend TimeType& operator+=(TimeType & u, Duration const& v)
friend TimePoint& operator+=(TimePoint & u, Duration const& v)
{
u.m_Time += v.m_Duration;
return u;
}
friend TimeType& operator-=(TimeType & u, Duration const& v)
friend TimePoint& operator-=(TimePoint & u, Duration const& v)
{
u.m_Time -= v.m_Duration;
return u;
}
std::ostream & Display(std::ostream & os) const { return os << m_Duration; }
std::istream & Read (std::istream & is) { return is >> m_Duration; }
std::ostream & Display(std::ostream & os) const;
std::istream & Read (std::istream & is);
OTBMetadata_EXPORT friend Duration Abs(Duration d);
friend OTBMetadata_EXPORT Duration Abs(Duration d);
private:
InternalDurationType m_Duration;
};
OTBMetadata_EXPORT Duration Abs(Duration d);
using DurationType = Duration;
OTBMetadata_EXPORT DurationType seconds(double);
OTBMetadata_EXPORT TimeType ReadFormattedDate(const std::string & dateStr, const std::string & format = "%Y-%m-%dT%H:%M:%S%F");
}
}
OTBMetadata_EXPORT double Ratio(const Duration & lhs, const Duration & rhs);
OTBMetadata_EXPORT TimePoint ReadFormattedDate(const std::string & dateStr, const std::string & format = details::timePointFormat);
} // namespace otb
} // namespace MetaData
#endif
#endif // otbDateTime_h
......@@ -86,7 +86,7 @@ public:
DictType<MDL2D, MetaData::LUT2D> LUT2DKeys;
DictType<MDTime, MetaData::Time> TimeKeys;
DictType<MDTime, MetaData::TimePoint> TimeKeys;
DictType<std::string, std::string> ExtraKeys;
......@@ -97,7 +97,7 @@ public:
DictType<MDStr, std::string> stringKeys,
DictType<MDL1D, MetaData::LUT1D> lut1DKeys,
DictType<MDL2D, MetaData::LUT2D> lut2DKeys,
DictType<MDTime, MetaData::Time> timeKeys,
DictType<MDTime, MetaData::TimePoint> timeKeys,
DictType<std::string, std::string> extraKeys);
// -------------------- Geom utility function ----------------------------
......@@ -191,10 +191,10 @@ public:
// -------------------- Time utility function ----------------------------
/** Read-only accessor to time keys */
const MetaData::Time & operator[](const MDTime& key) const;
const MetaData::TimePoint & operator[](const MDTime& key) const;
/** Setter for time keys */
void Add(const MDTime& key, const MetaData::Time &value);
void Add(const MDTime& key, const MetaData::TimePoint &value);
/** Remove a key from the dictionary (even if the key is already missing) */
size_t Remove(const MDTime& key);
......@@ -260,13 +260,13 @@ public:
ImageMetadataBandsType Bands;
// Constructor
ImageMetadata();
ImageMetadata() = default;
ImageMetadata(DictType<MDGeom, boost::any> geometryKeys,
DictType<MDNum, double> numericKeys,
DictType<MDStr, std::string> stringKeys,
DictType<MDL1D, MetaData::LUT1D> lut1DKeys,
DictType<MDL2D, MetaData::LUT2D> lut2DKeys,
DictType<MDTime, MetaData::Time> timeKeys,
DictType<MDTime, MetaData::TimePoint> timeKeys,
DictType<std::string, std::string> extraKeys,
ImageMetadataBandsType bands);
......
......@@ -140,7 +140,7 @@ public:
const double& Fetch(MDNum key, ImageMetadata & imd, const char *path, int band=-1);
bool CheckFetch(MDNum key, ImageMetadata & imd, const char *path, int band=-1);
const MetaData::Time& Fetch(MDTime key, ImageMetadata & imd, const char *path, int band=-1);
const MetaData::TimePoint& Fetch(MDTime key, ImageMetadata & imd, const char *path, int band=-1);
bool CheckFetch(MDTime key, ImageMetadata & imd, const char *path, int band=-1);
const std::string& Fetch(std::string key, ImageMetadata & imd, const char *path, int band=-1);
......
......@@ -232,65 +232,6 @@ namespace MetaData
using Keywordlist = std::unordered_map<std::string, std::string>;
struct OTBMetadata_EXPORT Time : tm
{
double frac_sec;
friend OTBMetadata_EXPORT std::ostream& operator<<(std::ostream& os, const Time& val);
friend OTBMetadata_EXPORT std::istream& operator>>(std::istream& is, Time& val);
friend OTBMetadata_EXPORT bool operator==(const Time & lhs, const Time & rhs)
{
tm tmLhs = lhs;
tm tmRhs = rhs;
return mktime(&tmLhs) + lhs.frac_sec == mktime(&tmRhs) + rhs.frac_sec;
}
friend OTBMetadata_EXPORT bool operator!=(const Time & lhs, const Time & rhs)
{
return !(lhs == rhs);
}
friend OTBMetadata_EXPORT bool operator<(const Time & lhs, const Time & rhs)
{
tm tmLhs = lhs;
tm tmRhs = rhs;
return mktime(&tmLhs) + lhs.frac_sec < mktime(&tmRhs) + rhs.frac_sec;
}
friend OTBMetadata_EXPORT bool operator>(const Time & lhs, const Time & rhs)
{
return rhs < lhs;
}
friend OTBMetadata_EXPORT bool operator<=(const Time & lhs, const Time & rhs)
{
return !(lhs > rhs);
}
friend OTBMetadata_EXPORT bool operator>=(const Time & lhs, const Time & rhs)
{
return !(lhs < rhs);
}
/** @name Getters
* Getters on the date components
*/
///@{
int GetDay() const;
int GetMonth() const;
int GetYear() const;
int GetHour() const;
int GetMinute() const;
double GetSecond() const;
double GetJulianDay() const;
double GetModifiedJulian() const;
///@}
};
struct LUTAxis
{
/** number of measurements on this axis */
......@@ -403,25 +344,6 @@ std::string EnumToString(std::string value);
} // end namespace MetaData
namespace Utils
{
template <>
inline MetaData::Time LexicalCast<MetaData::Time,std::string>(std::string const& in, std::string const& kind)
{
MetaData::Time output;
std::istringstream iss(in);
iss >> output;
if (iss.fail())
{
std::ostringstream oss;
oss << "Cannot decode '" << in << "' as this is not a valid value for '" << kind << "'";
throw std::runtime_error(oss.str());
}
return output;
}
} // end namespace Utils
} // end namespace otb
#endif
......@@ -24,21 +24,13 @@
#include "OTBMetadataExport.h"
#include <vector>
#include <string>
#include "otbMacro.h"
#include "otbStringUtils.h"
#include "otbStringUtilities.h"
#include <boost/algorithm/string.hpp>
#include "otbMissingMetadataException.h"
namespace otb
{
class MissingMetadataException : public itk::ExceptionObject
{
public:
using itk::ExceptionObject::ExceptionObject;
};
/** \class MetadataSupplierInterface
*
* \brief Base class to access metadata information in files/images
......
/*
* Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef otbMissingMetadataException_h
#define otbMissingMetadataException_h
// "Do not include itkExceptionObject.h directly, include itkMacro.h instead."
#include "otbMacro.h"
namespace otb
{
/** \class MissingMetadataException
*
* \brief Exception to be used when metadata parsing fails
*
* \ingroup OTBMetadata
*/
class MissingMetadataException : public itk::ExceptionObject
{
public:
using itk::ExceptionObject::ExceptionObject;
};
} // namespace otb
#endif
\ No newline at end of file
......@@ -63,7 +63,7 @@ private:
PleiadesImageMetadataInterface(const Self&) = delete;
void operator=(const Self&) = delete;
void FetchTabulatedPhysicalGain(const MetaData::Time & date, ImageMetadata& imd);
void FetchTabulatedPhysicalGain(const MetaData::TimePoint & date, ImageMetadata& imd);
void FetchSolarIrradiance(const std::vector<double> & dimapSolarIrradiance, ImageMetadata& imd);
void FetchSatAngles(const std::vector<double> & incidenceAngles,
......
......@@ -48,7 +48,7 @@ class SarCalibrationLookupData;
struct OTBMetadata_EXPORT AzimuthFmRate
{
/** Zero Doppler azimuth time to which azimuth FM rate parameters apply */
MetaData::Time azimuthTime;
MetaData::TimePoint azimuthTime;
/** Two way slant range time origin used for azimuth FM rate calculation */
double t0;
/** Azimuth FM rate coefficients c0 c1 c2 */
......@@ -68,7 +68,7 @@ struct OTBMetadata_EXPORT AzimuthFmRate
struct OTBMetadata_EXPORT DopplerCentroid
{
/** Zero Doppler azimuth time of this Doppler centroid estimate */
MetaData::Time azimuthTime;
MetaData::TimePoint azimuthTime;
/* Two-way slant range time origin for Doppler centroid estimate */
double t0;
/* Doppler centroid estimated from data */
......@@ -92,7 +92,7 @@ struct OTBMetadata_EXPORT Orbit
using PointType = itk::Point<double, 3>;
/** Timestamp at which orbit state vectors apply */
MetaData::TimeType time;
MetaData::TimePoint time;
/** Position vector */
PointType position;
/** Velocity vector */
......@@ -111,8 +111,8 @@ struct OTBMetadata_EXPORT Orbit
*/
struct OTBMetadata_EXPORT BurstRecord
{
MetaData::TimeType azimuthStartTime;
MetaData::TimeType azimuthStopTime;
MetaData::TimePoint azimuthStartTime;
MetaData::TimePoint azimuthStopTime;
unsigned long startLine;
unsigned long endLine;
unsigned long startSample;
......@@ -134,7 +134,7 @@ struct OTBMetadata_EXPORT BurstRecord
struct OTBMetadata_EXPORT GCPTime
{
/** Azimuth time of the gcp */
MetaData::TimeType azimuthTime;
MetaData::TimePoint azimuthTime;
/** Slant range time of the gcp */
double slantRangeTime;
......@@ -150,7 +150,7 @@ struct OTBMetadata_EXPORT GCPTime
*/
struct CoordinateConversionRecord
{
MetaData::TimeType azimuthTime;
MetaData::TimePoint azimuthTime;
double rg0;
std::vector<double> coeffs;
......@@ -175,7 +175,7 @@ struct OTBMetadata_EXPORT SARParam
*/
std::vector<AzimuthFmRate> azimuthFmRates;
MetaData::DurationType azimuthTimeInterval;
MetaData::Duration azimuthTimeInterval;
double nearRangeTime;
double rangeSamplingRate;
double rangeResolution;
......@@ -233,8 +233,8 @@ struct OTBMetadata_EXPORT SARCalib
bool calibrationLookupFlag = false;
double rescalingFactor;
MetaData::Time calibrationStartTime;
MetaData::Time calibrationStopTime;
MetaData::TimePoint calibrationStartTime;
MetaData::TimePoint calibrationStopTime;
ArrayType radiometricCalibrationNoisePolynomialDegree;
ArrayType radiometricCalibrationAntennaPatternNewGainPolynomialDegree;
ArrayType radiometricCalibrationAntennaPatternOldGainPolynomialDegree;
......
......@@ -91,7 +91,7 @@ protected:
std::vector<Orbit> GetOrbits(const XMLMetadataSupplier&) const;
/* Fetch the burst records */
std::vector<BurstRecord> GetBurstRecords(const XMLMetadataSupplier&, const MetaData::DurationType & azimuthTimeInterval) const;
std::vector<BurstRecord> GetBurstRecords(const XMLMetadataSupplier&, const MetaData::Duration & azimuthTimeInterval) const;
/* Fetch coordinate conversion records (Sr0/Gr0) */
std::vector<CoordinateConversionRecord> GetCoordinateConversionRecord(const XMLMetadataSupplier &xmlMS,
......
......@@ -31,6 +31,7 @@ ENABLE_SHARED
OTBCommon
OTBGdalAdapters
OTBTinyXML
OTBDate
TEST_DEPENDS
OTBTestKernel
......
......@@ -151,8 +151,8 @@ std::vector<BurstRecord> CosmoImageMetadataInterface::CreateBurstRecord(const st
record.endLine = endLine;
record.endSample = endSample;
record.azimuthStartTime = MetaData::ReadFormattedDate(firstLineTimeStr, "%Y-%m-%dT%H:%M:%S%F");
record.azimuthStopTime = MetaData::ReadFormattedDate(lastLineTimeStr, "%Y-%m-%dT%H:%M:%S%F");
record.azimuthStartTime = MetaData::ReadFormattedDate(firstLineTimeStr, "%Y-%m-%dT%H:%M:%S");
record.azimuthStopTime = MetaData::ReadFormattedDate(lastLineTimeStr, "%Y-%m-%dT%H:%M:%S");