First checkin, AXE release 0.2
[AXE.git] / src / date.cpp
1 /**************************************************************************
2 **  (c) Copyright 1999, Andromeda Technology & Automation
3 ***************************************************************************
4 ** MODULE INFORMATION *
5 ***********************
6 **      FILE NAME      : date.cpp
7 **      SYSTEM NAME    : AXE - Andromeda X-windows Encapsulation
8 **      VERSION NUMBER : $Revision: 1.1 $
9 **
10 **  DESCRIPTION      :  
11 **
12 **  EXPORTED OBJECTS : 
13 **  LOCAL    OBJECTS : 
14 **  MODULES  USED    :
15 ***************************************************************************
16 **  ADMINISTRATIVE INFORMATION *
17 ********************************
18 **      ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
19 **      CREATION DATE   : Feb 06, 1998
20 **      LAST UPDATE     : Oct 16, 1999
21 **************************************************************************/
22
23 /*****************************
24    $Log: date.cpp,v $
25    Revision 1.1  2002-07-25 08:01:26  arjen
26    First checkin, AXE release 0.2
27
28 *****************************/
29
30 static const char *RCSID = "$Id: date.cpp,v 1.1 2002-07-25 08:01:26 arjen Exp $";
31
32 #include <iostream> 
33 #include <time.h>
34 #include "date.h"
35 #include "parsedate.h"
36
37 static unsigned short mon[] =
38 {
39    0,
40    31, 28, 31, 30,
41    31, 30, 31, 31,
42    30, 31, 30, 31
43 };
44
45 static char * abr_month_name[] =
46 {
47    "xxx",
48    "Jan", "Feb", "Mar", "Apr",
49    "May", "Jun", "Jul", "Aug",
50    "Sep", "Oct", "Nov", "Dec"
51 };
52
53 date::date(String s)
54 {
55    struct parseddate *pd;
56
57    pd = parsedate(s);
58    year = pd->year;
59    month = pd->month;
60    day   = pd->day;
61 }
62
63 int date::Leap(void)
64 {
65    int leap;
66
67    leap = 0;
68    if (year % 4 == 0)
69       leap++;          // leapyear
70    if (year % 100 == 0)
71       leap--;          // But not every century
72    if (year % 400 == 0)
73       leap++;          // except every 4th century
74
75    return leap;
76 }
77
78 unsigned date::DaysInMonth(void)
79 {
80    unsigned days;
81    
82    if (month < 1 || month > 12)
83    {
84       days = 0;
85    }
86    else
87    {
88       days = mon[month];
89    
90       if (month == 2 && Leap())    //  Februari
91       {
92          days++;
93       }                                                 
94    }
95    
96    return days;
97 }
98  
99 date date::add(date D)
100 {
101    year += D.year;
102    month += D.month;
103    while (month > 12)
104    {
105       year++;
106       month -= 12;
107    }
108    day += D.day;
109    while (day > DaysInMonth())
110    {
111       day -= DaysInMonth();
112       month++;
113       if (month > 12)
114       {
115          year++;
116          month -= 12;
117       }
118    }
119
120    return *this;
121 }
122
123 date date::add(unsigned long days)
124 {
125    //  Calculate the date <days> days in the future
126
127    days += day;
128    while (days > DaysInMonth())
129    {
130       days -= DaysInMonth();
131       month++;
132       if (month > 12)
133       {
134          year++;
135          month -= 12;
136       }
137    }
138    day = days;
139
140    return *this;
141 }
142
143 date date::subtract(unsigned long days)
144 {
145    //  Calculate the date <days> days in the past
146
147    while (days != 0)
148    {
149       if (days < day)
150       {
151          day -= days;
152          days = 0;
153       }
154       else
155       {
156          month--;
157          if (month == 0)
158          {
159             year--;
160             month = 12;
161          }
162          days -= day;
163          day = DaysInMonth();
164       }
165    }
166
167    return *this;
168 }
169
170 date operator+(date d1, date d2)
171 {
172    d1.add(d2);
173    return d1;
174 }
175
176 date operator+(unsigned long l, date d)
177 {
178    d.add(l);
179    return d;
180 }
181
182 date operator+(date d, unsigned long l)
183 {
184    d.add(l);
185    return d;
186 }
187
188 date operator-(unsigned long l, date d)
189 {
190    d.subtract(l);
191    return d;
192 }
193
194 date operator-(date d, unsigned long l)
195 {
196    d.subtract(l);
197    return d;
198 }
199
200 date today()
201 {
202    long      clock;
203    struct tm   *tp;
204
205    time(&clock);
206    tp = localtime(&clock);
207    
208    return date(tp->tm_mday, tp->tm_mon+1, tp->tm_year+1900);
209 }
210
211 /*=========================================================================
212 **  NAME           : date::julian
213 **  SYNOPSIS       :
214 **  PARAMETERS     :
215 **  RETURN VALUE   :
216 **
217 **  DESCRIPTION    :  Return the number of days since the base date of the
218 **                    Julian Calendar.
219 **
220 **  VARS USED      :
221 **  VARS CHANGED   :
222 **  FUNCTIONS USED :
223 **  SEE ALSO       :
224 **  LAST MODIFIED  :
225 **  SEE ALSO       :
226 **  LAST MODIFIED  :
227 **=========================================================================
228 */
229
230 long date::julian(void)
231 {
232    register long cent;
233    register int  yr, mn, dy;
234
235    yr = year;
236    mn = month;
237    dy = day;
238
239    if (mn > 2)
240       mn -= 3;
241    else
242    {
243       mn += 9;
244       yr -= 1;
245    }
246
247    cent = yr / 100;
248    yr   %= 100;
249
250    return  (146097 * cent >> 2) + (1461 * yr >> 2) +
251            (153 * mn + 2) / 5 + dy + 1721119;
252
253 }
254
255 long operator-(date &d1, date &d2)
256 {
257    return d1.julian() - d2.julian();
258 }
259
260 ostream &operator<<(ostream &s, const date &d)
261 {
262    s.width(2);
263    s.fill('0');
264
265    s << int(d.day) << "-";
266    s.width(2);
267    s.fill('0');
268    s << int(d.month) << "-";
269    s << d.year;
270
271    return s;
272 }
273
274 istream &operator>>(istream &s, date &d)
275 {
276    char c;
277    int  D, M, Y;
278
279    s >> D >> c >> M >> c >> Y;
280
281    d.day = D;
282    d.month = M;
283    if (Y < 100)
284    {
285       if (Y < 70)
286          Y += 2000;
287       else
288          Y += 1900;
289    }
290    d.year = Y;
291
292    return s;
293 }
294
295 String date::MonthName(void)
296 {
297    if (month <= 12)
298    {
299       return String(abr_month_name[month]);
300    }
301    else
302    {
303       return String("xxx");
304    }
305 }
306
307 String date::format(const char *fmt)
308 {
309    String  s;
310    //char    buf[40];
311    struct  tm  t;
312
313    t.tm_year = year;
314    t.tm_mon  = month;
315    t.tm_mday = day;
316
317    s = String(int(day)) + String(" ") + MonthName() + String(" ") + String(year);
318    //strftime(buf, 40, fmt, &t);
319    //s = buf;
320
321    return s;
322 }
323