00001 #include ".\date.h"
00002 #include <time.h>
00003 
00004 Date::Date(void)
00005 :_serialNumber(LongInteger(0)){
00006 }
00007 
00008 Date::Date(LongInteger serialNumber)
00009 : _serialNumber(serialNumber) {
00010 }
00011 
00012 Date::Date(Day d, Month m, Year y){
00013         bool leap = isLeap(y);
00014         Day len = monthLength(m,leap), offset = monthOffset(m,leap);
00015         _serialNumber = d + offset + yearOffset(y);
00016 }
00017 
00018 Date::Date(Day d, ShortNatural m, Year y) {
00019         switch (m) {
00020                         case 1:
00021                                 Date(d,January,y);
00022                         case 2:
00023                                 Date(d,February,y);
00024                         case 3:
00025                                 Date(d,March,y);
00026                         case 4:
00027                                 Date(d,April,y);
00028                         case 5:
00029                                 Date(d,May,y);
00030                         case 6:
00031                                 Date(d,June,y);
00032                         case 7:
00033                                 Date(d,July,y);
00034                         case 8:
00035                                 Date(d,August,y);
00036                         case 9:
00037                                 Date(d,September,y);
00038                         case 10:
00039                                 Date(d,October,y);
00040                         case 11:
00041                                 Date(d,November,y);
00042                         case 12:
00043                                 Date(d,December,y);
00044         }
00045 
00046 }
00047 
00048 Weekday Date::weekday() const {
00049         Integer w = _serialNumber % 7;
00050         return Weekday(w == 0 ? 7 : w);
00051 }
00052 
00053 Day Date::dayOfMonth() const {
00054         return dayOfYear() - monthOffset(month(),isLeap(year()));
00055 }
00056 
00057 Day Date::dayOfYear() const {
00058         return (Day)(_serialNumber - yearOffset(year()));
00059 }
00060 
00061 Month Date::month() const {
00062         Day d = dayOfYear();
00063         Integer m = d/30 + 1;
00064         bool leap = isLeap(year());
00065         while (d <= monthOffset(Month(m),leap))
00066                 m--;
00067         while (d > monthOffset(Month(m+1),leap))
00068                 m++;
00069         return Month(m);
00070 }
00071 
00072 Year Date::year() const {
00073         Year y = (Year)(1900+(_serialNumber / 365));
00074         if (_serialNumber <= yearOffset(y))
00075                 y--;
00076         return y;
00077 }
00078 
00079 LongInteger Date::serialNumber() const {
00080         return _serialNumber;
00081 }
00082 
00083 bool Date::isEndOfMonth() const {
00084         return isEOM(*this);
00085 }
00086 
00087 Day Date::lastDayOfMonth() const {
00088         return endOfMonth(*this).dayOfMonth();
00089 }
00090 
00091 void Date::setDateToToday() {
00092         time_t tval = time(0);
00093         struct tm *tmp= localtime(&tval);
00094         bool leap = isLeap(tmp->tm_year + 1900);
00095         Day len = monthLength(Month(tmp->tm_mon+1),leap), offset = monthOffset(Month(tmp->tm_mon+1),leap);
00096         _serialNumber = tmp->tm_mday + offset + yearOffset(tmp->tm_year + 1900);
00097 }
00098 
00099 Date& Date::operator+=(LongInteger days) {
00100         LongInteger serial = _serialNumber + days;
00101         _serialNumber = serial;
00102         return *this;
00103 }
00104 
00105 Date& Date::operator-=(LongInteger days) {
00106         LongInteger serial = _serialNumber - days;
00107         _serialNumber = serial;
00108         return *this;
00109 }
00110 
00111 Date& Date::operator++() {
00112         LongInteger serial = _serialNumber + 1;
00113         _serialNumber = serial;
00114         return *this;
00115 }
00116 
00117 Date Date::operator++(int ) {
00118         Date temp = *this;
00119         LongInteger serial = _serialNumber + 1;
00120         _serialNumber = serial;
00121         return temp;
00122 }
00123 
00124 Date& Date::operator--() {
00125         LongInteger serial = _serialNumber - 1;
00126         _serialNumber = serial;
00127         return *this;
00128 }
00129 
00130 Date Date::operator--(int ) {
00131         Date temp = *this;
00132         LongInteger serial = _serialNumber - 1;
00133         _serialNumber = serial;
00134         return temp;
00135 }
00136 
00137 Date Date::operator+(LongInteger days) const {
00138         return Date(_serialNumber+days);
00139 }
00140 
00141 Date Date::operator-(LongInteger days) const {
00142         return Date(_serialNumber-days);
00143 }
00144 
00145 Date Date::plusDays(Integer days) const {
00146         return advance(*this,days,Days);
00147 }
00148 
00149 Date Date::plusWeeks(Integer weeks) const {
00150         return advance(*this,weeks,Weeks);
00151 }
00152 
00153 Date Date::plusMonths(Integer months) const {
00154         return advance(*this,months,Months);
00155 }
00156 
00157 Date Date::plusYears(Integer years) const {
00158         return advance(*this,years,Years);
00159 }
00160 
00161 Date Date::plus(Integer n, TimeUnit units) const {
00162         return advance(*this,n,units);
00163 }
00164 
00165 Date Date::minDate() {
00166         static const Date minimumDate(minimumSerialNumber());
00167         return minimumDate;
00168 }
00169 
00170 Date Date::maxDate() {
00171         static const Date maximumDate(maximumSerialNumber());
00172         return maximumDate;
00173 }
00174 
00175 Date Date::advance(const Date& date, Integer n, TimeUnit units) {
00176         switch (units) {
00177                   case Days:
00178                           return date + n;
00179                   case Weeks:
00180                           return date + 7*n;
00181                   case Months: {
00182                           Day d = date.dayOfMonth();
00183                           Integer m = Integer(date.month())+n;
00184                           Year y = date.year();
00185                           while (m > 12) {
00186                                   m -= 12;
00187                                   y += 1;
00188                           }
00189                           while (m < 1) {
00190                                   m += 12;
00191                                   y -= 1;
00192                           }
00193 
00194                           Integer length = monthLength(Month(m), isLeap(y));
00195                           if (d > length)
00196                                   d = length;
00197 
00198                           return Date(d, Month(m), y);
00199                                            }
00200                   case Years: {
00201                           Day d = date.dayOfMonth();
00202                           Month m = date.month();
00203                           Year y = date.year()+n;
00204 
00205                           if (d == 29 && m == February && !isLeap(y))
00206                                   d = 28;
00207 
00208                           return Date(d,m,y);
00209                                           }
00210                   
00211 
00212         }
00213 }
00214 
00215 bool Date::isLeap(Year y) {
00216         static const bool YearIsLeap[] = {
00217                         
00218                         true,false,false,false, true,false,false,false, true,false,
00219                         
00220                         false,false, true,false,false,false, true,false,false,false,
00221                         
00222                         true,false,false,false, true,false,false,false, true,false,
00223                         
00224                         false,false, true,false,false,false, true,false,false,false,
00225                         
00226                         true,false,false,false, true,false,false,false, true,false,
00227                         
00228                         false,false, true,false,false,false, true,false,false,false,
00229                         
00230                         true,false,false,false, true,false,false,false, true,false,
00231                         
00232                         false,false, true,false,false,false, true,false,false,false,
00233                         
00234                         true,false,false,false, true,false,false,false, true,false,
00235                         
00236                         false,false, true,false,false,false, true,false,false,false,
00237                         
00238                         true,false,false,false, true,false,false,false, true,false,
00239                         
00240                         false,false, true,false,false,false, true,false,false,false,
00241                         
00242                         true,false,false,false, true,false,false,false, true,false,
00243                         
00244                         false,false, true,false,false,false, true,false,false,false,
00245                         
00246                         true,false,false,false, true,false,false,false, true,false,
00247                         
00248                         false,false, true,false,false,false, true,false,false,false,
00249                         
00250                         true,false,false,false, true,false,false,false, true,false,
00251                         
00252                         false,false, true,false,false,false, true,false,false,false,
00253                         
00254                         true,false,false,false, true,false,false,false, true,false,
00255                         
00256                         false,false, true,false,false,false, true,false,false,false,
00257                         
00258                         false
00259         };
00260         return YearIsLeap[y-1900];
00261 }
00262 
00263 Date Date::endOfMonth(const Date& d) {
00264         Month m = d.month();
00265         Year y = d.year();
00266         return Date(monthLength(m, isLeap(y)), m, y);
00267 }
00268 
00269 bool Date::isEOM(const Date& d) {
00270         return (d.dayOfMonth() == monthLength(d.month(), isLeap(d.year())));
00271 }
00272 
00273 Date Date::nextWeekday(const Date& d, Weekday dayOfWeek) {
00274         Weekday wd = d.weekday();
00275         return d + ((wd>dayOfWeek ? 7 : 0) - wd + dayOfWeek);
00276 }
00277 
00278 Date Date::nthWeekday(ShortInteger nth, Weekday dayOfWeek, Month m, Year y) 
00279 {
00280         Weekday first = Date(1, m, y).weekday();
00281         ShortInteger skip = nth - (dayOfWeek>=first ? 1 : 0);
00282         return Date(1 + dayOfWeek-first + skip*7, m, y);
00283 }
00284 
00285 Integer Date::monthLength(Month m, bool leapYear) {
00286         static const Integer MonthLength[] = {
00287                 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
00288         };
00289         static const Integer MonthLeapLength[] = {
00290                 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
00291         };
00292         return (leapYear? MonthLeapLength[m-1] : MonthLength[m-1]);
00293 }
00294 
00295 Integer Date::monthOffset(Month m, bool leapYear) {
00296         static const Integer MonthOffset[] = {
00297                 0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334,
00298                         365     
00299         };
00300         static const Integer MonthLeapOffset[] = {
00301                 0,  31,  60,  91, 121, 152,     182, 213, 244, 274, 305, 335,
00302                         366     
00303         };
00304         return (leapYear? MonthLeapOffset[m-1] : MonthOffset[m-1]);
00305 }
00306 LongInteger Date::yearOffset(Year y) {
00307         static const LongInteger YearOffset[] = {
00308                         
00309                         0,  366,  731, 1096, 1461, 1827, 2192, 2557, 2922, 3288,
00310                         
00311                         3653, 4018, 4383, 4749, 5114, 5479, 5844, 6210, 6575, 6940,
00312                         
00313                         7305, 7671, 8036, 8401, 8766, 9132, 9497, 9862,10227,10593,
00314                         
00315                         10958,11323,11688,12054,12419,12784,13149,13515,13880,14245,
00316                         
00317                         14610,14976,15341,15706,16071,16437,16802,17167,17532,17898,
00318                         
00319                         18263,18628,18993,19359,19724,20089,20454,20820,21185,21550,
00320                         
00321                         21915,22281,22646,23011,23376,23742,24107,24472,24837,25203,
00322                         
00323                         25568,25933,26298,26664,27029,27394,27759,28125,28490,28855,
00324                         
00325                         29220,29586,29951,30316,30681,31047,31412,31777,32142,32508,
00326                         
00327                         32873,33238,33603,33969,34334,34699,35064,35430,35795,36160,
00328                         
00329                         36525,36891,37256,37621,37986,38352,38717,39082,39447,39813,
00330                         
00331                         40178,40543,40908,41274,41639,42004,42369,42735,43100,43465,
00332                         
00333                         43830,44196,44561,44926,45291,45657,46022,46387,46752,47118,
00334                         
00335                         47483,47848,48213,48579,48944,49309,49674,50040,50405,50770,
00336                         
00337                         51135,51501,51866,52231,52596,52962,53327,53692,54057,54423,
00338                         
00339                         54788,55153,55518,55884,56249,56614,56979,57345,57710,58075,
00340                         
00341                         58440,58806,59171,59536,59901,60267,60632,60997,61362,61728,
00342                         
00343                         62093,62458,62823,63189,63554,63919,64284,64650,65015,65380,
00344                         
00345                         65745,66111,66476,66841,67206,67572,67937,68302,68667,69033,
00346                         
00347                         69398,69763,70128,70494,70859,71224,71589,71955,72320,72685,
00348                         
00349                         73050
00350         };
00351         return YearOffset[y-1900];
00352 }
00353 
00354 LongInteger Date::minimumSerialNumber() {
00355         return 367;
00356 }
00357 
00358 LongInteger Date::maximumSerialNumber() {
00359         return 73050;    
00360 }
00361 
00362 bool Date::isBusinessDay() {
00363         return 1;
00364 }
00365 
00366 void Date::applyConvention(BusinessDayConvention convention) {
00367         switch (convention) {
00368                 case Preceding:
00369                         while (!isBusinessDay()) {_serialNumber--;};
00370                 case ModifiedPreceding: {
00371                         LongInteger ser=_serialNumber;
00372                         while (!isBusinessDay()) {_serialNumber--;};
00373                         if (Date(ser).month()!=month()) {
00374                                 _serialNumber=ser;
00375                                 while (!isBusinessDay()) {_serialNumber++;};
00376                         }
00377                 }
00378                 case Following:
00379                         while (!isBusinessDay()) {_serialNumber++;};
00380                 case ModifiedFollowing: {
00381                         LongInteger ser=_serialNumber;
00382                         while (!isBusinessDay()) {_serialNumber++;};
00383                         if (Date(ser).month()!=month()) {
00384                                 _serialNumber=ser;
00385                                 while (!isBusinessDay()) {_serialNumber--;};
00386                         }
00387                 }
00388         }
00389 }               
00390 
00391 Date Date::returnDateConvention(const Date& date, BusinessDayConvention convention) {
00392         Date d1=Date(date.serialNumber());
00393         d1.applyConvention(convention);
00394         return d1;
00395 }
00396 
00397 Real Date::dayCount(const Date& d,DayCountConvention dayconvention) const {
00398         switch (dayconvention) {
00399                 case ACT_365:
00400                         return (TN_REAL(d.serialNumber()-_serialNumber)/365);
00401                 case ACT_360:
00402                         return (TN_REAL(d.serialNumber()-_serialNumber)/360);
00403                 case Day30_365:
00404                         return (TN_REAL(d.dayOfMonth()+30-dayOfMonth()+30*(12*(d.year()-year())+d.month()-month()))/365);
00405                 case Day30_360:
00406                         return (TN_REAL(d.dayOfMonth()+30-dayOfMonth()+30*(12*(d.year()-year())+d.month()-month()))/360);
00407                 default:
00408                         return (TN_REAL(d.serialNumber()-_serialNumber)/365);
00409         }
00410 }
00411 
00412 char* Date::toString() const {
00413         char* strDate=new char[10];
00414         sprintf(strDate,"%d/%d/%d",month(),dayOfMonth(),year());
00415         return strDate;
00416 }
00417 
00418 Date::~Date(void)
00419 {
00420 }