35 static constexpr const char * good_format =
"%ntYyCGgmUWVjdwuHIMSDFRT" ;
36 static constexpr unsigned int million = 1000000U ;
38 template <
typename Tp> TimeInterval interval( Tp start , Tp end )
40 using namespace std::chrono ;
43 auto d = end - start ;
45 auto s = (duration_cast<seconds>(d)).count() ; G_ASSERT( s >= 0 ) ;
46 typename std::make_unsigned<
decltype(s)>::type su = s ;
47 if(
sizeof(su) >
sizeof(TimeInterval::s_type) &&
48 su > std::numeric_limits<TimeInterval::s_type>::max() )
51 auto us = (duration_cast<microseconds>(d) % seconds(1)).count() ; G_ASSERT( us >= 0 ) ;
52 typename std::make_unsigned<
decltype(us)>::type usu = us ;
53 G_ASSERT( us <= std::numeric_limits<TimeInterval::us_type>::max() ) ;
55 return TimeInterval(
static_cast<TimeInterval::s_type
>(su) ,
static_cast<TimeInterval::us_type
>(usu) ) ;
70 if( std::time_t(-1) == std::mktime( &m_tm ) )
71 throw DateTime::Error() ;
76 struct std::tm tm = m_tm ;
78 std::time_t t = std::mktime( &tm ) ;
79 if( t == std::time_t(-1) )
80 throw DateTime::Error() ;
87 copy.
m_tm.tm_sec = 0 ;
88 return copy.epochTimeFromUtcImp() + m_tm.tm_sec ;
91std::time_t G::BrokenDownTime::epochTimeFromUtcImp()
const
93 static bool diff_set = false ;
94 static std::time_t diff = 0 ;
95 return epochTimeFromUtcImp( diff_set , diff ) ;
98std::time_t G::BrokenDownTime::epochTimeFromUtcImp(
bool & diff_set , std::time_t & diff )
const
100 constexpr int day = 24 * 60 * 60 ;
101 constexpr std::time_t dt = 60 * 15 ;
102 constexpr std::time_t day_and_a_bit = day + dt ;
103 constexpr std::time_t t_rounding = 30 ;
106 std::time_t t_base = epochTimeFromLocal() ;
109 if( diff_set && !sameMinute( SystemTime(t_base+diff+t_rounding).utc() ) )
118 auto t = t_base - day_and_a_bit ;
119 auto end = t_base + day_and_a_bit ;
120 for( diff = -day_and_a_bit ; t <= end ; t += dt , diff += dt )
122 if( sameMinute( SystemTime(t+t_rounding).utc() ) )
131 throw DateTime::Error(
"unsupported timezone" ) ;
133 return t_base + diff ;
139 std::time_t s = t.
s() ;
140 if( localtime_r( &s , &tm.
m_tm ) ==
nullptr )
141 throw DateTime::Error() ;
148 std::time_t s = t.
s() ;
149 if( gmtime_r( &s , &tm.
m_tm ) ==
nullptr )
150 throw DateTime::Error() ;
157 m_tm.tm_year = y - 1900 ;
158 m_tm.tm_mon = mon - 1 ;
164 if( std::time_t(-1) == std::mktime( &m_tm ) )
165 throw DateTime::Error() ;
170 return { year , month , day , 12 , 0 , 0 } ;
175 for(
const char * p = std::strchr(fmt,
'%') ; p && p[1] ; p = std::strchr(p+1,
'%') )
177 if( !std::strchr(DateTimeImp::good_format,p[1]) )
178 throw DateTime::Error() ;
181 if( std::strftime( &out[0] , out.size() , fmt , &m_tm ) == 0U )
182 throw DateTime::Error() ;
187 return str(
"%F %T" ) ;
192 std::size_t n = std::strlen( fmt ) ;
193 for(
const char * p = std::strchr(fmt,
'%') ; p && p[1] ; p = std::strchr(p+1,
'%') )
196 std::vector<char> buffer( n ) ;
198 buffer.at(buffer.size()-1U) =
'\0' ;
199 return std::string( &buffer[0] ) ;
204 return m_tm.tm_hour ;
219 return m_tm.tm_year + 1900 ;
224 return m_tm.tm_mon + 1 ;
229 return m_tm.tm_mday ;
234 return m_tm.tm_wday ;
240 year() == other.
year() &&
241 month() == other.
month() &&
242 day() == other.
day() &&
243 hour() == other.
hour() &&
244 min() == other.
min() ;
256 m_tp = std::chrono::system_clock::from_time_t(t) ;
257 m_tp += std::chrono::microseconds( us ) ;
262 return SystemTime( std::chrono::system_clock::now() ) ;
272 return DateTimeImp::interval( m_tp , end.m_tp ) ;
277 m_tp += std::chrono::microseconds( us ) ;
283 return s() == t.s() ;
298 using namespace std::chrono ;
299 return static_cast<unsigned int>((duration_cast<milliseconds>(m_tp.time_since_epoch()) % seconds(1)).count()) ;
304 using namespace std::chrono ;
305 return static_cast<unsigned int>((duration_cast<microseconds>(m_tp.time_since_epoch()) % seconds(1)).count()) ;
310 using namespace std::chrono ;
311 G_ASSERT( duration_cast<seconds>(m_tp.time_since_epoch()).count() == system_clock::to_time_t(m_tp) ) ;
312 return system_clock::to_time_t( m_tp ) ;
317 duration_type zero{0} ;
318 G_ASSERT(
SystemTime(time_point_type(zero)).s() == 0 ) ;
324 return m_tp < other.m_tp ;
329 return m_tp <= other.m_tp ;
334 return m_tp == other.m_tp ;
339 return !( *
this == other ) ;
344 return m_tp > other.m_tp ;
349 return m_tp >= other.m_tp ;
361 using namespace std::chrono ;
362 m_tp += seconds(i.
s()) ;
363 m_tp += microseconds(i.
us()) ;
368 int w =
static_cast<int>( stream.width() ) ;
369 char c = stream.fill() ;
372 << std::setw(6) << std::setfill(
'0')
374 << std::setw(w) << std::setfill(c) ;
377std::ostream & G::operator<<( std::ostream & stream ,
const SystemTime & t )
387 return TimerTime( std::chrono::steady_clock::now() ,
false ) ;
392 duration_type zero_duration{0} ;
393 return TimerTime( time_point_type(zero_duration) ,
true ) ;
398 return TimerTime( time_point_type(std::chrono::seconds(s)+std::chrono::microseconds(us)) , s==0 && us==0 ) ;
401G::TimerTime::TimerTime( time_point_type tp ,
bool is_zero ) :
407unsigned long G::TimerTime::test_s()
const
409 using namespace std::chrono ;
410 return static_cast<unsigned long>(duration_cast<seconds>(m_tp.time_since_epoch()).count()) ;
413unsigned long G::TimerTime::test_us()
const
415 using namespace std::chrono ;
416 return static_cast<unsigned long>((duration_cast<microseconds>(m_tp.time_since_epoch()) % seconds(1)).count()) ;
423 t.m_is_zero = m_is_zero && interval.
s() == 0U && interval.
us() == 0U ;
429 using namespace std::chrono ;
430 m_tp += seconds(i.
s()) ;
431 m_tp += microseconds(i.
us()) ;
432 m_is_zero = m_is_zero && i.
s() == 0U && i.
us() == 0U ;
442 return DateTimeImp::interval( m_tp , end.m_tp ) ;
447 using namespace std::chrono ;
449 duration_cast<seconds>(m_tp.time_since_epoch()) ==
450 duration_cast<seconds>(t.m_tp.time_since_epoch()) ;
455 return m_tp < other.m_tp ;
460 return m_tp <= other.m_tp ;
465 return m_tp == other.m_tp ;
470 return m_tp != other.m_tp ;
475 return m_tp > other.m_tp ;
480 return m_tp >= other.m_tp ;
512void G::TimeInterval::normalise()
514 using namespace G::DateTimeImp ;
515 if( m_us >= million )
519 if( m_us >= million )
521 increase( m_s , m_us / million ) ;
522 m_us = m_us % million ;
529 using namespace G::DateTimeImp ;
530 return TimeInterval( std::numeric_limits<s_type>::max() , million-1U ) ;
550 return m_s == other.m_s && m_us == other.m_us ;
555 return !( *
this == other ) ;
560 return m_s < other.m_s || ( m_s == other.m_s && m_us < other.m_us ) ;
565 return *
this == other || *
this < other ;
570 return m_s > other.m_s || ( m_s == other.m_s && m_us > other.m_us ) ;
575 return *
this == other || *
this > other ;
592void G::TimeInterval::increase(
unsigned int & s ,
unsigned int ds )
596 const bool overflow = s < old ;
598 throw DateTime::Error(
"overflow" ) ;
603 using namespace G::DateTimeImp ;
605 if( m_us >= million )
610 increase( m_s , i.m_s ) ;
613void G::TimeInterval::decrease(
unsigned int & s ,
unsigned int ds )
616 throw DateTime::Error(
"underflow" ) ;
622 using namespace G::DateTimeImp ;
629 decrease( m_s , i.m_s ) ;
634 int w =
static_cast<int>( stream.width() ) ;
635 char c = stream.fill() ;
638 << std::setw(6) << std::setfill(
'0')
640 << std::setw(w) << std::setfill(c) ;
643std::ostream & G::operator<<( std::ostream & stream ,
const TimeInterval & ti )
655 bool ahead = t_in < t_zone ;
656 TimeInterval i = ahead ? (t_zone-t_in) : (t_in-t_zone) ;
657 return Offset{ ahead , i.
s() } ;
662 std::ostringstream ss ;
663 ss << ( tz < 0 ?
"-" :
"+" ) ;
664 if( tz < 0 ) tz = -tz ;
665 ss << (tz/10) << (tz%10) <<
"00" ;
671 unsigned int hh = (offset.second+30U) / 3600U ;
672 unsigned int mm = ((offset.second+30U) / 60U) % 60 ;
674 std::ostringstream ss ;
675 char sign = (offset.first || (hh==0&&mm==0)) ?
'+' :
'-' ;
676 ss << sign << (hh/10U) << (hh%10U) << (mm/10) << (mm%10) ;
An encapsulation of 'struct std::tm'.
int wday() const
Returns week day where sunday=0 and saturday=6.
int day() const
Returns the 1..31 month-day value.
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
Returns true if this and the other broken-down times are the same, at minute resolution with no round...
std::string str() const
Returns str() using a "%F %T" format.
BrokenDownTime(const struct std::tm &)
Constructor.
int sec() const
Returns the 0..59 or 0..60 seconds value.
static BrokenDownTime utc(SystemTime)
Factory function for the utc time of the given epoch time.
static BrokenDownTime midday(int year, int month, int day)
Factory function for midday on the given date.
int month() const
Returns the 1..12 month value.
void format(std::vector< char > &out, const char *fmt) const
Puts the formatted date, including a terminating null character, into the given buffer.
static BrokenDownTime local(SystemTime)
Factory function for the locale-dependent local time of the given epoch time.
int hour() const
Returns the 0..23 hour value.
int year() const
Returns the four-digit year value.
std::time_t epochTimeFromUtc() const
Searches std::mktime() over the range of all timezones to convert this utc broken-down time into epoc...
int min() const
Returns the 0..59 minute value.
static Offset offset(SystemTime)
Returns the offset in seconds between UTC and localtime as at the given system time.
static std::string offsetString(Offset offset)
Converts the given utc/localtime offset into a five-character "+/-hhmm" string.
Represents a unix-epoch time with microsecond resolution.
TimeInterval operator-(const SystemTime &start) const
Returns the given start time's interval() compared to this end time.
static SystemTime now()
Factory function for the current time.
std::time_t s() const noexcept
Returns the number of seconds since the start of the epoch.
SystemTime operator+(TimeInterval) const
Returns this time with given interval added.
unsigned int ms() const
Returns the millisecond fraction.
unsigned int us() const
Returns the microsecond fraction.
bool operator!=(const SystemTime &) const
Comparison operator.
BrokenDownTime local() const
Returns the locale-dependent local broken-down time.
bool operator>(const SystemTime &) const
Comparison operator.
void streamOut(std::ostream &) const
Streams out the time comprised of the s() value, a decimal point, and then the six-digit us() value.
TimeInterval interval(const SystemTime &end) const
Returns the interval between this time and the given end time.
bool sameSecond(const SystemTime &other) const noexcept
Returns true if this time and the other time are the same, at second resolution.
bool operator<=(const SystemTime &) const
Comparison operator.
bool operator>=(const SystemTime &) const
Comparison operator.
static SystemTime zero()
Factory function for the start of the epoch.
SystemTime(std::time_t, unsigned long us=0UL) noexcept
Constructor.
BrokenDownTime utc() const
Returns the utc broken-down time.
void operator+=(TimeInterval)
Adds the given interval. Throws on overflow.
bool operator<(const SystemTime &) const
Comparison operator.
bool operator==(const SystemTime &) const
Comparison operator.
An interval between two G::SystemTime values or two G::TimerTime values.
TimeInterval(unsigned int s, unsigned int us=0U)
Constructor.
TimeInterval operator+(const TimeInterval &) const
Returns the combined interval. Throws on overflow.
static TimeInterval zero()
Factory function for the zero interval.
void operator-=(TimeInterval)
Subtracts the given interval. Throws on underflow.
bool operator==(const TimeInterval &) const
Comparison operator.
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 operator+=(TimeInterval)
Adds the given interval. Throws on overflow.
bool operator>(const TimeInterval &) const
Comparison operator.
TimeInterval operator-(const TimeInterval &) const
Returns the interval difference. Throws on underflow.
bool operator<(const TimeInterval &) const
Comparison operator.
bool operator!=(const TimeInterval &) const
Comparison operator.
void streamOut(std::ostream &) const
Streams out the interval.
bool operator>=(const TimeInterval &) const
Comparison operator.
bool operator<=(const TimeInterval &) const
Comparison operator.
A monotonically increasing subsecond-resolution timestamp, notionally unrelated to time_t.
static TimerTime now()
Factory function for the current steady-clock time.
TimerTime operator+(const TimeInterval &) const
Returns this time with given interval added.
bool operator>(const TimerTime &) const
Comparison operator.
TimeInterval interval(const TimerTime &end) const
Returns the interval between this time and the given end time.
bool operator==(const TimerTime &) const
Comparison operator.
bool operator!=(const TimerTime &) const
Comparison operator.
TimeInterval operator-(const TimerTime &start) const
Returns the given start time's interval() compared to this end time.
bool sameSecond(const TimerTime &other) const
Returns true if this time and the other time are the same, at second resolution.
void operator+=(TimeInterval)
Adds an interval.
static TimerTime zero()
Factory function for the start of the epoch.
bool operator<(const TimerTime &) const
Comparison operator.
bool operator<=(const TimerTime &) const
Comparison operator.
bool operator>=(const TimerTime &) const
Comparison operator.