date.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2008 Marc Boris Duerner
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 #ifndef CXXTOOLS_DATE_H
29 #define CXXTOOLS_DATE_H
30 
31 #include <string>
32 #include <stdexcept>
33 #include <cxxtools/timespan.h>
34 
35 namespace cxxtools
36 {
37 
38 class SerializationInfo;
39 
40 class InvalidDate : public std::invalid_argument
41 {
42  public:
43  InvalidDate();
44 
45  explicit InvalidDate(const std::string& what);
46 
47  ~InvalidDate() throw()
48  {}
49 };
50 
51 void greg2jul(unsigned& jd, int y, int m, int d);
52 
53 void jul2greg(unsigned jd, int& y, int& m, int& d);
54 
55 /*
56  Notes:
57  - Henry F. Fliegel and Thomas C. Van Flandern, "A Machine Algorithm for
58  Processing Calendar Dates". CACM, Vol. 11, No. 10, October 1968, pp 657.
59 */
63 class Date
64 {
65  public:
66  enum Month
67  {
68  Jan = 1, Feb, Mar, Apr, May, Jun,
69  Jul, Aug, Sep, Oct, Nov, Dec
70  };
71 
72  enum WeekDay
73  {
74  Sun = 0, Mon, Tue, Wed, Thu, Fri, Sat
75  };
76 
80  static const unsigned DaysPerYear = 365;
81 
85  static const unsigned DaysPerLeapYear = 366;
86 
90  static const unsigned DaysOfJan = 31;
91 
95  static const unsigned DaysOfFeb = 28;
96 
100  static const unsigned DaysOfLeapFeb = 29;
101 
105  static const unsigned DaysOfMar = 31;
106 
110  static const unsigned DaysOfApr = 30;
111 
115  static const unsigned DaysOfMay = 31;
116 
120  static const unsigned DaysOfJun = 30;
121 
125  static const unsigned DaysOfJul = 31;
126 
130  static const unsigned DaysOfAug = 31;
131 
135  static const unsigned DaysOfSep = 30;
136 
140  static const unsigned DaysOfOct = 31;
141 
145  static const unsigned DaysOfNov = 30;
146 
150  static const unsigned DaysOfDec = 31;
151 
152  public:
157  Date()
158  : _julian(0)
159  {}
160 
174  explicit Date(const std::string& d, const std::string& fmt = "%Y-%m-%d");
175 
181  Date(int y, unsigned m, unsigned d)
182  {
183  greg2jul(_julian, y, m, d);
184  }
185 
188  explicit Date(unsigned julianDays)
189  : _julian(julianDays)
190  {}
191 
194  void setJulian(unsigned d)
195  { _julian=d; }
196 
199  unsigned julian() const
200  { return _julian; }
201 
207  void set(int year, unsigned month, unsigned day)
208  {
209  greg2jul(_julian, year, month, day);
210  }
211 
214  void get(int& year, unsigned& month, unsigned& day) const;
215 
218  unsigned day() const;
219 
222  unsigned month() const;
223 
226  int year() const;
227 
230  unsigned dayOfWeek() const;
231 
234  unsigned daysInMonth() const;
235 
238  unsigned dayOfYear() const;
239 
242  bool leapYear() const;
243 
246  Date& operator=(const Date& date)
247  { _julian = date._julian; return *this; }
248 
251  Date& operator+=(int days)
252  { _julian += days; return *this; }
253 
256  Date& operator-=(int days)
257  { _julian -= days; return *this; }
258 
261  Date& operator++()
262  { _julian++; return *this; }
263 
266  Date& operator--()
267  { _julian--; return *this; }
268 
271  bool operator==(const Date& date) const
272  { return _julian==date._julian; }
273 
276  bool operator!=(const Date& date) const
277  { return _julian!=date._julian; }
278 
281  bool operator<(const Date& date) const
282  { return _julian<date._julian; }
283 
286  bool operator<=(const Date& date) const
287  { return _julian<=date._julian; }
288 
291  bool operator>(const Date& date) const
292  { return _julian>date._julian; }
293 
296  bool operator>=(const Date& date) const
297  { return _julian>=date._julian; }
298 
299  friend inline Date operator+(const Date& d, int days);
300 
301  friend inline Date operator+(int days, const Date& d);
302 
303  friend inline Days operator-(const Date& a, const Date& b);
304 
318  std::string toString(const std::string& fmt = "%Y-%m-%d") const;
319 
326  std::string toIsoString() const
327  { return toString("%Y-%m-%d"); }
328 
339  static Date fromIsoString(const std::string& s)
340  { return Date(s, "%Y-%m-%d"); }
341 
342  public:
345  static bool isValid(int y, int m, int d);
346 
349  static bool leapYear(int year);
350 
351  private:
353  unsigned _julian;
354 };
355 
356 void operator >>=(const SerializationInfo& si, Date& date);
357 
358 void operator <<=(SerializationInfo& si, const Date& date);
359 
360 inline void Date::get(int& y, unsigned& m, unsigned& d) const
361 {
362  int mon, day;
363  jul2greg(_julian, y, mon, day);
364  m = mon;
365  d = day;
366 }
367 
368 
369 inline bool Date::leapYear(int y)
370 {
371  return ((y%4==0) && (y%100!=0)) || (y%400==0);
372 }
373 
374 
375 inline unsigned Date::day() const
376 {
377  int d,m,y;
378  jul2greg(_julian, y ,m, d);
379  return d;
380 }
381 
382 
383 inline unsigned Date::month() const
384 {
385  int d,m,y;
386  jul2greg(_julian, y, m, d);
387  return m;
388 }
389 
390 
391 inline int Date::year() const
392 {
393  int d,m,y;
394  jul2greg(_julian, y, m, d);
395  return y;
396 }
397 
398 
399 inline unsigned Date::dayOfWeek() const
400 {
401  return (_julian+1) % 7;
402 }
403 
404 
405 inline unsigned Date::daysInMonth() const
406 {
407  static const unsigned char monthDays[13]=
408  {
409  0,31,28,31,30,31,30,31,31,30,31,30,31
410  };
411 
412  int y, m, d;
413  jul2greg(_julian, y, m, d);
414 
415  if( m==2 && leapYear(y) )
416  return 29;
417 
418  return monthDays[m];
419 }
420 
421 
422 inline unsigned Date::dayOfYear() const
423 {
424  int y,m,d;
425  unsigned jd;
426  jul2greg(_julian,y,m,d);
427 
428  greg2jul(jd,y,1,1);
429  return _julian-jd+1;
430 }
431 
432 
433 inline bool Date::leapYear() const
434 {
435  int d,m,y;
436  jul2greg(_julian,y,m,d);
437  return leapYear(y);
438 }
439 
440 
441 inline Date operator+(const Date& d, int days)
442 { return Date(d._julian + days); }
443 
444 
445 inline Date operator+(int days, const Date& d)
446 { return Date(days + d._julian); }
447 
448 
449 inline Days operator-(const Date& a, const Date& b)
450 { return Days(a._julian - b._julian); }
451 
452 }
453 
454 #endif