E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gdatetime.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 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 // gdatetime.cpp
19 //
20
21 #include "gdef.h"
22 #include "gdatetime.h"
23 #include "gstr.h"
24 #include "gassert.h"
25 #include <sstream>
26 #include <iomanip>
27
28 namespace
29 {
30 const std::time_t minute = 60 ;
31 const std::time_t hour = 60 * minute ;
32 const std::time_t day = 24 * hour ;
33 }
34
35 G::EpochTime::EpochTime( std::time_t s_ , unsigned long us_ ) :
36 s(s_) ,
37 us(static_cast<unsigned int>(us_))
38 {
39 if( us_ >= 1000000UL )
40 {
41 s += static_cast<std::time_t>( us_ / 1000000UL ) ;
42 us = static_cast<unsigned int>( us_ % 1000000UL ) ;
43 }
44 }
45
46 G::EpochTime G::operator+( G::EpochTime lhs , G::EpochTime rhs )
47 {
48 lhs.s += rhs.s ;
49 lhs.us += rhs.us ;
50 if( lhs.us > 1000000UL )
51 {
52 lhs.s++ ;
53 lhs.us -= 1000000UL ;
54 }
55 return lhs ;
56 }
57
58 G::EpochTime G::operator-( G::EpochTime big , G::EpochTime small_ )
59 {
60 big.s -= small_.s ;
61 if( small_.us > big.us )
62 {
63 big.s-- ;
64 big.us += 1000000U ;
65 }
66 big.us -= small_.us ;
67 return big ;
68 }
69
70 void G::EpochTime::streamOut( std::ostream & stream ) const
71 {
72 std::streamsize w = stream.width() ;
73 char c = stream.fill() ;
74 stream
75 << s << "."
76 << std::setw(6) << std::setfill('0')
77 << us
78 << std::setw(w) << std::setfill(c) ;
79 }
80
81 // ==
82
83 G::EpochTime G::DateTime::epochTime( const BrokenDownTime & bdt_in )
84 {
85 // get a rough starting point -- mktime() works with localtime,
86 // including daylight saving, but there is no UTC equivalent --
87 // timegm(3) is deprecated in favour of nasty fiddling with the
88 // TZ environment variable
89 //
90 BrokenDownTime bdt( bdt_in ) ;
91 const bool leap_second = bdt.tm_sec == 60 ;
92 if( leap_second ) bdt.tm_sec = 59 ;
93 EpochTime tlocal( std::mktime(&bdt) , 0U ) ; // localtime
94
95 // optimisation
96 static std::time_t diff = 0 ;
97 static bool diff_set = false ;
98 if( diff_set )
99 {
100 EpochTime t( tlocal.s + diff ) ;
101 if( equivalent( t , bdt_in ) )
102 return leap_second ? (t+1) : t ;
103 diff_set = false ; // optimisation failure eg. change of dst
104 }
105
106 // iterate over all possible timezones
107 //
108 const std::time_t dt = minute * 30 ;
109 const std::time_t day_and_a_bit = day + dt ;
110 EpochTime t( tlocal.s - day_and_a_bit ) ;
111 const EpochTime end( tlocal.s + day_and_a_bit ) ;
112 for( diff = -day_and_a_bit ; t <= end ; t.s += dt , diff += dt )
113 {
114 if( equivalent( t , bdt_in ) )
115 {
116 diff_set = true ;
117 return leap_second ? (t+1) : t ;
118 }
119 }
120 throw Error() ;
121 }
122
123 G::DateTime::BrokenDownTime G::DateTime::utc( EpochTime epoch_time )
124 {
125 static BrokenDownTime zero ;
126 BrokenDownTime result = zero ;
127 G::DateTime::gmtime_imp( &epoch_time.s , &result ) ;
128 return result ;
129 }
130
131 G::DateTime::BrokenDownTime G::DateTime::local( EpochTime epoch_time )
132 {
133 static BrokenDownTime zero ;
134 BrokenDownTime bdt_local = zero ;
135 G::DateTime::localtime_imp( &epoch_time.s , &bdt_local ) ;
136 return bdt_local ;
137 }
138
139 G::DateTime::Offset G::DateTime::offset( EpochTime utc )
140 {
141 BrokenDownTime bdt_local = local(utc) ;
142
143 EpochTime local = epochTime(bdt_local) ;
144 bool ahead = local.s >= utc.s ; // ie. east-of
145 EpochTime n( ahead ? (local.s-utc.s) : (utc.s-local.s) ) ;
146 return Offset( ahead , static_cast<unsigned int>(n.s) ) ;
147 }
148
149 std::string G::DateTime::offsetString( int tz )
150 {
151 std::ostringstream ss ;
152 ss << ( tz < 0 ? "-" : "+" ) ;
153 if( tz < 0 ) tz = -tz ;
154 ss << (tz/10) << (tz%10) << "00" ;
155 return ss.str() ;
156 }
157
158 std::string G::DateTime::offsetString( Offset offset )
159 {
160 unsigned int hh = offset.second / 3600U ;
161 unsigned int mm = (offset.second / 60U) % 60 ;
162
163 std::ostringstream ss ;
164 char sign = (offset.first || (hh==0&&mm==0)) ? '+' : '-' ;
165 ss << sign << (hh/10U) << (hh%10U) << (mm/10) << (mm%10) ;
166 return ss.str() ;
167 }
168
169 bool G::DateTime::equivalent( EpochTime t , const BrokenDownTime & bdt_in )
170 {
171 BrokenDownTime bdt_test = utc(t) ;
172 return equivalent( bdt_test , bdt_in ) ;
173 }
174
175 bool G::DateTime::equivalent( const BrokenDownTime & bdt1 , const BrokenDownTime & bdt2 )
176 {
177 return
178 bdt1.tm_mday == bdt2.tm_mday &&
179 bdt1.tm_hour == bdt2.tm_hour &&
180 bdt1.tm_min == bdt2.tm_min ;
181 }
182
183 /// \file gdatetime.cpp
G::DateTime::utc
static BrokenDownTime utc(EpochTime epoch_time)
Converts from epoch time to UTC broken-down-time.
Definition: gdatetime.cpp:123
G::EpochTime
A subsecond-resolution timestamp based on a time_t.
Definition: gdatetime.h:39
G::DateTime::offset
static Offset offset(EpochTime epoch_time)
Returns the offset between UTC and localtime as at 'epoch_time'.
Definition: gdatetime.cpp:139
G::DateTime::local
static BrokenDownTime local(EpochTime epoch_time)
Converts from epoch time to local broken-down-time.
Definition: gdatetime.cpp:131
G::EpochTime::streamOut
void streamOut(std::ostream &) const
Used by operator<<.
Definition: gdatetime.cpp:70
gstr.h
gassert.h
gdatetime.h
G::DateTime::offsetString
static std::string offsetString(Offset offset)
Converts the given utc/localtime offset into a five-character "+/-hhmm" string.
Definition: gdatetime.cpp:158
G::EpochTime::EpochTime
EpochTime(std::time_t)
Constructor.
Definition: gdatetime.h:117
G::DateTime::epochTime
static EpochTime epochTime(const BrokenDownTime &broken_down_time)
Converts from UTC broken-down-time to epoch time.
Definition: gdatetime.cpp:83