E-MailRelay

gdatetime.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gdatetime.cpp
19///
20
21#include "gdef.h"
22#include "gdatetime.h"
23#include "goptional.h"
24#include "gstr.h"
25#include "gassert.h"
26#include <sstream>
27#include <iomanip>
28#include <utility>
29#include <vector>
30#include <type_traits>
31
32 namespace G
33{
34 namespace DateTimeImp
35 {
36 static constexpr const char * good_format = "%ntYyCGgmUWVjdwuHIMSDFRT" ;
37 static constexpr unsigned int million = 1000000U ;
38
39 template <typename Tp> TimeInterval interval( Tp start , Tp end )
40 {
41 using namespace std::chrono ;
42 if( end <= start )
43 return TimeInterval::zero() ;
44 auto d = end - start ;
45
46 auto s = (duration_cast<seconds>(d)).count() ; G_ASSERT( s >= 0 ) ;
47 typename std::make_unsigned<decltype(s)>::type su = s ;
48 if( sizeof(su) > sizeof(TimeInterval::s_type) &&
49 su > std::numeric_limits<TimeInterval::s_type>::max() )
50 return TimeInterval::limit() ;
51
52 auto us = (duration_cast<microseconds>(d) % seconds(1)).count() ; G_ASSERT( us >= 0 ) ;
53 typename std::make_unsigned<decltype(us)>::type usu = us ;
54 G_ASSERT( us <= std::numeric_limits<TimeInterval::us_type>::max() ) ;
55
56 return TimeInterval( static_cast<TimeInterval::s_type>(su) , static_cast<TimeInterval::us_type>(usu) ) ;
57 }
58 bool operator<( const std::tm & a , const std::tm & b ) noexcept
59 {
60 if( a.tm_year < b.tm_year ) return true ;
61 if( a.tm_year > b.tm_year ) return false ;
62 if( a.tm_mon < b.tm_mon ) return true ;
63 if( a.tm_mon > b.tm_mon ) return false ;
64 if( a.tm_mday < b.tm_mday ) return true ;
65 if( a.tm_mday > b.tm_mday ) return false ;
66 if( a.tm_hour < b.tm_hour ) return true ;
67 if( a.tm_hour > b.tm_hour ) return false ;
68 if( a.tm_min < b.tm_min ) return true ;
69 if( a.tm_min > b.tm_min ) return false ;
70 return a.tm_sec < b.tm_sec ;
71 }
72 bool sameMinute( const std::tm & a , const std::tm & b ) noexcept
73 {
74 return
75 a.tm_year == b.tm_year &&
76 a.tm_mon == b.tm_mon &&
77 a.tm_mday == b.tm_mday &&
78 a.tm_hour == b.tm_hour &&
79 a.tm_min == b.tm_min ;
80 }
81 bool sameSecond( const std::tm & a , const std::tm & b ) noexcept
82 {
83 return sameMinute( a , b ) && a.tm_sec == b.tm_sec ;
84 }
85 void localtime_( std::tm & tm_out , std::time_t t_in )
86 {
87 if( localtime_r( &t_in , &tm_out ) == nullptr )
88 throw DateTime::Error() ;
89 tm_out.tm_isdst = -1 ;
90 }
91 void gmtime_( std::tm & tm_out , std::time_t t_in )
92 {
93 if( gmtime_r( &t_in , &tm_out ) == nullptr )
94 throw DateTime::Error() ;
95 tm_out.tm_isdst = -1 ;
96 }
97 std::time_t mktime_( std::tm & tm )
98 {
99 tm.tm_isdst = -1 ;
100 std::time_t t = std::mktime( &tm ) ;
101 if( t == std::time_t(-1) )
102 throw DateTime::Error() ;
103 return t ;
104 }
105 std::time_t mktimelocal( const std::tm & local_tm_in )
106 {
107 struct std::tm tm = local_tm_in ;
108 return mktime_( tm ) ;
109 }
110 std::time_t mktimeutc( const std::tm & utc_tm_in , std::time_t begin , std::time_t end )
111 {
112 // returns 't' such that std::gmtime(t) gives the target broken-down time -- does
113 // a binary search over the time_t range down to one second resolution
114 std::time_t count = end - begin ;
115 std::time_t t = begin ;
116 while( count > 0 )
117 {
118 std::time_t i = t ;
119 std::time_t step = count / 2 ;
120 i += step ;
121 std::tm tm {} ;
122 gmtime_( tm , i ) ;
123 if( tm < utc_tm_in )
124 {
125 t = ++i ;
126 count -= step + 1 ;
127 }
128 else
129 {
130 count = step ;
131 }
132 }
133 return t ;
134 }
135 }
136}
137
138 G::BrokenDownTime::BrokenDownTime() :
139 m_tm{}
140{
141 m_tm.tm_isdst = -1 ;
142}
143
144#ifndef G_LIB_SMALL
145 G::BrokenDownTime::BrokenDownTime( const struct std::tm & tm_in ) :
146 m_tm(tm_in)
147{
148 // dont trust the dst flag passed in -- force mktime()
149 // to do the extra work (strftime() does anyway)
150 m_tm.tm_isdst = -1 ;
151}
152#endif
153
154 G::BrokenDownTime::BrokenDownTime( int y , int mon , int d , int h , int min , int s ) :
155 m_tm{}
156{
157 m_tm.tm_year = y - 1900 ;
158 m_tm.tm_mon = mon - 1 ;
159 m_tm.tm_mday = d ;
160 m_tm.tm_hour = h ;
161 m_tm.tm_min = min ;
162 m_tm.tm_sec = s ;
163 m_tm.tm_isdst = -1 ;
164 m_tm.tm_wday = 0 ;
165 m_tm.tm_yday = 0 ;
166}
167
168#ifndef G_LIB_SMALL
169std::time_t G::BrokenDownTime::epochTimeFromLocal() const
170{
171 return DateTimeImp::mktimelocal( m_tm ) ;
172}
173#endif
174
175std::time_t G::BrokenDownTime::epochTimeFromUtc() const
176{
177 std::time_t t0 = DateTimeImp::mktimelocal( m_tm ) ;
178
179 static std::optional<std::time_t> memo ;
180 if( memo.has_value() )
181 {
182 std::tm tm {} ;
183 DateTimeImp::gmtime_( tm , t0+memo.value() ) ;
184 if( DateTimeImp::sameSecond(tm,m_tm) )
185 return t0 + memo.value() ;
186 }
187
188 std::time_t dt = 25 * 3600 + 10 ;
189 std::time_t begin = std::max(dt,t0) - dt ;
190 std::time_t end = t0 + dt ;
191 std::time_t t = DateTimeImp::mktimeutc( m_tm , begin , end ) ;
192 if( t == begin || t == end )
193 throw DateTime::Error( "timezone error" ) ;
194
195 memo = t - t0 ;
196 return t ;
197}
198
199#ifndef G_LIB_SMALL
200 G::BrokenDownTime G::BrokenDownTime::null()
201{
202 return {} ;
203}
204#endif
205
206 G::BrokenDownTime G::BrokenDownTime::local( SystemTime t )
207{
208 BrokenDownTime bdt ;
209 DateTimeImp::localtime_( bdt.m_tm , t.s() ) ;
210 return bdt ;
211}
212
213 G::BrokenDownTime G::BrokenDownTime::utc( SystemTime t )
214{
215 BrokenDownTime bdt ;
216 DateTimeImp::gmtime_( bdt.m_tm , t.s() ) ;
217 return bdt ;
218}
219
220 G::BrokenDownTime G::BrokenDownTime::midday( int year , int month , int day )
221{
222 return { year , month , day , 12 , 0 , 0 } ;
223}
224
225#ifndef G_LIB_SMALL
226 G::BrokenDownTime G::BrokenDownTime::midnight( int year , int month , int day )
227{
228 return { year , month , day , 0 , 0 , 0 } ;
229}
230#endif
231
232 bool G::BrokenDownTime::format( char * out , std::size_t out_size , const char * fmt ) const
233{
234 for( const char * p = std::strchr(fmt,'%') ; p && p[1] ; p = std::strchr(p+1,'%') )
235 {
236 if( std::strchr(DateTimeImp::good_format,p[1]) == nullptr )
237 throw DateTime::Error( "bad format string" ) ;
238 }
239
240 std::tm tm_copy = m_tm ;
241 DateTimeImp::mktime_( tm_copy ) ; // fill in isdst, wday, yday
242
243 return std::strftime( out , out_size , fmt , &tm_copy ) > 0U ;
244}
245
246 void G::BrokenDownTime::format( std::vector<char> & out , const char * fmt ) const
247{
248 if( !format( out.data() , out.size() , fmt ) )
249 throw DateTime::Error() ;
250}
251
252#ifndef G_LIB_SMALL
253std::string G::BrokenDownTime::str() const
254{
255 return str( "%F %T" ) ;
256}
257#endif
258
259std::string G::BrokenDownTime::str( const char * fmt ) const
260{
261 std::size_t n = std::strlen( fmt ) + 1U ;
262 for( const char * p = std::strchr(fmt,'%') ; p && p[1] ; p = std::strchr(p+1,'%') )
263 n += 10U ; // biggest allowed format is eg. %F -> "2001-12-31"
264
265 std::vector<char> buffer( n ) ;
266 format( buffer , fmt ) ;
267 buffer.at(buffer.size()-1U) = '\0' ; // just in case
268 return { buffer.data() } ;
269}
270
271 int G::BrokenDownTime::hour() const
272{
273 return m_tm.tm_hour ;
274}
275
276 int G::BrokenDownTime::min() const
277{
278 return m_tm.tm_min ;
279}
280
281 int G::BrokenDownTime::sec() const
282{
283 return m_tm.tm_sec ;
284}
285
286 int G::BrokenDownTime::year() const
287{
288 return m_tm.tm_year + 1900 ;
289}
290
291 int G::BrokenDownTime::month() const
292{
293 return m_tm.tm_mon + 1 ;
294}
295
296 int G::BrokenDownTime::day() const
297{
298 return m_tm.tm_mday ;
299}
300
301 int G::BrokenDownTime::wday() const
302{
303 std::tm tm_copy = m_tm ;
304 DateTimeImp::mktime_( tm_copy ) ;
305 return tm_copy.tm_wday ;
306}
307
308#ifndef G_LIB_SMALL
309 bool G::BrokenDownTime::sameMinute( const BrokenDownTime & other ) const noexcept
310{
311 return DateTimeImp::sameMinute( m_tm , other.m_tm ) ;
312}
313#endif
314
315// ==
316
317 G::SystemTime::SystemTime( time_point_type tp ) :
318 m_tp(tp)
319{
320}
321
322 G::SystemTime::SystemTime( std::time_t t , unsigned long us ) noexcept
323{
324 m_tp = std::chrono::system_clock::from_time_t(t) ;
325 m_tp += std::chrono::microseconds( us ) ;
326}
327
328 G::SystemTime G::SystemTime::now()
329{
330 return SystemTime( std::chrono::system_clock::now() ) ;
331}
332
333 G::TimeInterval G::SystemTime::operator-( const SystemTime & start ) const
334{
335 return start.interval( *this ) ;
336}
337
338 G::TimeInterval G::SystemTime::interval( const SystemTime & end ) const
339{
340 return DateTimeImp::interval( m_tp , end.m_tp ) ;
341}
342
343#ifndef G_LIB_SMALL
344 G::SystemTime & G::SystemTime::add( unsigned long us )
345{
346 m_tp += std::chrono::microseconds( us ) ;
347 return *this ;
348}
349#endif
350
351 bool G::SystemTime::sameSecond( const SystemTime & t ) const noexcept
352{
353 return s() == t.s() ;
354}
355
356 G::BrokenDownTime G::SystemTime::local() const
357{
358 return BrokenDownTime::local( *this ) ;
359}
360
361 G::BrokenDownTime G::SystemTime::utc() const
362{
363 return BrokenDownTime::utc( *this ) ;
364}
365
366#ifndef G_LIB_SMALL
367 unsigned int G::SystemTime::ms() const
368{
369 using namespace std::chrono ;
370 return static_cast<unsigned int>((duration_cast<milliseconds>(m_tp.time_since_epoch()) % seconds(1)).count()) ;
371}
372#endif
373
374 unsigned int G::SystemTime::us() const
375{
376 using namespace std::chrono ;
377 return static_cast<unsigned int>((duration_cast<microseconds>(m_tp.time_since_epoch()) % seconds(1)).count()) ;
378}
379
380std::time_t G::SystemTime::s() const noexcept
381{
382 using namespace std::chrono ;
383 G_ASSERT( duration_cast<seconds>(m_tp.time_since_epoch()).count() == system_clock::to_time_t(m_tp) ) ; // as per c++17
384 return system_clock::to_time_t( m_tp ) ;
385}
386
387#ifndef G_LIB_SMALL
388 G::SystemTime G::SystemTime::zero()
389{
390 duration_type zero{0} ;
391 G_ASSERT( SystemTime(time_point_type(zero)).s() == 0 ) ; // assert 1970 epoch as per c++17
392 return SystemTime( time_point_type(zero) ) ;
393}
394#endif
395
396#ifndef G_LIB_SMALL
397 bool G::SystemTime::isZero() const
398{
399 return m_tp == time_point_type( duration_type(0) ) ;
400}
401#endif
402
403 bool G::SystemTime::operator<( const SystemTime & other ) const
404{
405 return m_tp < other.m_tp ;
406}
407
408#ifndef G_LIB_SMALL
409 bool G::SystemTime::operator<=( const SystemTime & other ) const
410{
411 return m_tp <= other.m_tp ;
412}
413#endif
414
415 bool G::SystemTime::operator==( const SystemTime & other ) const
416{
417 return m_tp == other.m_tp ;
418}
419
420 bool G::SystemTime::operator!=( const SystemTime & other ) const
421{
422 return !( *this == other ) ;
423}
424
425#ifndef G_LIB_SMALL
426 bool G::SystemTime::operator>( const SystemTime & other ) const
427{
428 return m_tp > other.m_tp ;
429}
430#endif
431
432#ifndef G_LIB_SMALL
433 bool G::SystemTime::operator>=( const SystemTime & other ) const
434{
435 return m_tp >= other.m_tp ;
436}
437#endif
438
439#ifndef G_LIB_SMALL
440 G::SystemTime G::SystemTime::operator+( TimeInterval interval ) const
441{
442 SystemTime t( *this ) ;
443 t += interval ;
444 return t ;
445}
446#endif
447
448 void G::SystemTime::operator+=( TimeInterval i )
449{
450 using namespace std::chrono ;
451 m_tp += seconds(i.s()) ;
452 m_tp += microseconds(i.us()) ;
453}
454
455 void G::SystemTime::streamOut( std::ostream & stream ) const
456{
457 int w = static_cast<int>( stream.width() ) ;
458 char c = stream.fill() ;
459 stream
460 << s() << "."
461 << std::setw(6) << std::setfill('0')
462 << us()
463 << std::setw(w) << std::setfill(c) ;
464}
465
466std::ostream & G::operator<<( std::ostream & stream , const SystemTime & t )
467{
468 t.streamOut( stream ) ;
469 return stream ;
470}
471
472// ==
473
474G::TimerTime::TimerTime( time_point_type tp ) :
475 m_tp(tp)
476{
477}
478
479 G::TimerTime G::TimerTime::now()
480{
481 time_point_type tp = std::chrono::steady_clock::now() ;
482 if( tp == time_point_type() ) tp += duration_type(1) ;
483 return TimerTime( tp ) ;
484}
485
486 G::TimerTime G::TimerTime::zero()
487{
488 return TimerTime( time_point_type( duration_type(0) ) ) ;
489}
490
491 bool G::TimerTime::isZero() const noexcept
492{
493 return m_tp == time_point_type( duration_type(0) ) ;
494}
495
496#ifndef G_LIB_SMALL
497 G::TimerTime G::TimerTime::test( int s , int us )
498{
499 using namespace std::chrono ;
500 return TimerTime( time_point_type( seconds(s) + microseconds(us) ) ) ;
501}
502#endif
503
504 unsigned long G::TimerTime::s() const
505{
506 using namespace std::chrono ;
507 return static_cast<unsigned long>( duration_cast<seconds>(m_tp.time_since_epoch()).count() ) ;
508}
509
510 unsigned long G::TimerTime::us() const
511{
512 using namespace std::chrono ;
513 return static_cast<unsigned long>( (duration_cast<microseconds>(m_tp.time_since_epoch()) % seconds(1)).count() ) ;
514}
515
516#ifndef G_LIB_SMALL
517std::string G::TimerTime::str() const
518{
519 std::ostringstream ss ;
520 ss << s() << '.' << std::setw(6) << std::setfill('0') << us() ;
521 return ss.str() ;
522}
523#endif
524
525 G::TimerTime G::TimerTime::operator+( const TimeInterval & interval ) const
526{
527 TimerTime t( *this ) ;
528 t += interval ;
529 return t ;
530}
531
532 void G::TimerTime::operator+=( TimeInterval i )
533{
534 using namespace std::chrono ;
535 m_tp += seconds(i.s()) ;
536 m_tp += microseconds(i.us()) ;
537}
538
539#ifndef G_LIB_SMALL
540 G::TimeInterval G::TimerTime::operator-( const TimerTime & start ) const
541{
542 return start.interval( *this ) ;
543}
544#endif
545
546 G::TimeInterval G::TimerTime::interval( const TimerTime & end ) const
547{
548 return DateTimeImp::interval( m_tp , end.m_tp ) ;
549}
550
551#ifndef G_LIB_SMALL
552 bool G::TimerTime::sameSecond( const TimerTime & t ) const
553{
554 using namespace std::chrono ;
555 return
556 duration_cast<seconds>(m_tp.time_since_epoch()) ==
557 duration_cast<seconds>(t.m_tp.time_since_epoch()) ;
558}
559#endif
560
561 bool G::TimerTime::operator<=( const TimerTime & other ) const
562{
563 return m_tp <= other.m_tp ;
564}
565
566 bool G::TimerTime::operator==( const TimerTime & other ) const
567{
568 return m_tp == other.m_tp ;
569}
570
571#ifndef G_LIB_SMALL
572 bool G::TimerTime::operator!=( const TimerTime & other ) const
573{
574 return m_tp != other.m_tp ;
575}
576#endif
577
578#ifndef G_LIB_SMALL
579 bool G::TimerTime::operator>( const TimerTime & other ) const
580{
581 return m_tp > other.m_tp ;
582}
583#endif
584
585#ifndef G_LIB_SMALL
586 bool G::TimerTime::operator>=( const TimerTime & other ) const
587{
588 return m_tp >= other.m_tp ;
589}
590#endif
591
592// ==
593
594 G::TimeInterval::TimeInterval( s_type s , us_type us ) :
595 m_s(s) ,
596 m_us(us)
597{
598 normalise() ;
599}
600
601#ifndef G_LIB_SMALL
602 G::TimeInterval::TimeInterval( const SystemTime & start , const SystemTime & end ) :
603 m_s(0) ,
604 m_us(0)
605{
606 TimeInterval i = start.interval( end ) ;
607 m_s = i.m_s ;
608 m_us = i.m_us ;
609 normalise() ;
610}
611#endif
612
613 G::TimeInterval::TimeInterval( const TimerTime & start , const TimerTime & end ) :
614 m_s(0) ,
615 m_us(0)
616{
617 TimeInterval i = start.interval( end ) ;
618 m_s = i.m_s ;
619 m_us = i.m_us ;
620 normalise() ;
621}
622
623 void G::TimeInterval::normalise()
624{
625 using namespace G::DateTimeImp ;
626 if( m_us >= million )
627 {
628 m_us -= million ;
629 increase( m_s ) ;
630 if( m_us >= million ) // still
631 {
632 increase( m_s , m_us / million ) ;
633 m_us = m_us % million ;
634 }
635 }
636}
637
638 G::TimeInterval G::TimeInterval::limit()
639{
640 using namespace G::DateTimeImp ;
641 return TimeInterval( std::numeric_limits<s_type>::max() , million-1U ) ;
642}
643
644 G::TimeInterval G::TimeInterval::zero()
645{
646 return TimeInterval( 0UL , 0U ) ;
647}
648
649G::TimeInterval::s_type G::TimeInterval::s() const
650{
651 return m_s ;
652}
653
654G::TimeInterval::us_type G::TimeInterval::us() const
655{
656 return m_us ;
657}
658
659 bool G::TimeInterval::operator==( const TimeInterval & other ) const
660{
661 return m_s == other.m_s && m_us == other.m_us ;
662}
663
664#ifndef G_LIB_SMALL
665 bool G::TimeInterval::operator!=( const TimeInterval & other ) const
666{
667 return !( *this == other ) ;
668}
669#endif
670
671 bool G::TimeInterval::operator<( const TimeInterval & other ) const
672{
673 return m_s < other.m_s || ( m_s == other.m_s && m_us < other.m_us ) ;
674}
675
676#ifndef G_LIB_SMALL
677 bool G::TimeInterval::operator<=( const TimeInterval & other ) const
678{
679 return *this == other || *this < other ;
680}
681#endif
682
683 bool G::TimeInterval::operator>( const TimeInterval & other ) const
684{
685 return m_s > other.m_s || ( m_s == other.m_s && m_us > other.m_us ) ;
686}
687
688#ifndef G_LIB_SMALL
689 bool G::TimeInterval::operator>=( const TimeInterval & other ) const
690{
691 return *this == other || *this > other ;
692}
693#endif
694
695#ifndef G_LIB_SMALL
696 G::TimeInterval G::TimeInterval::operator+( const TimeInterval & other ) const
697{
698 TimeInterval t( *this ) ;
699 t += other ;
700 return t ;
701}
702#endif
703
704#ifndef G_LIB_SMALL
705 G::TimeInterval G::TimeInterval::operator-( const TimeInterval & other ) const
706{
707 TimeInterval t( *this ) ;
708 t -= other ;
709 return t ;
710}
711#endif
712
713 void G::TimeInterval::increase( unsigned int & s , unsigned int ds )
714{
715 const auto old = s ;
716 s += ds ;
717 const bool overflow = s < old ;
718 if( overflow )
719 throw DateTime::Error( "overflow" ) ;
720}
721
722 void G::TimeInterval::operator+=( TimeInterval i )
723{
724 using namespace G::DateTimeImp ;
725 m_us += i.m_us ;
726 if( m_us >= million )
727 {
728 m_us -= million ;
729 increase( m_s ) ;
730 }
731 increase( m_s , i.m_s ) ;
732}
733
734 void G::TimeInterval::decrease( unsigned int & s , unsigned int ds )
735{
736 if( s < ds )
737 throw DateTime::Error( "underflow" ) ;
738 s -= ds ;
739}
740
741 void G::TimeInterval::operator-=( TimeInterval i )
742{
743 using namespace G::DateTimeImp ;
744 if( m_us < i.m_us )
745 {
746 decrease( m_s ) ;
747 m_us += million ;
748 }
749 m_us -= i.m_us ;
750 decrease( m_s , i.m_s ) ;
751}
752
753 void G::TimeInterval::streamOut( std::ostream & stream ) const
754{
755 int w = static_cast<int>( stream.width() ) ;
756 char c = stream.fill() ;
757 stream
758 << s() << "."
759 << std::setw(6) << std::setfill('0')
760 << us()
761 << std::setw(w) << std::setfill(c) ;
762}
763
764std::ostream & G::operator<<( std::ostream & stream , const TimeInterval & ti )
765{
766 ti.streamOut( stream ) ;
767 return stream ;
768}
769
770// ==
771
772G::DateTime::Offset G::DateTime::offset( SystemTime t_in )
773{
774 G_ASSERT( !(t_in == SystemTime::zero()) ) ;
775 SystemTime t_zone( BrokenDownTime::local(t_in).epochTimeFromUtc() ) ;
776 bool ahead = t_in < t_zone ; // ie. east-of
777 TimeInterval i = ahead ? (t_zone-t_in) : (t_in-t_zone) ;
778 return Offset{ ahead , i.s() } ;
779}
780
781#ifndef G_LIB_SMALL
782std::string G::DateTime::offsetString( int tz )
783{
784 std::ostringstream ss ;
785 ss << ( tz < 0 ? "-" : "+" ) ;
786 if( tz < 0 ) tz = -tz ;
787 ss << (tz/10) << (tz%10) << "00" ;
788 return ss.str() ;
789}
790#endif
791
792std::string G::DateTime::offsetString( Offset offset )
793{
794 unsigned int hh = (offset.second+30U) / 3600U ;
795 unsigned int mm = ((offset.second+30U) / 60U) % 60 ;
796
797 std::ostringstream ss ;
798 char sign = (offset.first || (hh==0&&mm==0)) ? '+' : '-' ;
799 ss << sign << (hh/10U) << (hh%10U) << (mm/10) << (mm%10) ;
800 return ss.str() ;
801}
802
G::BrokenDownTime
An encapsulation of 'struct std::tm'.
Definition: gdatetime.h:45
G::BrokenDownTime::wday
int wday() const
Returns week day where sunday=0 and saturday=6.
Definition: gdatetime.cpp:301
G::BrokenDownTime::day
int day() const
Returns the 1..31 month-day value.
Definition: gdatetime.cpp:296
G::BrokenDownTime::null
static BrokenDownTime null()
Factory function for an unusable object with bogus component values.
Definition: gdatetime.cpp:200
G::BrokenDownTime::epochTimeFromLocal
std::time_t epochTimeFromLocal() const
Uses std::mktime() to convert this locale-dependent local broken-down time into epoch time.
Definition: gdatetime.cpp:169
G::BrokenDownTime::str
std::string str() const
Returns str() using a "%F %T" format.
Definition: gdatetime.cpp:253
G::BrokenDownTime::BrokenDownTime
BrokenDownTime(const struct std::tm &)
Constructor.
Definition: gdatetime.cpp:145
G::BrokenDownTime::sec
int sec() const
Returns the 0..59 or 0..60 seconds value.
Definition: gdatetime.cpp:281
G::BrokenDownTime::utc
static BrokenDownTime utc(SystemTime)
Factory function for the utc broken-down time of the given epoch time.
Definition: gdatetime.cpp:213
G::BrokenDownTime::midday
static BrokenDownTime midday(int year, int month, int day)
Factory function for midday on the given date.
Definition: gdatetime.cpp:220
G::BrokenDownTime::midnight
static BrokenDownTime midnight(int year, int month, int day)
Factory function for midnight starting the given date.
Definition: gdatetime.cpp:226
G::BrokenDownTime::month
int month() const
Returns the 1..12 month value.
Definition: gdatetime.cpp:291
G::BrokenDownTime::local
static BrokenDownTime local(SystemTime)
Factory function for the locale-dependent local broken-down time of the given epoch time.
Definition: gdatetime.cpp:206
G::BrokenDownTime::hour
int hour() const
Returns the 0..23 hour value.
Definition: gdatetime.cpp:271
G::BrokenDownTime::year
int year() const
Returns the four-digit year value.
Definition: gdatetime.cpp:286
G::BrokenDownTime::format
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.
Definition: gdatetime.cpp:232
G::BrokenDownTime::sameMinute
bool sameMinute(const BrokenDownTime &) const noexcept
Returns true if this and the other broken-down times are the same, at minute resolution with no round...
Definition: gdatetime.cpp:309
G::BrokenDownTime::epochTimeFromUtc
std::time_t epochTimeFromUtc() const
Converts this utc broken-down time into epoch time.
Definition: gdatetime.cpp:175
G::BrokenDownTime::min
int min() const
Returns the 0..59 minute value.
Definition: gdatetime.cpp:276
G::DateTime::offset
static Offset offset(SystemTime)
Returns the offset in seconds between UTC and localtime as at the given system time.
Definition: gdatetime.cpp:772
G::DateTime::offsetString
static std::string offsetString(Offset offset)
Converts the given utc/localtime offset into a five-character "+/-hhmm" string.
Definition: gdatetime.cpp:792
G::SystemTime
Represents a unix-epoch time with microsecond resolution.
Definition: gdatetime.h:140
G::SystemTime::operator-
TimeInterval operator-(const SystemTime &start) const
Returns the given start time's interval() compared to this end time.
Definition: gdatetime.cpp:333
G::SystemTime::now
static SystemTime now()
Factory function for the current time.
Definition: gdatetime.cpp:328
G::SystemTime::s
std::time_t s() const noexcept
Returns the number of seconds since the start of the epoch.
Definition: gdatetime.cpp:380
G::SystemTime::operator+
SystemTime operator+(TimeInterval) const
Returns this time with given interval added.
Definition: gdatetime.cpp:440
G::SystemTime::ms
unsigned int ms() const
Returns the millisecond fraction.
Definition: gdatetime.cpp:367
G::SystemTime::us
unsigned int us() const
Returns the microsecond fraction.
Definition: gdatetime.cpp:374
G::SystemTime::operator!=
bool operator!=(const SystemTime &) const
Comparison operator.
Definition: gdatetime.cpp:420
G::SystemTime::local
BrokenDownTime local() const
Returns the locale-dependent local broken-down time.
Definition: gdatetime.cpp:356
G::SystemTime::operator>
bool operator>(const SystemTime &) const
Comparison operator.
Definition: gdatetime.cpp:426
G::SystemTime::streamOut
void streamOut(std::ostream &) const
Streams out the time comprised of the s() value, a decimal point, and then the six-digit us() value.
Definition: gdatetime.cpp:455
G::SystemTime::interval
TimeInterval interval(const SystemTime &end) const
Returns the interval between this time and the given end time.
Definition: gdatetime.cpp:338
G::SystemTime::sameSecond
bool sameSecond(const SystemTime &other) const noexcept
Returns true if this time and the other time are the same, at second resolution.
Definition: gdatetime.cpp:351
G::SystemTime::operator<=
bool operator<=(const SystemTime &) const
Comparison operator.
Definition: gdatetime.cpp:409
G::SystemTime::isZero
bool isZero() const
Returns true if zero().
Definition: gdatetime.cpp:397
G::SystemTime::operator>=
bool operator>=(const SystemTime &) const
Comparison operator.
Definition: gdatetime.cpp:433
G::SystemTime::zero
static SystemTime zero()
Factory function for the start of the epoch.
Definition: gdatetime.cpp:388
G::SystemTime::SystemTime
SystemTime(std::time_t, unsigned long us=0UL) noexcept
Constructor.
Definition: gdatetime.cpp:322
G::SystemTime::utc
BrokenDownTime utc() const
Returns the utc broken-down time.
Definition: gdatetime.cpp:361
G::SystemTime::operator+=
void operator+=(TimeInterval)
Adds the given interval. Throws on overflow.
Definition: gdatetime.cpp:448
G::SystemTime::operator<
bool operator<(const SystemTime &) const
Comparison operator.
Definition: gdatetime.cpp:403
G::SystemTime::operator==
bool operator==(const SystemTime &) const
Comparison operator.
Definition: gdatetime.cpp:415
G::TimeInterval
An interval between two G::SystemTime values or two G::TimerTime values.
Definition: gdatetime.h:305
G::TimeInterval::TimeInterval
TimeInterval(unsigned int s, unsigned int us=0U)
Constructor.
Definition: gdatetime.cpp:594
G::TimeInterval::operator+
TimeInterval operator+(const TimeInterval &) const
Returns the combined interval. Throws on overflow.
Definition: gdatetime.cpp:696
G::TimeInterval::zero
static TimeInterval zero()
Factory function for the zero interval.
Definition: gdatetime.cpp:644
G::TimeInterval::operator-=
void operator-=(TimeInterval)
Subtracts the given interval. Throws on underflow.
Definition: gdatetime.cpp:741
G::TimeInterval::operator==
bool operator==(const TimeInterval &) const
Comparison operator.
Definition: gdatetime.cpp:659
G::TimeInterval::limit
static TimeInterval limit()
Factory function for the maximum valid interval.
Definition: gdatetime.cpp:638
G::TimeInterval::s
unsigned int s() const
Returns the number of seconds.
Definition: gdatetime.cpp:649
G::TimeInterval::us
unsigned int us() const
Returns the fractional microseconds part.
Definition: gdatetime.cpp:654
G::TimeInterval::operator+=
void operator+=(TimeInterval)
Adds the given interval. Throws on overflow.
Definition: gdatetime.cpp:722
G::TimeInterval::operator>
bool operator>(const TimeInterval &) const
Comparison operator.
Definition: gdatetime.cpp:683
G::TimeInterval::operator-
TimeInterval operator-(const TimeInterval &) const
Returns the interval difference. Throws on underflow.
Definition: gdatetime.cpp:705
G::TimeInterval::operator<
bool operator<(const TimeInterval &) const
Comparison operator.
Definition: gdatetime.cpp:671
G::TimeInterval::operator!=
bool operator!=(const TimeInterval &) const
Comparison operator.
Definition: gdatetime.cpp:665
G::TimeInterval::streamOut
void streamOut(std::ostream &) const
Streams out the interval.
Definition: gdatetime.cpp:753
G::TimeInterval::operator>=
bool operator>=(const TimeInterval &) const
Comparison operator.
Definition: gdatetime.cpp:689
G::TimeInterval::operator<=
bool operator<=(const TimeInterval &) const
Comparison operator.
Definition: gdatetime.cpp:677
G::TimerTime
A monotonically increasing subsecond-resolution timestamp, notionally unrelated to time_t.
Definition: gdatetime.h:231
G::TimerTime::isZero
bool isZero() const noexcept
Returns true if zero().
Definition: gdatetime.cpp:491
G::TimerTime::now
static TimerTime now()
Factory function for the current steady-clock time.
Definition: gdatetime.cpp:479
G::TimerTime::operator+
TimerTime operator+(const TimeInterval &) const
Returns this time with given interval added.
Definition: gdatetime.cpp:525
G::TimerTime::operator>
bool operator>(const TimerTime &) const
Comparison operator.
Definition: gdatetime.cpp:579
G::TimerTime::interval
TimeInterval interval(const TimerTime &end) const
Returns the interval between this time and the given end time.
Definition: gdatetime.cpp:546
G::TimerTime::operator==
bool operator==(const TimerTime &) const
Comparison operator.
Definition: gdatetime.cpp:566
G::TimerTime::operator!=
bool operator!=(const TimerTime &) const
Comparison operator.
Definition: gdatetime.cpp:572
G::TimerTime::operator-
TimeInterval operator-(const TimerTime &start) const
Returns the given start time's interval() compared to this end time.
Definition: gdatetime.cpp:540
G::TimerTime::sameSecond
bool sameSecond(const TimerTime &other) const
Returns true if this time and the other time are the same, at second resolution.
Definition: gdatetime.cpp:552
G::TimerTime::operator+=
void operator+=(TimeInterval)
Adds an interval.
Definition: gdatetime.cpp:532
G::TimerTime::zero
static TimerTime zero()
Factory function for the start of the epoch, guaranteed to be less than any now().
Definition: gdatetime.cpp:486
G::TimerTime::operator<=
bool operator<=(const TimerTime &) const
Comparison operator.
Definition: gdatetime.cpp:561
G::TimerTime::operator>=
bool operator>=(const TimerTime &) const
Comparison operator.
Definition: gdatetime.cpp:586
G::format
A simple version of boost::format for formatting strings in an i18n-friendly way.
Definition: gformat.h:46
G::optional
A class template like a simplified c++17 std::optional.
Definition: goptional.h:50
G::optional::value
const T & value() const
Returns the value.
Definition: goptional.h:121
G::optional::has_value
bool has_value() const noexcept
Returns true if a defined value.
Definition: goptional.h:109
gassert.h
gdatetime.h
goptional.h
gstr.h
G
Low-level classes.
Definition: garg.h:36
G::BrokenDownTime::m_tm
Definition: gdatetime.h:133