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 }