588 lines
20 KiB
C++
588 lines
20 KiB
C++
/***************************************************************************
|
|
* Copyright (C) gempa GmbH *
|
|
* All rights reserved. *
|
|
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
|
* *
|
|
* GNU Affero General Public License Usage *
|
|
* This file may be used under the terms of the GNU Affero *
|
|
* Public License version 3.0 as published by the Free Software Foundation *
|
|
* and appearing in the file LICENSE included in the packaging of this *
|
|
* file. Please review the following information to ensure the GNU Affero *
|
|
* Public License version 3.0 requirements will be met: *
|
|
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
|
* *
|
|
* Other Usage *
|
|
* Alternatively, this file may be used in accordance with the terms and *
|
|
* conditions contained in a signed written agreement between you and *
|
|
* gempa GmbH. *
|
|
***************************************************************************/
|
|
|
|
|
|
#ifndef SEISCOMP_CORE_DATETIME_H
|
|
#define SEISCOMP_CORE_DATETIME_H
|
|
|
|
|
|
#include <cstdint>
|
|
#include <chrono>
|
|
#include <limits>
|
|
#include <iostream>
|
|
#include <cmath>
|
|
#include <string_view>
|
|
|
|
|
|
namespace Seiscomp {
|
|
namespace Core {
|
|
|
|
|
|
/**
|
|
* @brief The TimeSpan class holds the amount of microseconds passed between
|
|
* two times.
|
|
*
|
|
* Internally it is represented with a std::chrono::duration with microsecond
|
|
* precision. It can be constructed from a std::chrono::duration object
|
|
* Its binary represention is 64bit signed integer regardless of the
|
|
* underlying architecture.
|
|
*
|
|
* The limit of a representable time span is +/-32768 years.
|
|
*/
|
|
class TimeSpan {
|
|
public:
|
|
using Storage = int64_t;
|
|
using Weeks = std::chrono::duration<Storage, std::ratio<7*86400> >;
|
|
using Days = std::chrono::duration<Storage, std::ratio<86400> >;
|
|
using Hours = std::chrono::duration<Storage, std::ratio<3600> >;
|
|
using Minutes = std::chrono::duration<Storage, std::ratio<60> >;
|
|
using Seconds = std::chrono::duration<Storage, std::ratio<1> >;
|
|
using MilliSeconds = std::chrono::duration<Storage, std::milli>;
|
|
using MicroSeconds = std::chrono::duration<Storage, std::micro>;
|
|
using F1 = std::chrono::duration<Storage, std::ratio<1, 10> >;
|
|
using F2 = std::chrono::duration<Storage, std::ratio<1, 100> >;
|
|
using F3 = std::chrono::duration<Storage, std::ratio<1, 1000> >;
|
|
using F4 = std::chrono::duration<Storage, std::ratio<1, 10000> >;
|
|
using F5 = std::chrono::duration<Storage, std::ratio<1, 100000> >;
|
|
using F6 = std::chrono::duration<Storage, std::ratio<1, 1000000> >;
|
|
using Duration = MicroSeconds;
|
|
|
|
static const double MinSpan;
|
|
static const double MaxSpan;
|
|
static const Storage MinSeconds;
|
|
static const Storage MaxSeconds;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// X'truction
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
TimeSpan() = default;
|
|
TimeSpan(const TimeSpan &other) = default;
|
|
constexpr TimeSpan(Storage secs, Storage usecs = 0);
|
|
TimeSpan(double ts);
|
|
|
|
template<typename Rep, typename Period>
|
|
constexpr TimeSpan(const std::chrono::duration<Rep, Period> &duration);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Assignment operators
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
//! Assigns integer epoch seconds
|
|
TimeSpan &operator=(int t);
|
|
//! Assigns integer epoch seconds
|
|
TimeSpan &operator=(Storage t);
|
|
//! Assigns floating point epoch seconds
|
|
TimeSpan &operator=(double t);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Comparison operators
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
constexpr bool operator==(const TimeSpan &other) const noexcept;
|
|
constexpr bool operator!=(const TimeSpan &other) const noexcept;
|
|
constexpr bool operator<=(const TimeSpan &other) const noexcept;
|
|
constexpr bool operator<(const TimeSpan &other) const noexcept;
|
|
constexpr bool operator>=(const TimeSpan &other) const noexcept;
|
|
constexpr bool operator>(const TimeSpan &other) const noexcept;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Arithmetic operators
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
constexpr TimeSpan operator+(const TimeSpan &other) const;
|
|
constexpr TimeSpan operator-(const TimeSpan &other) const;
|
|
constexpr TimeSpan operator*(int op) const;
|
|
constexpr TimeSpan operator*(size_t op) const;
|
|
constexpr TimeSpan operator*(double op) const;
|
|
constexpr TimeSpan operator/(int op) const;
|
|
constexpr TimeSpan operator/(size_t op) const;
|
|
constexpr TimeSpan operator/(double op) const;
|
|
constexpr TimeSpan operator-() const;
|
|
TimeSpan &operator+=(const TimeSpan &other);
|
|
TimeSpan &operator-=(const TimeSpan &other);
|
|
TimeSpan &operator*=(int op);
|
|
TimeSpan &operator*=(size_t op);
|
|
TimeSpan &operator*=(double op);
|
|
TimeSpan &operator/=(int op);
|
|
TimeSpan &operator/=(size_t op);
|
|
TimeSpan &operator/=(double op);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Conversion operators
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
constexpr explicit operator Duration() const noexcept;
|
|
constexpr explicit operator double() const noexcept;
|
|
//! Returns whether the timespan is empty or not.
|
|
constexpr explicit operator bool() const noexcept;
|
|
|
|
//! Returns an std::chrono::time_point
|
|
constexpr const Duration &repr() const noexcept;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Setter and getter
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
/**
|
|
* @brief Returns the maximum number of full seconds of this
|
|
* time span.
|
|
* @return Number of full seconds.
|
|
*/
|
|
constexpr Storage seconds() const;
|
|
|
|
/**
|
|
* @brief Returns the fractional part of the time span in
|
|
* microseconds.
|
|
* The number of microseconds returns is guaranteed to be less than
|
|
* one million (1000000).
|
|
* @return Fraction in microseconds.
|
|
*/
|
|
constexpr Storage microseconds() const noexcept;
|
|
|
|
/**
|
|
* @brief Returns this time span expressed in microseconds.
|
|
* @return Number of ticks in microseconds.
|
|
*/
|
|
constexpr Storage count() const noexcept;
|
|
|
|
//! Returns the absolute value of time
|
|
TimeSpan abs() const;
|
|
|
|
TimeSpan &set(Storage seconds, Storage usecs = 0);
|
|
|
|
void get(int *days, int *hours = nullptr,
|
|
int *minutes = nullptr, int *seconds = nullptr) const;
|
|
|
|
[[deprecated("Use get() instead")]]
|
|
void elapsedTime(int *days, int *hours = nullptr,
|
|
int *minutes = nullptr, int *seconds = nullptr) const;
|
|
|
|
//! Sets the microseconds
|
|
TimeSpan &setUSecs(Storage);
|
|
|
|
/**
|
|
* @brief Returns the time span in frational seconds.
|
|
* @return Fractional seconds as double.
|
|
*/
|
|
constexpr double length() const;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Public interface
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
/**
|
|
* @return A string representing the current time span.
|
|
*/
|
|
std::string toString() const;
|
|
|
|
/**
|
|
* @brief Converts a string to a time span representation.
|
|
* @param sv The input string_view
|
|
* @return The conversion result
|
|
*/
|
|
bool fromString(std::string_view sv);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Private members
|
|
// ----------------------------------------------------------------------
|
|
private:
|
|
Duration _repr{0};
|
|
|
|
|
|
friend class Time;
|
|
};
|
|
|
|
|
|
namespace Literals {
|
|
|
|
|
|
TimeSpan operator "" _weeks(long double weeks);
|
|
TimeSpan operator "" _weeks(unsigned long long int weeks);
|
|
TimeSpan operator "" _days(long double days);
|
|
TimeSpan operator "" _days(unsigned long long int days);
|
|
TimeSpan operator "" _hours(long double hours);
|
|
TimeSpan operator "" _hours(unsigned long long int hours);
|
|
TimeSpan operator "" _minutes(long double minutes);
|
|
TimeSpan operator "" _minutes(unsigned long long int minutes);
|
|
TimeSpan operator "" _seconds(long double seconds);
|
|
TimeSpan operator "" _seconds(unsigned long long int seconds);
|
|
TimeSpan operator "" _milliseconds(long double milliseconds);
|
|
TimeSpan operator "" _milliseconds(unsigned long long int milliseconds);
|
|
|
|
|
|
}
|
|
|
|
std::ostream &operator<<(std::ostream &os, const TimeSpan &ts);
|
|
|
|
|
|
/**
|
|
* @brief The Time class implements the representation of a point in time
|
|
* with microsecond precision.
|
|
*
|
|
* Internally it is represented with a date::time_point instance from the
|
|
* C++ date library of Howard Hinnant [1].
|
|
*
|
|
* Due to microseconds precision the valid date range is defined from
|
|
* -32768-01-01 to 32767-12-31.
|
|
*
|
|
* [1] https://github.com/HowardHinnant/date
|
|
*/
|
|
class Time {
|
|
// ----------------------------------------------------------------------
|
|
// Public types
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
using Storage = TimeSpan::Storage;
|
|
using Duration = TimeSpan::Duration;
|
|
using TimePoint = std::chrono::time_point<std::chrono::system_clock, Duration>;
|
|
|
|
static Time Null;
|
|
|
|
static const double MinTime;
|
|
static const double MaxTime;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// X'truction
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
Time() = default;
|
|
Time(const Time &other) = default;
|
|
explicit constexpr Time(const TimePoint &tp);
|
|
explicit constexpr Time(Storage epochSeconds, Storage microSeconds = 0);
|
|
explicit Time(double);
|
|
Time(int year, int month, int day,
|
|
int hour = 0, int min = 0, int sec = 0,
|
|
int usec = 0);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Assignment operators
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
Time &operator=(double epoch);
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Comparison operators
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
constexpr bool operator==(const Time &other) const noexcept;
|
|
constexpr bool operator!=(const Time &other) const noexcept;
|
|
constexpr bool operator<(const Time &other) const noexcept;
|
|
constexpr bool operator<=(const Time &other) const noexcept;
|
|
constexpr bool operator>(const Time &other) const noexcept;
|
|
constexpr bool operator>=(const Time &other) const noexcept;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Arithmetic operators
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
Time &operator+=(const TimeSpan &ts);
|
|
Time &operator-=(const TimeSpan &ts);
|
|
|
|
constexpr Time operator+(const TimeSpan &ts) const;
|
|
constexpr Time operator-(const TimeSpan &ts) const;
|
|
constexpr TimeSpan operator-(const Time &tp) const;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Conversion operators
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
constexpr explicit operator TimePoint() const noexcept;
|
|
constexpr explicit operator double() const noexcept;
|
|
[[deprecated("Use OPT(Time) instead")]]
|
|
constexpr explicit operator bool() const noexcept;
|
|
constexpr const TimePoint &repr() const noexcept;
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Public interface
|
|
// ----------------------------------------------------------------------
|
|
public:
|
|
/**
|
|
* @brief Returns whether the time object is a valid time or not.
|
|
* Internally the minimum possible value is used to declare an invalid
|
|
* time which is for backwards compatibility 1970-01-01 00:00:00.
|
|
* @return True if valid, false otherwise.
|
|
*/
|
|
[[deprecated("Use OPT(Time) instead")]]
|
|
constexpr bool valid() const;
|
|
|
|
/**
|
|
* @brief Sets the time object with y/m/d and h/m/s/u individually.
|
|
* The resulting time will be defined in seconds from Jan. 1, 1970 UTC.
|
|
* If local time is desired then call toLocalTime() afterwards.
|
|
* \code
|
|
* Time t;
|
|
* t.set(2020,1,1,12,00,00).toLocalTime()
|
|
* \endcode
|
|
* @param year The year between -32767 and 32768
|
|
* @param month The month between 1 and 12
|
|
* @param day The day between 1 and 31
|
|
* @param hour The hour of the day between 0 and 23
|
|
* @param min The minute of the hour between 0 and 59
|
|
* @param sec The second of the minute between 0 and 59
|
|
* @param usec The microseconds of the second between 0 and 999999
|
|
* @return this instance
|
|
*/
|
|
Time &set(int year, int month, int day,
|
|
int hour, int min, int sec,
|
|
int usec);
|
|
|
|
/**
|
|
* @brief Retrieves individual date and time components.
|
|
* @param year The year between -32767 and 32768
|
|
* @param month The month of the year between 1 and 12
|
|
* @param day The day of the month between 1 and 31
|
|
* @param hour The hour of the day between 0 and 23
|
|
* @param min The minute of the hour between 0 and 59
|
|
* @param sec The second of the minute between 0 and 59
|
|
* @param usec The microseconds of the second between 0 and 999999
|
|
* @return Success flag
|
|
*/
|
|
bool get(int *year, int *month = nullptr, int *day = nullptr,
|
|
int *hour = nullptr, int *min = nullptr, int *sec = nullptr,
|
|
int *usec = nullptr) const;
|
|
|
|
/**
|
|
* @brief Sets the time object with y/d and h/m/s/u individually.
|
|
* The resulting time will be defined in seconds from Jan. 1, 1970 UTC.
|
|
* If local time is desired then call toLocalTime() afterwards.
|
|
* \code
|
|
* Time t;
|
|
* t.set(2020,1,1,12,00,00).toLocalTime()
|
|
* \endcode
|
|
* @param year The year between -32767 and 32768
|
|
* @param yday The day of the year between 0 and 365
|
|
* @param hour The hour of the day between 0 and 23
|
|
* @param min The minute of the hour between 0 and 59
|
|
* @param sec The second of the minute between 0 and 59
|
|
* @param usec The microseconds of the second between 0 and 999999
|
|
* @return this instance
|
|
*/
|
|
Time &set2(int year, int yday,
|
|
int hour, int min, int sec,
|
|
int usec);
|
|
|
|
/**
|
|
* @brief Retrieves individual date and time components.
|
|
* @param year The year between -32767 and 32768
|
|
* @param yday The day of the year between 0 and 365
|
|
* @param hour The hour of the day between 0 and 23
|
|
* @param min The minute of the hour between 0 and 59
|
|
* @param sec The second of the minute between 0 and 59
|
|
* @param usec The microseconds of the second between 0 and 999999
|
|
* @return Success flag
|
|
*/
|
|
bool get2(int *year, int *yday = nullptr,
|
|
int *hour = nullptr, int *min = nullptr, int *sec = nullptr,
|
|
int *usec = nullptr) const;
|
|
|
|
/**
|
|
* @brief Alias for utc()
|
|
* @return The current time in UTC
|
|
*/
|
|
Time &now();
|
|
|
|
/**
|
|
* This is an alias for utc().
|
|
* @return The current time in UTC
|
|
*/
|
|
Time &gmt();
|
|
|
|
/**
|
|
* @return The current time in UTC
|
|
*/
|
|
Time &utc();
|
|
|
|
/**
|
|
* @return The ISO string of the time in UTC
|
|
*/
|
|
std::string iso() const;
|
|
|
|
/**
|
|
* @return A string representing the current time point without
|
|
* time zone information, UTC time.
|
|
*/
|
|
std::string toString(const char *format) const;
|
|
|
|
/**
|
|
* @brief Converts the time point to a string in the current
|
|
* system's time zone.
|
|
* @param format The string format.
|
|
* @return The formatted string
|
|
*/
|
|
std::string toLocalString(const char *format) const;
|
|
|
|
/**
|
|
* @brief Converts the time point to a string in a given
|
|
* time zone.
|
|
* This method may throw an std::runtime_error if the provided time
|
|
* zone does not exist.
|
|
* @param format The string format.
|
|
* @return The formatted string
|
|
*/
|
|
std::string toZonedString(const char *format, const std::string &tz) const;
|
|
|
|
/**
|
|
* Converts a string into a time representation.
|
|
* @param str The string representation of the time
|
|
* @return The conversion result
|
|
*/
|
|
bool fromString(std::string_view sv);
|
|
|
|
/**
|
|
* Converts a string into a time representation.
|
|
* @param str The string representation of the time
|
|
* @param fmt The format string containing the conversion
|
|
* specification (-> toString)
|
|
* @return The conversion result
|
|
*/
|
|
bool fromString(std::string_view sv, const char *format);
|
|
|
|
/**
|
|
* @brief Converts a string to a Time object.
|
|
* This method throws a runtime_error if the input string cannot
|
|
* be parsed into a valid Time.
|
|
* @param str The string representation of the time
|
|
* @return A Time object
|
|
*/
|
|
static Time FromString(const std::string &str);
|
|
|
|
/**
|
|
* @brief Converts a string to a Time object.
|
|
* This method throws a runtime_error if the input string cannot
|
|
* be parsed into a valid Time given the format.
|
|
* @param str The string representation of the time
|
|
* @param fmt The format string containing the conversion
|
|
* specification (-> toString)
|
|
* @return A Time object
|
|
*/
|
|
static Time FromString(const std::string &str, const char *format);
|
|
|
|
/**
|
|
* @brief Constructs a time object from a year and the day of the year.
|
|
* @param year The year between -32767 and 32768
|
|
* @param doy The day of the year between 1 and 366. Note that in
|
|
* contrast to set2 and get2 the doy is not starting with 0
|
|
* at January 1st but with 1.
|
|
* @return
|
|
*/
|
|
static Time FromYearDay(int year, int doy);
|
|
|
|
/**
|
|
* @return The number of seconds since Jan. 1, 1970.
|
|
*
|
|
* Backwards compatibility alias for epochSeconds().
|
|
*/
|
|
[[deprecated("Use epochSeconds() instead")]]
|
|
constexpr Storage seconds() const;
|
|
|
|
/**
|
|
* @return The number of seconds since Jan. 1, 1970.
|
|
*/
|
|
constexpr Storage epochSeconds() const;
|
|
|
|
/**
|
|
* @return The number of seconds with fractional seconds since
|
|
* Jan. 1, 1970.
|
|
*/
|
|
constexpr double epoch() const;
|
|
|
|
/**
|
|
* @return Seconds fraction.
|
|
*/
|
|
constexpr int microseconds() const;
|
|
|
|
Time &setUSecs(Storage ms);
|
|
|
|
static Time FromEpoch(Storage secs, Storage usecs);
|
|
static Time FromEpoch(double secs);
|
|
|
|
//! Returns the current time in UTC. This is an alias for UTC().
|
|
static Time Now();
|
|
|
|
//! Returns the current time in GMT. This is an alias for UTC().
|
|
[[deprecated("Use UTC() instead")]] static Time GMT();
|
|
|
|
//! Returns the current time in UTC
|
|
static Time UTC();
|
|
|
|
//! Returns the current time as UTC plus the time zone offset.
|
|
static Time LocalTime();
|
|
|
|
static std::string LocalTimeZone();
|
|
|
|
//! Converts the time of the UTC representation to local time.
|
|
//! This effectively adds the local timezone offset.
|
|
Time toLocalTime() const;
|
|
|
|
//! Converts the time of the local time representation to UTC. This
|
|
//! effectively removes the local timezone offset.
|
|
Time toUTC() const;
|
|
|
|
//! Converts the time of the local time representation to UTC. This
|
|
//! effectively removes the local timezone offset.
|
|
[[deprecated("Use toUTC() instead")]] Time toGMT() const;
|
|
|
|
/**
|
|
* @brief Returns the local timezone offset with respect to the
|
|
* time currently stored.
|
|
* @return The local timezone offset as @TimeSpan
|
|
*/
|
|
TimeSpan localTimeZoneOffset() const;
|
|
|
|
/**
|
|
* @brief Returns the timezone offset for a given timezone.
|
|
*
|
|
* If the timezone is unknown then a runtime_error will be thrown.
|
|
* @return The timezone offset as @TimeSpan
|
|
*/
|
|
TimeSpan timeZoneOffset(const std::string &tzName) const;
|
|
|
|
|
|
private:
|
|
TimePoint _repr{Duration{0}};
|
|
};
|
|
|
|
|
|
std::ostream &operator<<(std::ostream &os, const Time &time);
|
|
|
|
|
|
#include "datetime.ipp"
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|