• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/Dates.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #include <ctype.h>
00018 #include <math.h>
00019 #include <spl/Debug.h>
00020 #include <spl/Date.h>
00021 #include <spl/DateTime.h>
00022 #include <spl/Int32.h>
00023 #include <spl/text/StringBuffer.h>
00024 
00025 static int _daysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00026 
00027 inline bool _IsLeapYear(int year)
00028 {
00029         if ((year % 4) != 0)
00030         {
00031                 return false;
00032         }
00033         else if  ((year % 400) == 0)
00034         {
00035                 return true;
00036         }
00037         else if ((year % 100) == 0)
00038         {
00039                 return false;
00040         }
00041         else
00042         {
00043                 return true;
00044         }
00045 }
00046 
00047 long Date::YmdToJd( const int iYear, const int iMonth, const int iDay )
00048 {
00049     long jul_day;
00050 
00051 #ifndef JULDATE_USE_ALTERNATE_METHOD
00052 
00053     int a,b;
00054     int year = iYear, month = iMonth, day = iDay;
00055     float year_corr;
00056 
00057     if ( year < 0 )
00058         year++;
00059     year_corr = (float)( year > 0 ? 0.0 : 0.75 );
00060     if ( month <= 2 )
00061     {
00062         year--;
00063         month += 12;
00064     }
00065     b = 0;
00066     if ( year * 10000.0 + month * 100.0 + day >= 15821015.0 )
00067     {
00068         a = year / 100;
00069         b = 2 - a + a / 4;
00070     }
00071     jul_day = (long) ( 365.25 * year - year_corr ) +
00072               (long) ( 30.6001 * ( month + 1 ) ) + day + 1720995L + b;
00073 
00074 #else
00075 
00076     long lmonth = (long) iMonth, lday = (long) iDay, lyear = (long) iYear;
00077 
00078     // Adjust BC years
00079     if ( lyear < 0 )
00080         lyear++;
00081 
00082     jul_day = lday - 32075L +
00083         1461L * ( lyear + 4800L + ( lmonth - 14L ) / 12L ) / 4L +
00084         367L * ( lmonth - 2L - ( lmonth - 14L ) / 12L * 12L ) / 12L -
00085         3L * ( ( lyear + 4900L + ( lmonth - 14L ) / 12L ) / 100L ) / 4L;
00086 
00087 #endif
00088 
00089     return jul_day;
00090 }
00091 
00092 void Date::JdToYmd( const long lJD, int *piYear, int *piMonth, int *piDay )
00093 {
00094 #ifndef JULDATE_USE_ALTERNATE_METHOD
00095 
00096     long a, b, c, d, e, z, alpha;
00097 
00098     z = lJD;
00099     if ( z < 2299161L )
00100         a = z;
00101     else
00102     {
00103         alpha = (long) ( ( z - 1867216.25 ) / 36524.25 );
00104         a = z + 1 + alpha - alpha / 4;
00105     }
00106     b = a + 1524;
00107     c = (long) ( ( b - 122.1 ) / 365.25 );
00108     d = (long) ( 365.25 * c );
00109     e = (long) ( ( b - d ) / 30.6001 );
00110     *piDay = (int) b - d - (long) ( 30.6001 * e );
00111     *piMonth = (int) ( e < 13.5 ) ? e - 1 : e - 13;
00112     *piYear = (int) ( *piMonth > 2.5 ) ? ( c - 4716 ) : c - 4715;
00113     if ( *piYear <= 0 )
00114         *piYear -= 1;
00115 
00116 #else
00117 
00118     long t1, t2, yr, mo;
00119 
00120     t1 = lJD + 68569L;
00121     t2 = 4L * t1 / 146097L;
00122     t1 = t1 - ( 146097L * t2 + 3L ) / 4L;
00123     yr = 4000L * ( t1 + 1L ) / 1461001L;
00124     t1 = t1 - 1461L * yr / 4L + 31L;
00125     mo = 80L * t1 / 2447L;
00126     *piDay = (int) ( t1 - 2447L * mo / 80L );
00127     t1 = mo / 11L;
00128     *piMonth = (int) ( mo + 2L - 12L * t1 );
00129     *piYear = (int) ( 100L * ( t2 - 49L ) + yr + t1 );
00130 
00131     // Correct for BC years
00132     if ( *piYear <= 0 )
00133         *piYear -= 1;
00134 
00135 #endif
00136 
00137     return;
00138 }
00139 
00140 void Date::Init(time_t t)
00141 {
00142         struct tm *ptm;
00143         ptm = localtime( &t );
00144         m_y = ptm->tm_year + 1900;
00145         m_m = ptm->tm_mon + 1;
00146         m_d = ptm->tm_mday;
00147         m_lJulianDay = YmdToJd( m_y, m_m, m_d );
00148 }
00149 
00150 Date::Date() 
00151 { 
00152         time_t t;
00153         time( &t );
00154         Init(t);
00155 }
00156 
00157 Date::Date(int year, int mo, int day)
00158 : m_y(year), m_m(mo), m_d(day)
00159 {
00160         if ( year < 100 )
00161         {
00162                 year += 2000;
00163                 m_y = year;
00164         }
00165         ASSERT( mo > 0 && mo < 13 );
00166         ASSERT( day > 0 && day < 32 );
00167         m_lJulianDay = YmdToJd( year, mo, day );
00168 }
00169 
00170 Date::Date( time_t tt )
00171 {
00172         Init( tt );
00173 }
00174 
00175 Date::Date(const Date& dt)
00176 {
00177         m_lJulianDay = dt.m_lJulianDay;
00178         JdToYmd( m_lJulianDay, &m_y, &m_m, &m_d );
00179 }
00180 
00181 Date Date::Parse(const String& str)
00182 {
00183         RefCountPtr<Vector<StringPtr> > dateparts;
00184         int mpos = 0;
00185         int dpos = 1;
00186         int ypos = 2;
00187         if ( str.IndexOf('/') > -1 )
00188         {
00189                 dateparts = str.Split("/");
00190         }
00191         else
00192         {
00193                 dateparts = str.Split("-");
00194                 if (dateparts->Count() > 0 && dateparts->ElementAtRef(0)->Length() == 4)
00195                 {
00196                         ypos = 0;
00197                         mpos = 1;
00198                         dpos = 2;
00199                 }
00200                 else
00201                 {
00202                         mpos = 1;
00203                         dpos = 0;
00204                 }
00205         }
00206         if ( dateparts->Count() != 3 )
00207         {
00208                 throw new InvalidArgumentException("Invalid date");
00209         }
00210         
00211         int m = Int32::Parse(*dateparts->ElementAt(mpos));
00212         int d = Int32::Parse(*dateparts->ElementAt(dpos));
00213         int y = Int32::Parse(*dateparts->ElementAt(ypos));
00214 
00215         return Date(y, m, d);
00216 }
00217 
00218 bool Date::IsDate(const String& str)
00219 {
00220         try
00221         {
00222                 Date::Parse(str);
00223                 return true;
00224         }
00225         catch (Exception *ex)
00226         {
00227                 delete ex;
00228                 return false;
00229         }
00230 }
00231 
00232 Date::~Date()
00233 {
00234 }
00235 
00236 void Date::AddMonths( int months )
00237 {
00238         if ( months > 12 )
00239         {
00240                 AddYears( months / 12 );
00241                 months %= 12;
00242         }
00243         m_m += months;
00244         if ( m_m > 12 )
00245         {
00246                 m_y++;
00247                 m_m -= 12;
00248         }
00249         m_lJulianDay = YmdToJd( m_y, m_m, m_d );
00250         JdToYmd( m_lJulianDay, &m_y, &m_m, &m_d );
00251 }
00252 
00253 int32 Date::HashCode() const
00254 {
00255 #ifdef _WINDOWS
00256         return (int32)( (m_lJulianDay & 0xFFFFFFFFL) ^ (m_lJulianDay / (int64)pow(2.0, 32)) );
00257 #else
00258         return (int32)( (m_lJulianDay & 0xFFFFFFFFL) ^ (m_lJulianDay >> 32L) );
00259 #endif
00260 }
00261 
00262 bool Date::Equals(const IComparable *a) const
00263 {
00264         if (a->MajicNumber() != MajicNumber())
00265         {
00266                 return 1;
00267         }
00268         const Date *vp = static_cast<const Date *>(a);
00269         return Equals(vp);
00270 }
00271 
00272 int Date::Compare(const IComparable *a) const
00273 {
00274         if (a->MajicNumber() != MajicNumber())
00275         {
00276                 return 1;
00277         }
00278         const Date *vp = static_cast<const Date *>(a);
00279         return (int)(m_lJulianDay - vp->m_lJulianDay);
00280 }
00281 
00282 bool Date::Equals(const IComparable& a) const
00283 {
00284         if (a.MajicNumber() != MajicNumber())
00285         {
00286                 return 1;
00287         }
00288         return Equals(static_cast<const Date &>(a));
00289 }
00290 
00291 int Date::Compare(const IComparable& a) const
00292 {
00293         if (a.MajicNumber() != MajicNumber())
00294         {
00295                 return 1;
00296         }
00297         const Date& vp = static_cast<const Date&>(a);
00298         return (int)(m_lJulianDay - vp.m_lJulianDay);
00299 }
00300 
00301 int32 Date::MajicNumber() const
00302 {
00303         return DATE_MAJIC;
00304 }
00305 
00306 /*
00307 bool Date::IsHoliday()
00308 {
00309         switch (m_m)
00310         {
00311                 case 1:
00312                         //      New Years
00313                         //      RULE
00314                         //      January 1.  If on a Saturday, the previous friday is off. If on a Sunday then Monday is off
00315                         if (m_d == 1 && (DayOfWeek() != DayOfWeek::SATURDAY && DayOfWeek() != DayOfWeek::SUNDAY))
00316                         {
00317                                 return true;
00318                         }
00319                         if (m_d == 2 && DayOfWeek == DayOfWeek.Monday)
00320                                 return true;
00321 
00322                         //      MLK Day
00323                         //      RULE
00324                         //      celebrated as third Monday in January, King's birthday is Jan 18.
00325                         if (DayOfWeek == DayOfWeek.Monday)
00326                         {
00327                                 Date mlkDay = new Date(Year, 1, 1);
00328                                 while (mlkDay.DayOfWeek != DayOfWeek.Monday)
00329                                 {
00330                                         mlkDay = mlkDay.AddDays(1);
00331                                 }
00332                                 mlkDay = mlkDay.AddDays(14);
00333 
00334                                 if (this.Equals(mlkDay))
00335                                 {
00336                                         return true;
00337                                 }
00338                         }
00339                         break;
00340                 case 2:
00341                         //      Presidents' Day
00342                         //      RULE
00343                         //      Third Monday in February.  Replaced Lincoln and Washington's birthday in 1971.
00344                         if (DayOfWeek == DayOfWeek.Monday)
00345                         {
00346                                 Date presDay = new Date(Year, 2, 1);
00347                                 while (presDay.DayOfWeek != DayOfWeek.Monday)
00348                                 {
00349                                         presDay = presDay.AddDays(1);
00350                                 }
00351                                 presDay = presDay.AddDays(14);
00352 
00353                                 if (this.Equals(presDay))
00354                                 {
00355                                         return true;
00356                                 }
00357                         }
00358                         break;
00359                 case 5:
00360                         //      Memorial Day
00361                         //      RULE
00362                         //      Last Monday in May. Originally May 31
00363                         if (DayOfWeek == DayOfWeek.Monday)
00364                         {
00365                                 if (AddDays(7).Month() == 6)
00366                                 {
00367                                         return true;
00368                                 }
00369                         }
00370                         break;
00371                 case 7:
00372                         // July 4th
00373                         // RULE
00374                         //      If on a Saturday, then friday is off
00375                         //      If on a Sunday, then monday is off
00376                         if (m_d == 4 && (DayOfWeek != DayOfWeek.Saturday && DayOfWeek != DayOfWeek.Sunday))
00377                         {
00378                                 return true;
00379                         }
00380                         if (m_d == 3 && DayOfWeek == DayOfWeek.Friday)
00381                         {
00382                                 return true;
00383                         }
00384                         if (m_d == 5 && DayOfWeek == DayOfWeek.Monday)
00385                         {
00386                                 return true;
00387                         }
00388                         break;
00389                 case 9:
00390                         //      Labor Day
00391                         //      RULE
00392                         //      First Monday in September. In 1882..1883 it was celebrated on September 5.
00393                         if (DayOfWeek == DayOfWeek.Monday)
00394                         {
00395                                 if (AddDays(-7).Month == 8)
00396                                 {
00397                                         return true;
00398                                 }
00399                         }
00400                         break;
00401                 case 10:
00402                         //      Columbus Day
00403                         //      RULE
00404                         //      1905 .. 1970 -> October 12
00405                         //      1971 .. now  -> Second Monday in October.
00406                         if (DayOfWeek == DayOfWeek.Monday)
00407                         {
00408                                 Date columbusDay = new Date(Year, 10, 1);
00409                                 while (columbusDay.DayOfWeek != DayOfWeek.Monday)
00410                                 {
00411                                         columbusDay = columbusDay.AddDays(1);
00412                                 }
00413                                 columbusDay = columbusDay.AddDays(7);
00414 
00415                                 if (this.Equals(columbusDay))
00416                                 {
00417                                         return true;
00418                                 }
00419                         }
00420                         break;
00421                 case 11:
00422                         // Veterans' Day
00423                         // RULE
00424                         // November 11.  If on a Saturday, the previous friday is off. If on a Sunday then Monday is off
00425                         if (m_d == 11 && DayOfWeek != DayOfWeek.Saturday && DayOfWeek != DayOfWeek.Sunday)
00426                         {
00427                                 return true;
00428                         }
00429                         if (m_d == 10 && DayOfWeek == DayOfWeek.Friday)
00430                         {
00431                                 return true;
00432                         }
00433                         if (m_d == 12 && DayOfWeek == DayOfWeek.Monday)
00434                         {
00435                                 return true;
00436                         }
00437 
00438                         //  Thanksgiving 
00439                         //      RULE
00440                         //      1621         -> first Thanksgiving, precise date unknown.
00441                         //      1622         -> was no Thanksgiving.
00442                         //      1623 .. 1675 -> precise date unknown.
00443                         //      1676 .. 1862 -> June 29.
00444                         //      1863 .. 1938 -> last Thursday of November.
00445                         //      1939 .. 1941 -> 2nd to last Thursday of November.
00446                         //      1942 .. now  -> 4th Thursday of November.
00447                         if (DayOfWeek == DayOfWeek.Thursday)
00448                         {
00449                                 DateTime thanksgivingDay = new DateTime(Year, 11, 1);
00450                                 while (thanksgivingDay.DayOfWeek != DayOfWeek.Thursday)
00451                                 {
00452                                         thanksgivingDay = thanksgivingDay.AddDays(1);
00453                                 }
00454                                 thanksgivingDay = thanksgivingDay.AddDays(21);
00455 
00456                                 if (this.Equals(thanksgivingDay.Date))
00457                                 {
00458                                         return true;
00459                                 }
00460                         }
00461                         else if (DayOfWeek == DayOfWeek.Friday)
00462                         {
00463                                 // the day after is also a bank holiday
00464                                 Date dayAfterTg = new Date(Year, 11, 1);
00465 
00466                                 while (dayAfterTg.DayOfWeek != DayOfWeek.Thursday)
00467                                 {
00468                                         dayAfterTg = dayAfterTg.AddDays(1);
00469                                 }
00470                                 dayAfterTg = dayAfterTg.AddDays(22);
00471 
00472                                 if (this.Equals(dayAfterTg))
00473                                 {
00474                                         return true;
00475                                 }
00476                         }
00477                         break;
00478                 case 12:
00479                         //      Christmas
00480                         //      RULE
00481                         //       If on a saturday, then friday is off
00482                         //       If on a sunday, then monday is off
00483                         if (m_d == 25 && (DayOfWeek != DayOfWeek.Saturday && DayOfWeek != DayOfWeek.Sunday))
00484                         {
00485                                 return true;
00486                         }
00487 
00488                         if (m_d == 24 && DayOfWeek == DayOfWeek.Friday)
00489                         {
00490                                 // the 25th is on saturday
00491                                 return true;
00492                         }
00493                         
00494                         if (m_d == 26 && DayOfWeek == DayOfWeek.Monday)
00495                         {
00496                                 // the 25th is on sunday
00497                                 return true;
00498                         }
00499 
00500                         //      New Years
00501                         //      RULE
00502                         //      January 1.  If on a Saturday, the previous friday is off
00503                         if (m_d == 31 && DayOfWeek == DayOfWeek.Friday)
00504                         {
00505                                 // the friday of Dec 31 is a holiday (jan 1 is on saturday)
00506                                 return true;
00507                         }
00508                         break;
00509         }
00510         return false;
00511 }       
00512 */
00513 
00514 #ifdef DEBUG
00515 void Date::ValidateMem() const
00516 {
00517 }
00518 
00519 void Date::CheckMem() const
00520 {
00521 }
00522 #endif
00523 
00524 DateTime::DateTime()
00525 {
00526         time(&m_timet);
00527         m_dtm = *localtime( &m_timet );
00528 }
00529 
00530 DateTime::DateTime( const time_t t )
00531 {
00532         m_timet = t;
00533         m_dtm = *localtime( &t );
00534 }
00535 
00536 DateTime::DateTime( int year, int month, int day )
00537 {
00538         m_dtm.tm_year = year - 1900 ;
00539         m_dtm.tm_mon = month-1;
00540         m_dtm.tm_mday = day;
00541         m_dtm.tm_hour = 0;
00542         m_dtm.tm_min = 0;
00543         m_dtm.tm_sec = 0;
00544         m_dtm.tm_isdst = 0;
00545 
00546         m_timet = mktime( (struct tm *)&m_dtm );
00547 }
00548 
00549 DateTime::DateTime(const Date& dt)
00550 {
00551         m_dtm.tm_year = dt.Year() ;
00552         m_dtm.tm_mon = dt.Month();
00553         m_dtm.tm_mday = dt.Day();
00554         m_dtm.tm_hour = 0;
00555         m_dtm.tm_min = 0;
00556         m_dtm.tm_sec = 0;
00557         m_dtm.tm_isdst = 0;
00558 
00559         m_timet = mktime( (struct tm *)&m_dtm );
00560 }
00561 
00562 DateTime::DateTime( int year, int month, int day, int hour, int minute, int second )
00563 {
00564         ASSERT( hour > -1 && hour < 24 && minute > -1 && minute < 60 && second > -1 && second < 60 );
00565         m_dtm.tm_year = year - 1900 ;
00566         m_dtm.tm_mon = month-1;
00567         m_dtm.tm_mday = day;
00568         m_dtm.tm_hour = hour;
00569         m_dtm.tm_min = minute;
00570         m_dtm.tm_sec = second;
00571         m_dtm.tm_isdst = 0;
00572 
00573         m_timet = mktime( (struct tm *)&m_dtm );
00574 }
00575 
00576 DateTime::DateTime(const DateTime& dtm)
00577 {
00578         m_dtm = dtm.m_dtm;
00579         m_timet = dtm.m_timet;
00580 }
00581 
00582 DateTime::~DateTime()
00583 {
00584 }
00585 
00586 DateTime DateTime::Parse(const String& str)
00587 {
00588         RefCountPtr<Vector<StringPtr> > dtparts = str.Split(" ");
00589         if (dtparts->Count() == 0)
00590         {
00591                 throw new InvalidArgumentException("Invalid time format");              
00592         }
00593                 
00594         // process date
00595         Date dt(Date::Parse(dtparts->ElementAt(0)));
00596         
00597         int m = dt.Month();
00598         int d = dt.Day();
00599         int y = dt.Year();
00600 
00601         if ( dtparts->Count() == 1 )
00602         {
00603                 return DateTime(y, m, d);
00604         }
00605 
00606         int h, min, s = 0, mm = 0;
00607         char buf[3];
00608         int pos = 0;
00609         StringPtr time = dtparts->ElementAt(1);
00610         if ( dtparts->ElementAt(1)->IndexOf(':') > -1 )
00611         {
00612                 // AM/PM format
00613                 int bpos = 0;
00614                 buf[bpos++] = time->CharAt(pos++);
00615                 if ( time->CharAt(pos) != ':' )
00616                 {
00617                         buf[bpos++] = time->CharAt(pos++);
00618                 }
00619                 buf[bpos] = '\0';
00620                 h = Int32::Parse(buf);
00621                 
00622                 pos++;  // skip :
00623 
00624                 bpos = 0;
00625                 buf[bpos++] = time->CharAt(pos++);
00626                 if ( time->CharAt(pos) != ':' )
00627                 {
00628                         buf[bpos++] = time->CharAt(pos++);
00629                 }
00630                 buf[bpos] = '\0';
00631                 min = Int32::Parse(buf);
00632 
00633                 if ( time->CharAt(pos) == ':' )
00634                 {
00635                         // seconds
00636                         pos++;  // skip :
00637                         
00638                         bpos = 0;
00639                         buf[bpos++] = time->CharAt(pos++);
00640                         if ( isdigit(time->CharAt(pos)) )
00641                         {
00642                                 buf[bpos++] = time->CharAt(pos++);
00643                         }
00644                         buf[bpos] = '\0';
00645                         s = Int32::Parse(buf);
00646 
00647                         if ( time->CharAt(pos) == '.' )
00648                         {
00649                                 // millis
00650                                 pos++;  // skip .
00651 
00652                                 StringPtr smm = time->Substring(pos);
00653                                 mm = Int32::Parse(*smm);
00654                         }
00655 
00656                         while ( time->CharAt(pos) == ' ' )
00657                         {
00658                                 pos++;
00659                         }
00660                         if ( 'P' == time->CharAt(pos) )
00661                         {
00662                                 // PM
00663                                 h += 12;
00664                         }
00665                 }
00666         }
00667         else
00668         {
00669                 // military
00670                 if ( 3 == dtparts->Count() )
00671                 {
00672                         throw new InvalidArgumentException("Invalid time format");
00673                 }
00674                 buf[0] = time->CharAt(pos++);
00675                 buf[1] = time->CharAt(pos++);
00676                 buf[2] = '\0';
00677                 h = Int32::Parse(buf);
00678                 buf[0] = time->CharAt(pos++);
00679                 buf[1] = time->CharAt(pos++);
00680                 buf[2] = '\0';
00681                 min = Int32::Parse(buf);
00682         }
00683 
00684         return DateTime(y, m, d, h, min, s/*, mm*/);
00685 }
00686 
00687 bool DateTime::IsDateTime(const String& str)
00688 {
00689         try
00690         {
00691                 DateTime::Parse(str);
00692                 return true;
00693         }
00694         catch (Exception *ex)
00695         {
00696                 delete ex;
00697                 return false;
00698         }
00699 }
00700 
00701 DateTime DateTime::AddSeconds(int64 seconds) const
00702 {
00704         DateTime dt1(2000, 1, 1, 1, 1, 0);
00705         DateTime dt2(2000, 1, 1, 1, 1, 1);
00706 
00707         double timetSecond = difftime(dt2.m_timet, dt1.m_timet);
00708         return DateTime( (time_t)((time_t)(seconds * timetSecond) + m_timet) );
00709 }
00710 
00711 DateTime DateTime::AddMinutes(int minutes) const
00712 {
00713         return AddSeconds(minutes * 60);
00714 }
00715 
00716 DateTime DateTime::AddHours(int hours) const
00717 {
00718         return AddSeconds(hours * 60L * 60L);
00719 }
00720 
00721 DateTime DateTime::AddDays(int days) const
00722 {
00723         return AddSeconds(days * 24L * 60L * 60L);
00724 }
00725 
00726 DateTime DateTime::AddMonths(int months) const
00727 {
00728         int year = Year() + months / 12;
00729         int day = Day();
00730         int month = Month() + months % 12;
00731 
00732         if (_daysPerMonth[month-1] > day)
00733         {
00734                 if (Date::IsLeapYear(year) && month == 2)
00735                 {
00736                         if (day > 29)
00737                         {
00738                                 day = 29;
00739                         }
00740                 }
00741                 else
00742                 {
00743                         day = _daysPerMonth[month-1];
00744                 }
00745         }
00746         return DateTime(year, month, day, Hour(), Minutes(), Seconds());
00747 }
00748 
00749 DateTime DateTime::AddYears(int years) const
00750 {
00751         int year = Year() + years;
00752         int month = Month();
00753         int day = Day();
00754 
00755         if (!Date::IsLeapYear(year) && Month() == 2)
00756         {
00757                 if (day > 28)
00758                 {
00759                         day = 28;
00760                 }
00761         }
00762         return DateTime(year, month, day, Hour(), Minutes(), Seconds());
00763 }
00764 
00765 int32 DateTime::HashCode() const
00766 {
00767         return ((m_dtm.tm_year - 1900) + m_dtm.tm_yday * 1000) ^ ((m_dtm.tm_hour + m_dtm.tm_min * 60 + m_dtm.tm_sec * 3600) << 16);
00768 }
00769 
00770 bool DateTime::Equals(const IComparable *a) const
00771 {
00772         if (a->MajicNumber() != MajicNumber())
00773         {
00774                 return false;
00775         }
00776         const DateTime *vp = static_cast<const DateTime *>(a);
00777         return Equals(vp);
00778 }
00779 
00780 int DateTime::Compare(const IComparable *a) const
00781 {
00782         if (a->MajicNumber() != MajicNumber())
00783         {
00784                 return 1;
00785         }
00786         const DateTime *vp = static_cast<const DateTime *>(a);
00787         if (Equals(vp))
00788         {
00789                 return 0;
00790         }
00791         return (int)DiffInSeconds(*vp);
00792 }
00793 
00794 bool DateTime::Equals(const IComparable& a) const
00795 {
00796         if (a.MajicNumber() != MajicNumber())
00797         {
00798                 return false;
00799         }
00800         const DateTime& vp = static_cast<const DateTime&>(a);
00801         return Equals(vp);
00802 }
00803 
00804 int DateTime::Compare(const IComparable& a) const
00805 {
00806         if (a.MajicNumber() != MajicNumber())
00807         {
00808                 return 1;
00809         }
00810         const DateTime& vp = static_cast<const DateTime&>(a);
00811         if (Equals(vp))
00812         {
00813                 return 0;
00814         }
00815         return (int)DiffInSeconds(vp);
00816 }
00817 
00818 int32 DateTime::MajicNumber() const
00819 {
00820         return DATETIME_MAJIC;
00821 }
00822 
00823 StringPtr DateTime::ToStringISO8601() const
00824 {
00825         StringBuffer buf(21);
00826         buf.Append(Int32::ToString(Year()));
00827         buf.Append('-');
00828         int i = Month();
00829         if (i < 10)
00830         {
00831                 buf.Append('0');
00832         }
00833         buf.Append(Int32::ToString(i));
00834         buf.Append('-');
00835         if ((i = Day()) < 10)
00836         {
00837                 buf.Append('0');
00838         }
00839         buf.Append(Int32::ToString(i));
00840         buf.Append(' ');
00841         if ((i = Hour()) < 10)
00842         {
00843                 buf.Append('0');
00844         }
00845         buf.Append(Int32::ToString(i));
00846         buf.Append(':');
00847         if ((i = Minutes()) < 10)
00848         {
00849                 buf.Append('0');
00850         }
00851         buf.Append(Int32::ToString(i));
00852         buf.Append(':');
00853         if ((i = Seconds()) < 10)
00854         {
00855                 buf.Append('0');
00856         }
00857         buf.Append(Int32::ToString(i));
00858         
00859         return buf.ToString();
00860 }
00861 
00862 StringPtr DateTime::ToTimeString() const
00863 {
00864         StringBuffer buf(11);
00865         int i;
00866         if ((i = Hour()) < 10)
00867         {
00868                 buf.Append('0');
00869         }
00870         buf.Append(Int32::ToString(i));
00871         buf.Append(':');
00872         if ((i = Minutes()) < 10)
00873         {
00874                 buf.Append('0');
00875         }
00876         buf.Append(Int32::ToString(i));
00877         buf.Append(':');
00878         if ((i = Seconds()) < 10)
00879         {
00880                 buf.Append('0');
00881         }
00882         buf.Append(Int32::ToString(i));
00883         
00884         return buf.ToString();  
00885 }
00886 
00887 #ifdef DEBUG
00888 void DateTime::ValidateMem() const
00889 {
00890 }
00891 
00892 void DateTime::CheckMem() const
00893 {
00894 }
00895 #endif