E-MailRelay
gdate.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 gdate.cpp
19///
20
21#include "gdef.h"
22#include "gdate.h"
23#include "gstr.h"
24#include "glog.h"
25#include "gassert.h"
26#include <ctime>
27
29{
30 //return 2035 ; // see mktime()
31 return 9999 ;
32}
33
35{
36 return 1970 ; // see mktime()
37}
38
39#ifndef G_LIB_SMALL
41{
42 init( SystemTime::now().utc() ) ;
43 //check() ;
44}
45#endif
46
47#ifndef G_LIB_SMALL
49{
50 init( t.utc() ) ;
51 //check() ;
52}
53#endif
54
55#ifndef G_LIB_SMALL
57{
58 init( t.local() ) ;
59 //check() ;
60}
61#endif
62
64{
65 init( tm ) ;
66 //check() ;
67}
68
69#ifndef G_LIB_SMALL
71{
72 init( SystemTime::now().local() ) ;
73 //check() ;
74}
75#endif
76
77#ifndef G_LIB_SMALL
78G::Date::Date( int year , Date::Month month , int day_of_month , std::nothrow_t ) noexcept :
79 m_day(day_of_month) ,
80 m_month(static_cast<int>(month)) ,
81 m_year(year)
82{
83 m_day = std::max( 1 , std::min(m_day,31) ) ;
84 m_month = std::max( 1 , std::min(m_month,12) ) ;
85 m_year = std::max( yearLowerLimit() , std::min(m_year,yearUpperLimit()) ) ;
86}
87#endif
88
89#ifndef G_LIB_SMALL
90G::Date::Date( int year , Date::Month month , int day_of_month ) :
91 m_day(day_of_month) ,
92 m_month(static_cast<int>(month)) ,
93 m_year(year)
94{
95 check() ;
96}
97#endif
98
99void G::Date::init( const BrokenDownTime & tm )
100{
101 m_year = tm.year() ;
102 m_month = tm.month() ;
103 m_day = tm.day() ;
104}
105
106void G::Date::check() const
107{
108 bool ok =
109 m_year >= yearLowerLimit() &&
110 m_year <= yearUpperLimit() &&
111 m_month >= 1 &&
112 m_month <= 12 &&
113 m_day >= 1 &&
114 m_day <= 31 ;
115 if( !ok )
116 throw DateError( "out of range" ) ;
117}
118
119#ifndef G_LIB_SMALL
120std::string G::Date::str( Format format ) const
121{
122 std::ostringstream ss ;
123 if( format == Format::yyyy_mm_dd_slash )
124 {
125 ss << yyyy() << "/" << mm() << "/" << dd() ;
126 }
127 else if( format == Format::yyyy_mm_dd )
128 {
129 ss << yyyy() << mm() << dd() ;
130 }
131 else if( format == Format::mm_dd )
132 {
133 ss << mm() << dd() ;
134 }
135 else
136 {
137 G_ASSERT( !"enum error" ) ;
138 }
139 return ss.str() ;
140}
141#endif
142
144{
145 return m_day ;
146}
147
148std::string G::Date::dd() const
149{
150 return Str::fromInt(std::min(99,std::max(0,m_day))+100).substr(1U) ;
151}
152
153std::string G::Date::mm() const
154{
155 return Str::fromInt(std::min(99,std::max(0,m_month))+100).substr(1U) ;
156}
157
158std::string G::Date::yyyy() const
159{
160 return Str::fromInt(std::min(9999,std::max(0,m_year))+10000).substr(1U) ;
161}
162
163G::Date::Weekday G::Date::weekday() const
164{
165 if( ! m_weekday_set )
166 {
167 BrokenDownTime bdt = BrokenDownTime::midday( m_year , m_month , m_day ) ;
168 const_cast<Date*>(this)->m_weekday_set = true ;
169 const_cast<Date*>(this)->m_weekday = Weekday(bdt.wday()) ;
170 }
171 return m_weekday ;
172}
173
174std::string G::Date::weekdayName( bool brief ) const
175{
176 Weekday d = weekday() ;
177 const char * p = "" ;
178 if( d == Weekday::sunday ) p = brief ? "Sun" : "Sunday" ;
179 else if( d == Weekday::monday ) p = brief ? "Mon" : "Monday" ;
180 else if( d == Weekday::tuesday ) p = brief ? "Tue" : "Tuesday" ;
181 else if( d == Weekday::wednesday ) p = brief ? "Wed" : "Wednesday" ;
182 else if( d == Weekday::thursday ) p= brief ? "Thu" : "Thursday" ;
183 else if( d == Weekday::friday ) p = brief ? "Fri" : "Friday" ;
184 else if( d == Weekday::saturday ) p = brief ? "Sat" : "Saturday" ;
185 return { p } ;
186}
187
188G::Date::Month G::Date::month() const
189{
190 return Month(m_month) ;
191}
192
193std::string G::Date::monthName( bool brief ) const
194{
195 Month m = month() ;
196 const char * p = "" ;
197 if( m == Month::january ) p = brief ? "Jan" : "January" ;
198 else if( m == Month::february ) p = brief ? "Feb" : "February" ;
199 else if( m == Month::march ) p = brief ? "Mar" : "March" ;
200 else if( m == Month::april ) p = brief ? "Apr" : "April" ;
201 else if( m == Month::may ) p = "May" ;
202 else if( m == Month::june ) p = brief ? "Jun" : "June" ;
203 else if( m == Month::july ) p = brief ? "Jul" : "July" ;
204 else if( m == Month::august ) p = brief ? "Aug" : "August" ;
205 else if( m == Month::september ) p = brief ? "Sep" : "September" ;
206 else if( m == Month::october ) p = brief ? "Oct" : "October" ;
207 else if( m == Month::november ) p = brief ? "Nov" : "November" ;
208 else if( m == Month::december ) p = brief ? "Dec" : "December" ;
209 return { p } ;
210}
211
212int G::Date::year() const
213{
214 return m_year ;
215}
216
217#ifndef G_LIB_SMALL
219{
220 Date d( *this ) ;
221 ++d ;
222 return d ;
223}
224#endif
225
227{
228 ++m_day ;
229 if( m_day == (lastDay(m_month,m_year)+1) )
230 {
231 m_day = 1 ;
232 ++m_month ;
233 if( m_month == 13 )
234 {
235 m_month = 1 ;
236 ++m_year ;
237 }
238 }
239 if( m_weekday_set )
240 {
241 if( m_weekday == Weekday::saturday )
242 m_weekday = Weekday::sunday ;
243 else
244 m_weekday = static_cast<Weekday>(static_cast<int>(m_weekday)+1) ;
245 }
246 return *this ;
247}
248
249#ifndef G_LIB_SMALL
251{
252 Date d( *this ) ;
253 --d ;
254 return d ;
255}
256#endif
257
259{
260 if( m_day == 1 )
261 {
262 if( m_month == 1 )
263 {
264 m_year-- ;
265 m_month = 12 ;
266 }
267 else
268 {
269 m_month-- ;
270 }
271
272 m_day = lastDay( m_month , m_year ) ;
273 }
274 else
275 {
276 m_day-- ;
277 }
278 if( m_weekday_set )
279 {
280 if( m_weekday == Weekday::sunday )
281 m_weekday = Weekday::saturday ;
282 else
283 m_weekday = static_cast<Weekday>(static_cast<int>(m_weekday)-1) ;
284 }
285 return *this ;
286}
287
288int G::Date::lastDay( int month , int year )
289{
290 int end = 30 ;
291 if( month == 1 ||
292 month == 3 ||
293 month == 5 ||
294 month == 7 ||
295 month == 8 ||
296 month == 10 ||
297 month == 12 )
298 {
299 end = 31 ;
300 }
301 else if( month == 2 )
302 {
303 end = isLeapYear(year) ? 29 : 28 ;
304 }
305 return end ;
306}
307
308bool G::Date::isLeapYear( int y )
309{
310 return y >= 1800 && ( y % 400 == 0 || ( y % 100 != 0 && y % 4 == 0 ) ) ;
311}
312
313bool G::Date::operator==( const Date &other ) const
314{
315 return
316 year() == other.year() &&
317 month() == other.month() &&
318 monthday() == other.monthday() ;
319}
320
321#ifndef G_LIB_SMALL
322bool G::Date::operator!=( const Date &other ) const
323{
324 return !( other == *this ) ;
325}
326#endif
327
An encapsulation of 'struct std::tm'.
Definition: gdatetime.h:45
int wday() const
Returns week day where sunday=0 and saturday=6.
Definition: gdatetime.cpp:301
int day() const
Returns the 1..31 month-day value.
Definition: gdatetime.cpp:296
static BrokenDownTime midday(int year, int month, int day)
Factory function for midday on the given date.
Definition: gdatetime.cpp:220
int month() const
Returns the 1..12 month value.
Definition: gdatetime.cpp:291
int year() const
Returns the four-digit year value.
Definition: gdatetime.cpp:286
An overload discriminator class for Date constructors.
Definition: gdate.h:46
A day-month-year date class.
Definition: gdate.h:42
Date()
Default constructor for the current date in the UTC timezone.
Definition: gdate.cpp:40
Date & operator--()
Decrements the date by one day.
Definition: gdate.cpp:258
std::string monthName(bool brief=false) const
Returns the month as a string (in english).
Definition: gdate.cpp:193
std::string weekdayName(bool brief=false) const
Returns an english string representation of the day of the week.
Definition: gdate.cpp:174
bool operator==(const Date &rhs) const
Comparison operator.
Definition: gdate.cpp:313
Month month() const
Returns the month.
Definition: gdate.cpp:188
static int yearUpperLimit() noexcept
Returns the largest supported year value.
Definition: gdate.cpp:28
int monthday() const
Returns the day of the month.
Definition: gdate.cpp:143
Date & operator++()
Increments the date by one day.
Definition: gdate.cpp:226
std::string yyyy() const
Returns the year as a four-digit decimal string.
Definition: gdate.cpp:158
std::string dd() const
Returns the day of the month as a two-digit decimal string.
Definition: gdate.cpp:148
std::string str(Format format=Format::yyyy_mm_dd_slash) const
Returns a string representation of the date.
Definition: gdate.cpp:120
Weekday weekday() const
Returns the day of the week.
Definition: gdate.cpp:163
Date next() const
Returns the next date.
Definition: gdate.cpp:218
bool operator!=(const Date &rhs) const
Comparison operator.
Definition: gdate.cpp:322
static int yearLowerLimit() noexcept
Returns the smallest supported year value.
Definition: gdate.cpp:34
Date previous() const
Returns the previous date.
Definition: gdate.cpp:250
int year() const
Returns the year.
Definition: gdate.cpp:212
std::string mm() const
Returns the month as a two-digit decimal string.
Definition: gdate.cpp:153
static std::string fromInt(int i)
Converts int 'i' to a string.
Definition: gstr.h:594
Represents a unix-epoch time with microsecond resolution.
Definition: gdatetime.h:140
static SystemTime now()
Factory function for the current time.
Definition: gdatetime.cpp:328
BrokenDownTime local() const
Returns the locale-dependent local broken-down time.
Definition: gdatetime.cpp:356
BrokenDownTime utc() const
Returns the utc broken-down time.
Definition: gdatetime.cpp:361
A simple version of boost::format for formatting strings in an i18n-friendly way.
Definition: gformat.h:46