1 // ----------------------------------------------------------------------------
2 //
3 // Date.cxx date class for Fast Light Took Kit
4 //
5 // Copyright (C) 1998 David Freese
6 //
7 // This file is part of fldigi.
8 //
9 // Fldigi is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Fldigi is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with fldigi. If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22
23 #include <config.h>
24
25 #include <iostream>
26 #include <cstring>
27 #include <ctime>
28 #include <cstdio>
29
30 #include "date.h"
31
32 using namespace std;
33
34 const int Date::mdays[] =
35 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
36
37 const int Date::jdays[2][13] = {
38 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
39 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
40 };
41
42 const char *Date::month_name[] =
43 {
44 "January",
45 "Febuary",
46 "March",
47 "April",
48 "May",
49 "June",
50 "July",
51 "August",
52 "September",
53 "October",
54 "November",
55 "December"
56 };
57
today()58 void Date::today()
59 {
60 time_t t;
61 struct tm *now;
62 time( &t );
63 now = localtime( &t );
64 year = now->tm_year + 1900;
65 month = now->tm_mon + 1;
66 day = now->tm_mday;
67 }
68
Date()69 Date::Date()
70 {
71 today();
72 fmt = 0;
73 }
74
Date(int m,int d,int y)75 Date::Date( int m, int d, int y )
76 {
77 setDate( m, d, y );
78 fmt = 1;
79 }
80
setDate(int mm,int dd,int yy)81 void Date::setDate( int mm, int dd, int yy )
82 {
83 if( isvalid( mm, dd, yy ) ) {
84 year = yy; month = mm; day = dd;
85 } else
86 today();
87 }
88
setDate(Date & dt)89 void Date::setDate( Date &dt )
90 {
91 year = dt.year;
92 month = dt.month;
93 day = dt.day;
94 }
95
setFormat(int iFmt)96 void Date::setFormat( int iFmt )
97 {
98 fmt = iFmt;
99 }
100
Year(int y)101 void Date::Year( int y )
102 {
103 year = y;
104 }
105
Year()106 int Date::Year()
107 {
108 return year;
109 }
110
Month(int m)111 void Date::Month( int m )
112 {
113 month = m;
114 }
115
Month()116 int Date::Month()
117 {
118 return month;
119 }
120
Day(int d)121 void Date::Day( int d )
122 {
123 day = d;
124 }
125
Day()126 int Date::Day()
127 {
128 return day;
129 }
130
leapYear(int y)131 bool Date::leapYear( int y )
132 {
133 if( y % 400 == 0 || ( y % 100 != 0 && y % 4 == 0 ) )
134 return true;
135 return false;
136 }
137
138
isvalid(int m,int d,int y)139 bool Date::isvalid( int m, int d, int y )
140 {
141 if( y > 2035 ) return false;
142 if( m < 1 || m > 12 ) return false;
143 if( d < 1 ) return false;
144 if( leapYear( y ) ){
145 if( m == 2 && d > 29 )
146 return false;
147 else
148 return true;
149 }
150 if( d > mdays[m] ) return false;
151 return true;
152 }
153
daysinmonth(int month,int leap)154 int Date::daysinmonth (int month, int leap)
155 {
156 /* Validate the month. */
157 if (month < JANUARY || month > DECEMBER)
158 return -1;
159
160 /* Return 28, 29, 30, or 31 based on month/leap. */
161 switch (month) {
162 case FEBRUARY:
163 return leap ? 29 : 28;
164 default:
165 return mdays[month];
166 }
167 }
168
169
dayofyear(int year,int mon,int mday)170 int Date::dayofyear (int year, int mon, int mday)
171 {
172 /* Return day of year. */
173 return mday + jdays[isleapyear (year) ? 1 : 0][mon];
174 }
175
dayofepoch(int year,int mon,int mday)176 int Date::dayofepoch (int year, int mon, int mday)
177 {
178 int doe;
179 int era, cent, quad, rest;
180
181 /* break down the year into 400, 100, 4, and 1 year multiples */
182 rest = year - 1;
183 quad = rest / 4; rest %= 4;
184 cent = quad / 25; quad %= 25;
185 era = cent / 4; cent %= 4;
186
187 /* set up doe */
188 doe = dayofyear (year, mon, mday);
189 doe += era * (400 * 365 + 97);
190 doe += cent * (100 * 365 + 24);
191 doe += quad * (4 * 365 + 1);
192 doe += rest * 365;
193
194 return doe;
195 }
196
dayofweek(int year,int mon,int mday)197 int Date::dayofweek (int year, int mon, int mday)
198 {
199 return dayofepoch (year, mon, mday) % 7;
200 }
201
previous_month()202 void Date::previous_month ()
203 {
204 if (month == 1)
205 {
206 month = 12;
207 year--;
208 }
209 else
210 month--;
211
212 while ((day >= 1) && (!datevalid ()))
213 day--;
214 }
215
next_month()216 void Date::next_month ()
217 {
218 if (month == 12)
219 {
220 month = 1;
221 year++;
222 }
223 else
224 month++;
225
226 while ((day >= 1) && (!datevalid ()))
227 day--;
228 }
229
previous_year()230 void Date::previous_year ()
231 {
232 if (month == 2 && day == 29)
233 day = 28;
234 year--;
235 }
236
next_year()237 void Date::next_year ()
238 {
239 if (month == 2 && day == 29)
240 day = 28;
241 year++;
242 }
243
244
szDate(int fmt)245 char *Date::szDate (int fmt)
246 {
247 static char temp[20];
248 char szMonth[10];
249 switch (fmt) {
250 case 1 :
251 snprintf (temp, sizeof(temp), "%02d/%02d/%02d",
252 month,
253 day,
254 year > 1999 ? year - 2000 : year - 1900);
255 break;
256 case 2 :
257 snprintf (temp, sizeof(temp), "%4d%02d%02d", year, month, day);
258 break;
259 case 3 :
260 snprintf (temp, sizeof(temp), "%s %2d, %4d",
261 month_name[month - 1],
262 day,
263 year);
264 break;
265 case 4 :
266 strcpy (szMonth, month_name [month - 1]);
267 szMonth[3] = 0;
268 snprintf (temp, sizeof(temp), "%s %2d, %4d", szMonth, day, year);
269 break;
270 case 5 :
271 strcpy (szMonth, month_name [month - 1]);
272 szMonth[3] = 0;
273 snprintf (temp, sizeof(temp), "%02d %s %4d", day, szMonth, year);
274 break;
275 case 0 :
276 default :
277 snprintf (temp, sizeof(temp), "%02d/%02d/%04d",
278 month,
279 day,
280 year);
281 break;
282 }
283 return temp;
284 }
285
szDate()286 char *Date::szDate ()
287 {
288 return szDate (fmt);
289 }
290
291 // operator functions
292
operator <<(ostream & output,Date & d)293 ostream &operator<<( ostream &output, Date &d )
294 {
295 output << d.szDate ();
296 return output;
297 }
298
endOfMonth(int d)299 bool Date::endOfMonth( int d )
300 {
301 if( month == 2 && leapYear( year ) )
302 return (d == 29 ); // last day of Feb in leap year
303 else
304 return (d == mdays[ month ] );
305 }
306
helpIncrement()307 void Date::helpIncrement()
308 {
309 if( endOfMonth( day ) && month == 12 ) { // end year
310 day = 1;
311 month = 1;
312 ++year;
313 } else if ( endOfMonth( day ) ) {
314 day = 1;
315 ++month;
316 } else
317 ++day;
318 }
319
operator ++()320 Date &Date::operator++()
321 {
322 helpIncrement();
323 return *this; // reference return to create an lvalue
324 }
325
operator ++(int)326 Date Date::operator++( int )
327 {
328 Date temp = *this;
329 helpIncrement();
330 return temp; // return non-increment, saved temporary object
331 }
332
operator +=(int ndays)333 const Date &Date::operator+=( int ndays )
334 {
335 for( int i = 0; i < ndays; i++ )
336 helpIncrement();
337 return *this; // enables cascading
338 }
339
340
operator ==(const Date & d)341 bool Date::operator==( const Date &d )
342 {
343 if( this->year != d.year ) return false;
344 if( this->month != d.month ) return false;
345 if( this->day != d.day ) return false;
346 return true;
347 }
348
operator !=(const Date & d)349 bool Date::operator!=( const Date &d )
350 {
351 return ( !( *this == d ) );
352 }
353
operator <(const Date & d)354 bool Date::operator<( const Date &d )
355 {
356 if( this->year < d.year ) return true;
357 if( this->year > d.year ) return false;
358 if( this->month < d.month ) return true;
359 if( this->month > d.month ) return false;
360 if( this->day < d.day ) return true;
361 return false;
362 }
363
operator >(const Date & d)364 bool Date::operator>( const Date &d )
365 {
366 if( *this < d ) return false;
367 if( *this == d ) return false;
368 return true;
369 }
370
operator =(const Date & d)371 void Date::operator=( const Date &d )
372 {
373 this->year = d.year;
374 this->month = d.month;
375 this->day = d.day;
376 }
377
dJulian()378 double Date::dJulian ()
379 {
380 int DaysInYear = 365;
381 if (leapYear ()) DaysInYear++;
382 return ( year + 1.0 * (dayofyear (year, month, day) - 1) / DaysInYear);
383 }
384