00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
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
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
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
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
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++;
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
00636 pos++;
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
00650 pos++;
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
00663 h += 12;
00664 }
00665 }
00666 }
00667 else
00668 {
00669
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);
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