1 ///////////////////////////////////////////////////////////////////////////////
\r 
   3 //      File    : $Id: date.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $
\r 
   4 //      Subject : IBPP, Date class implementation
\r 
   6 ///////////////////////////////////////////////////////////////////////////////
\r 
   8 //      (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)
\r 
  10 //      The contents of this file are subject to the IBPP License (the "License");
\r 
  11 //      you may not use this file except in compliance with the License.  You may
\r 
  12 //      obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'
\r 
  13 //      file which must have been distributed along with this file.
\r 
  15 //      This software, distributed under the License, is distributed on an "AS IS"
\r 
  16 //      basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the
\r 
  17 //      License for the specific language governing rights and limitations
\r 
  18 //      under the License.
\r 
  20 ///////////////////////////////////////////////////////////////////////////////
\r 
  23 //      * Tabulations should be set every four characters when editing this file.
\r 
  25 ///////////////////////////////////////////////////////////////////////////////
\r 
  28 #pragma warning(disable: 4786 4996)
\r 
  30 #pragma warning(disable: 4702)
\r 
  40 #include <time.h>               // Can't use <ctime> thanks to MSVC6 buggy library
\r 
  42 using namespace ibpp_internals;
\r 
  44 void IBPP::Date::Today()
\r 
  46         time_t systime = time(0);
\r 
  47         tm* loctime = localtime(&systime);
\r 
  49         if (! IBPP::itod(&mDate, loctime->tm_year + 1900,
\r 
  50                 loctime->tm_mon + 1, loctime->tm_mday))
\r 
  51                         throw LogicExceptionImpl("Date::Today", _("Out of range"));
\r 
  54 void IBPP::Date::SetDate(int dt)
\r 
  56         if (! IBPP::dtoi(dt, 0, 0, 0))
\r 
  57                 throw LogicExceptionImpl("Date::SetDate", _("Out of range"));
\r 
  61 void IBPP::Date::SetDate(int year, int month, int day)
\r 
  63         if (! IBPP::itod(&mDate, year, month, day))
\r 
  64                 throw LogicExceptionImpl("Date::SetDate", _("Out of range"));
\r 
  67 void IBPP::Date::GetDate(int& year, int& month, int& day) const
\r 
  69         if (! IBPP::dtoi(mDate, &year, &month, &day))
\r 
  70                 throw LogicExceptionImpl("Date::GetDate", _("Out of range"));
\r 
  73 int IBPP::Date::Year() const
\r 
  76         if (! IBPP::dtoi(mDate, &year, 0, 0))
\r 
  77                 throw LogicExceptionImpl("Date::Year", _("Out of range"));
\r 
  81 int IBPP::Date::Month() const
\r 
  84         if (! IBPP::dtoi(mDate, 0, &month, 0))
\r 
  85                 throw LogicExceptionImpl("Date::Month", _("Out of range"));
\r 
  89 int IBPP::Date::Day() const
\r 
  92         if (! IBPP::dtoi(mDate, 0, 0, &day))
\r 
  93                 throw LogicExceptionImpl("Date::Day", _("Out of range"));
\r 
  97 void IBPP::Date::Add(int days)
\r 
  99         int newdate = mDate + days;             // days can be signed
\r 
 100         if (! IBPP::dtoi(newdate, 0, 0, 0))
\r 
 101                 throw LogicExceptionImpl("Date::Add()", _("Out of range"));
\r 
 105 void IBPP::Date::StartOfMonth()
\r 
 108         if (! IBPP::dtoi(mDate, &year, &month, 0))
\r 
 109                 throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range"));
\r 
 110         if (! IBPP::itod(&mDate, year, month, 1))               // First of same month
\r 
 111                 throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range"));
\r 
 114 void IBPP::Date::EndOfMonth()
\r 
 117         if (! IBPP::dtoi(mDate, &year, &month, 0))
\r 
 118                 throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range"));
\r 
 119         if (++month > 12) { month = 1; year++; }
\r 
 120         if (! IBPP::itod(&mDate, year, month, 1))       // First of next month
\r 
 121                 throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range"));
\r 
 122         mDate--;        // Last day of original month, all weird cases accounted for
\r 
 125 IBPP::Date::Date(int year, int month, int day)
\r 
 127         SetDate(year, month, day);
\r 
 130 IBPP::Date::Date(const IBPP::Date& copied)
\r 
 132         mDate = copied.mDate;
\r 
 135 IBPP::Date& IBPP::Date::operator=(const IBPP::Timestamp& assigned)
\r 
 137         mDate = assigned.GetDate();
\r 
 141 IBPP::Date& IBPP::Date::operator=(const IBPP::Date& assigned)
\r 
 143         mDate = assigned.mDate;
\r 
 147 // The following date calculations were inspired by web pages found on
\r 
 148 // Peter Baum web homepage at 'http://www.capecod.net/~pbaum/'.
\r 
 149 // His contact info is at : 'http://home.capecod.net/~pbaum/contact.htm'.
\r 
 150 // Please, understand that Peter Baum is not related to this IBPP project.
\r 
 151 // So __please__, do not contact him regarding IBPP matters.
\r 
 153 //      Take a date, in its integer format as used in IBPP internals and splits
\r 
 154 //      it in year (4 digits), month (1-12), day (1-31)
\r 
 156 bool IBPP::dtoi (int date, int *y, int *m, int *d)
\r 
 158     int RataDie, Z, H, A, B, C;
\r 
 159     int year, month, day;
\r 
 161         // Validity control.
\r 
 162         if (date < IBPP::MinDate || date > IBPP::MaxDate)
\r 
 165         // The "Rata Die" is the date specified as the number of days elapsed since
\r 
 166         // 31 Dec of year 0. So 1 Jan 0001 is 1.
\r 
 168         RataDie = date + ibpp_internals::consts::Dec31_1899;    // Because IBPP sets the '0' on 31 Dec 1899.
\r 
 174     year = (100*B + H) / 36525;
\r 
 175     C = B + Z - 365*year - year / 4;
\r 
 176     month = (5*C + 456) / 153;
\r 
 177     day = C - (153*month - 457) / 5;
\r 
 178     if (month > 12) { year += 1; month -= 12; }
\r 
 180         if (y != 0) *y = (int)year;
\r 
 181         if (m != 0) *m = (int)month;
\r 
 182         if (d != 0) *d = (int)day;
\r 
 187 //      Take a date from its components year, month, day and convert it to the
\r 
 188 //      integer representation used internally in IBPP.
\r 
 190 bool IBPP::itod (int *pdate, int year, int month, int day)
\r 
 192     int RataDie, result;
\r 
 195         d = day;        m = month;              y = year;
\r 
 196     if (m < 3) { m += 12; y -= 1; }
\r 
 197     RataDie = d + (153*m - 457) / 5 + 365*y + y/4 - y/100 + y/400 - 306;
\r 
 199         result = RataDie - ibpp_internals::consts::Dec31_1899;   // Because IBPP sets the '0' on 31 Dec 1899
\r 
 201         // Validity control
\r 
 202         if (result < IBPP::MinDate || result > IBPP::MaxDate)
\r