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