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