404 lines
12 KiB
C++
404 lines
12 KiB
C++
//
|
|
// Copyright (C) 2001-2022 Graeme Walker <graeme_walker@users.sourceforge.net>
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
// ===
|
|
///
|
|
/// \file gdatetime.h
|
|
///
|
|
|
|
#ifndef G_DATE_TIME_H
|
|
#define G_DATE_TIME_H
|
|
|
|
#include "gdef.h"
|
|
#include "gexception.h"
|
|
#include <chrono>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <iostream>
|
|
|
|
namespace G
|
|
{
|
|
class DateTime ;
|
|
class SystemTime ;
|
|
class TimerTime ;
|
|
class TimeInterval ;
|
|
class BrokenDownTime ;
|
|
class DateTimeTest ;
|
|
}
|
|
|
|
//| \class G::BrokenDownTime
|
|
/// An encapsulation of 'struct std::tm'.
|
|
///
|
|
class G::BrokenDownTime
|
|
{
|
|
public:
|
|
explicit BrokenDownTime( const struct std::tm & ) ;
|
|
///< Constructor.
|
|
|
|
BrokenDownTime( int year , int month , int day , int hh , int mm , int ss ) ;
|
|
///< Constructor.
|
|
|
|
static BrokenDownTime null() ;
|
|
///< Factory function for an unusable object with bogus
|
|
///< component values.
|
|
|
|
static BrokenDownTime midday( int year , int month , int day ) ;
|
|
///< Factory function for midday on the given date.
|
|
|
|
static BrokenDownTime midnight( int year , int month , int day ) ;
|
|
///< Factory function for midnight starting the given date.
|
|
|
|
static BrokenDownTime local( SystemTime ) ;
|
|
///< Factory function for the locale-dependent local time of the
|
|
///< given epoch time. See also SystemTime::local().
|
|
|
|
static BrokenDownTime utc( SystemTime ) ;
|
|
///< Factory function for the utc time of the given epoch time.
|
|
///< See also SystemTime::utc().
|
|
|
|
bool format( char * out , std::size_t out_size , const char * fmt ) const ;
|
|
///< Puts the formatted date, including a terminating null character,
|
|
///< into the given output buffer. Returns false if the output buffer
|
|
///< is too small. Only simple non-locale-dependent format specifiers
|
|
///< are allowed, and these allowed specifiers explicitly exclude
|
|
///< '%z' and '%Z'.
|
|
|
|
void format( std::vector<char> & out , const char * fmt ) const ;
|
|
///< Overload for an output vector. Throws if the vector is
|
|
///< too small for the result (with its null terminator).
|
|
|
|
std::string str( const char * fmt ) const ;
|
|
///< Returns the formatted date, with the same restrictions
|
|
///< as format().
|
|
|
|
std::string str() const ;
|
|
///< Returns str() using a "%F %T" format.
|
|
|
|
int year() const ;
|
|
///< Returns the four-digit year value.
|
|
|
|
int month() const ;
|
|
///< Returns the 1..12 month value.
|
|
|
|
int day() const ;
|
|
///< Returns the 1..31 month-day value.
|
|
|
|
int hour() const ;
|
|
///< Returns the 0..23 hour value.
|
|
|
|
int min() const ;
|
|
///< Returns the 0..59 minute value.
|
|
|
|
int sec() const ;
|
|
///< Returns the 0..59 or 0..60 seconds value.
|
|
|
|
int wday() const ;
|
|
///< Returns week day where sunday=0 and saturday=6.
|
|
|
|
std::time_t epochTimeFromUtc() const ;
|
|
///< Searches std::mktime() over the range of all timezones
|
|
///< to convert this utc broken-down time into epoch time.
|
|
|
|
std::time_t epochTimeFromLocal() const ;
|
|
///< Uses std::mktime() to convert this locale-dependent
|
|
///< local broken-down time into epoch time.
|
|
|
|
bool sameMinute( const BrokenDownTime & other ) const noexcept ;
|
|
///< Returns true if this and the other broken-down
|
|
///< times are the same, at minute resolution with
|
|
///< no rounding.
|
|
|
|
private:
|
|
BrokenDownTime() ;
|
|
|
|
private:
|
|
friend class G::DateTimeTest ;
|
|
struct std::tm m_tm{} ;
|
|
} ;
|
|
|
|
//| \class G::SystemTime
|
|
/// Represents a unix-epoch time with microsecond resolution.
|
|
///
|
|
class G::SystemTime
|
|
{
|
|
public:
|
|
static SystemTime now() ;
|
|
///< Factory function for the current time.
|
|
|
|
static SystemTime zero() ;
|
|
///< Factory function for the start of the epoch.
|
|
|
|
explicit SystemTime( std::time_t , unsigned long us = 0UL ) noexcept ;
|
|
///< Constructor. The first parameter should be some
|
|
///< large positive number. The second parameter can be
|
|
///< more than 10^6.
|
|
|
|
bool sameSecond( const SystemTime & other ) const noexcept ;
|
|
///< Returns true if this time and the other time are the same,
|
|
///< at second resolution.
|
|
|
|
BrokenDownTime local() const ;
|
|
///< Returns the locale-dependent local broken-down time.
|
|
|
|
BrokenDownTime utc() const ;
|
|
///< Returns the utc broken-down time.
|
|
|
|
unsigned int ms() const ;
|
|
///< Returns the millisecond fraction.
|
|
|
|
unsigned int us() const ;
|
|
///< Returns the microsecond fraction.
|
|
|
|
std::time_t s() const noexcept ;
|
|
///< Returns the number of seconds since the start of the epoch.
|
|
|
|
bool operator<( const SystemTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator<=( const SystemTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator==( const SystemTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator!=( const SystemTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator>( const SystemTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator>=( const SystemTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
void operator+=( TimeInterval ) ;
|
|
///< Adds the given interval. Throws on overflow.
|
|
|
|
SystemTime operator+( TimeInterval ) const ;
|
|
///< Returns this time with given interval added.
|
|
///< Throws on overflow.
|
|
|
|
TimeInterval operator-( const SystemTime & start ) const ;
|
|
///< Returns the given start time's interval() compared
|
|
///< to this end time. Returns TimeInterval::zero() on
|
|
///< underflow or TimeInterval::limit() on overflow of
|
|
///< TimeInterval::s_type.
|
|
|
|
TimeInterval interval( const SystemTime & end ) const ;
|
|
///< Returns the interval between this time and the given
|
|
///< end time. Returns TimeInterval::zero() on underflow or
|
|
///< TimeInterval::limit() on overflow of TimeInterval::s_type.
|
|
|
|
void streamOut( std::ostream & ) const ;
|
|
///< Streams out the time comprised of the s() value, a decimal
|
|
///< point, and then the six-digit us() value.
|
|
|
|
private:
|
|
friend class G::DateTimeTest ;
|
|
using duration_type = std::chrono::system_clock::duration ;
|
|
using time_point_type = std::chrono::time_point<std::chrono::system_clock> ;
|
|
explicit SystemTime( time_point_type ) ;
|
|
SystemTime & add( unsigned long us ) ;
|
|
|
|
private:
|
|
time_point_type m_tp ;
|
|
} ;
|
|
|
|
//| \class G::TimerTime
|
|
/// A monotonically increasing subsecond-resolution timestamp, notionally
|
|
/// unrelated to time_t.
|
|
///
|
|
class G::TimerTime
|
|
{
|
|
public:
|
|
static TimerTime now() ;
|
|
///< Factory function for the current steady-clock time.
|
|
|
|
static TimerTime zero() ;
|
|
///< Factory function for the start of the epoch.
|
|
|
|
bool isZero() const noexcept ;
|
|
///< Returns true if zero().
|
|
|
|
bool sameSecond( const TimerTime & other ) const ;
|
|
///< Returns true if this time and the other time are the same,
|
|
///< at second resolution.
|
|
|
|
bool operator<( const TimerTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator<=( const TimerTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator==( const TimerTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator!=( const TimerTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator>( const TimerTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator>=( const TimerTime & ) const ;
|
|
///< Comparison operator.
|
|
|
|
TimerTime operator+( const TimeInterval & ) const ;
|
|
///< Returns this time with given interval added.
|
|
|
|
void operator+=( TimeInterval ) ;
|
|
///< Adds an interval.
|
|
|
|
TimeInterval operator-( const TimerTime & start ) const ;
|
|
///< Returns the given start time's interval() compared
|
|
///< to this end time. Returns TimeInterval::zero() on
|
|
///< underflow or TimeInterval::limit() if the
|
|
///< TimeInterval::s_type value overflows.
|
|
|
|
TimeInterval interval( const TimerTime & end ) const ;
|
|
///< Returns the interval between this time and the given
|
|
///< end time. Returns TimeInterval::zero() on underflow or
|
|
///< TimeInterval::limit() if the TimeInterval::s_type
|
|
///< value overflows.
|
|
|
|
private:
|
|
friend class G::DateTimeTest ;
|
|
using duration_type = std::chrono::steady_clock::duration ;
|
|
using time_point_type = std::chrono::time_point<std::chrono::steady_clock> ;
|
|
TimerTime( time_point_type , bool ) ;
|
|
static TimerTime test( int , int ) ;
|
|
unsigned long s() const ; // DateTimeTest
|
|
unsigned long us() const ; // DateTimeTest
|
|
std::string str() const ; // DateTimeTest
|
|
|
|
private:
|
|
bool m_is_zero ;
|
|
time_point_type m_tp ;
|
|
} ;
|
|
|
|
inline
|
|
bool G::TimerTime::isZero() const noexcept
|
|
{
|
|
return m_is_zero ;
|
|
}
|
|
|
|
//| \class G::TimeInterval
|
|
/// An interval between two G::SystemTime values or two G::TimerTime
|
|
/// values.
|
|
///
|
|
class G::TimeInterval
|
|
{
|
|
public:
|
|
using s_type = unsigned int ;
|
|
using us_type = unsigned int ;
|
|
|
|
explicit TimeInterval( unsigned int s , unsigned int us = 0U ) ;
|
|
///< Constructor.
|
|
|
|
TimeInterval( const SystemTime & start , const SystemTime & end ) ;
|
|
///< Constructor. Constructs a zero interval if 'end' is before
|
|
///< 'start', and the limit() interval if 'end' is too far
|
|
///< ahead of 'start' for the underlying type.
|
|
|
|
TimeInterval( const TimerTime & start , const TimerTime & end ) ;
|
|
///< Constructor. Overload for TimerTime.
|
|
|
|
static TimeInterval zero() ;
|
|
///< Factory function for the zero interval.
|
|
|
|
static TimeInterval limit() ;
|
|
///< Factory function for the maximum valid interval.
|
|
|
|
unsigned int s() const ;
|
|
///< Returns the number of seconds.
|
|
|
|
unsigned int us() const ;
|
|
///< Returns the fractional microseconds part.
|
|
|
|
void streamOut( std::ostream & ) const ;
|
|
///< Streams out the interval.
|
|
|
|
bool operator<( const TimeInterval & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator<=( const TimeInterval & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator==( const TimeInterval & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator!=( const TimeInterval & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator>( const TimeInterval & ) const ;
|
|
///< Comparison operator.
|
|
|
|
bool operator>=( const TimeInterval & ) const ;
|
|
///< Comparison operator.
|
|
|
|
TimeInterval operator+( const TimeInterval & ) const ;
|
|
///< Returns the combined interval. Throws on overflow.
|
|
|
|
TimeInterval operator-( const TimeInterval & ) const ;
|
|
///< Returns the interval difference. Throws on underflow.
|
|
|
|
void operator+=( TimeInterval ) ;
|
|
///< Adds the given interval. Throws on overflow.
|
|
|
|
void operator-=( TimeInterval ) ;
|
|
///< Subtracts the given interval. Throws on underflow.
|
|
|
|
private:
|
|
void normalise() ;
|
|
static void increase( unsigned int & s , unsigned int ds = 1U ) ;
|
|
static void decrease( unsigned int & s , unsigned int ds = 1U ) ;
|
|
|
|
private:
|
|
unsigned int m_s ;
|
|
unsigned int m_us ;
|
|
} ;
|
|
|
|
namespace G
|
|
{
|
|
std::ostream & operator<<( std::ostream & , const SystemTime & ) ;
|
|
std::ostream & operator<<( std::ostream & , const TimeInterval & ) ;
|
|
}
|
|
|
|
//| \class G::DateTime
|
|
/// A static class that knows about timezone offsets.
|
|
///
|
|
class G::DateTime
|
|
{
|
|
public:
|
|
G_EXCEPTION_CLASS( Error , "date/time error" ) ;
|
|
using Offset = std::pair<bool,unsigned int> ;
|
|
|
|
static Offset offset( SystemTime ) ;
|
|
///< Returns the offset in seconds between UTC and localtime
|
|
///< as at the given system time. The returned pair has 'first'
|
|
///< set to true if localtime is ahead of (ie. east of) UTC.
|
|
|
|
static std::string offsetString( Offset offset ) ;
|
|
///< Converts the given utc/localtime offset into a five-character
|
|
///< "+/-hhmm" string.
|
|
///< See also RFC-2822.
|
|
|
|
static std::string offsetString( int hh ) ;
|
|
///< Overload for a signed integer timezone.
|
|
|
|
public:
|
|
DateTime() = delete ;
|
|
} ;
|
|
|
|
#endif
|