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