00001
00011 #include "O3DBIDate.h"
00012 #include "O3DBIException.h"
00013 #include "O3DBIError.h"
00014
00015 #define O3DBI_DATE_YEAR_MIN -4712
00016 #define O3DBI_DATE_YEAR_MAX 9999
00017 #define O3DBI_DATE_MONTH_MIN 1
00018 #define O3DBI_DATE_MONTH_MAX 12
00019 #define O3DBI_DATE_DAY_MIN 1
00020 #define O3DBI_DATE_DAY_MAX 31
00021 #define O3DBI_DATE_HOUR_MIN 0
00022 #define O3DBI_DATE_HOUR_MAX 23
00023 #define O3DBI_DATE_MINUTE_MIN 0
00024 #define O3DBI_DATE_MINUTE_MAX 59
00025 #define O3DBI_DATE_SECOND_MIN 0
00026 #define O3DBI_DATE_SECOND_MAX 59
00027
00028 #ifndef MAX_TIME_BUFFER_SIZE
00029 #define MAX_TIME_BUFFER_SIZE 128
00030 #endif
00031 #define MAX_TIME_FORMAT_SIZE 64
00032
00033
00034
00035
00036 int O3DBIDate::_arrDaysInMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30,
00037 31, 30, 31 };
00038
00039
00040
00041
00042 O3DBIDate::O3DBIDate()
00043 {
00044 _value._year = 1899;
00045 _value._month = 12;
00046 _value._day = 30;
00047 _value._hour = 0;
00048 _value._minute = 0;
00049 _value._second = 0;
00050 }
00051
00052 O3DBIDate::O3DBIDate(int year,
00053 int month,
00054 int day,
00055 int hour,
00056 int minute,
00057 int second)
00058 {
00059 _value._year = year;
00060 _value._month = month;
00061 _value._day = day;
00062 _value._hour = hour;
00063 _value._minute = minute;
00064 _value._second = second;
00065
00066 if (! RangeCheck())
00067 throw new O3DBIException(O3DBI_INVALID_DATE,
00068 O3DBIErrorTxt::pchInvalidDate, _T("O3DBIDate::O3DBIDate"), this);
00069 if (JumpFromJulianToGregorian())
00070 _value._day = 15;
00071 }
00072
00073 O3DBIDate::O3DBIDate(const tm& t)
00074 {
00075 (*this) = t;
00076 }
00077
00078 O3DBIDate::O3DBIDate(time_t time)
00079 {
00080 (*this) = time;
00081 }
00082
00083 O3DBIDate::O3DBIDate(unsigned long ulJulianDay)
00084 {
00085
00086
00087 unsigned long t1;
00088 unsigned long t2;
00089 unsigned long yr;
00090 unsigned long mo;
00091
00092 t1 = ulJulianDay + 68569L;
00093 t2 = 4L * t1 / 146097L;
00094 t1 = t1 - (146097L * t2 + 3L) / 4L;
00095 yr = 4000L * (t1 + 1L) / 1461001L;
00096 t1 = t1 - 1461L * yr / 4L + 31L;
00097 mo = 80L * t1 / 2447L;
00098 _value._day = static_cast<int>(t1 - 2447L * mo / 80L);
00099 t1 = mo / 11L;
00100 _value._month = static_cast<int>(mo + 2L - 12L * t1);
00101 _value._year = static_cast<int>(100L * (t2 - 49L) + yr + t1);
00102
00103
00104 if (_value._year <= 0)
00105 _value._year -= 1;
00106
00107
00108 _value._hour = 0;
00109 _value._minute = 0;
00110 _value._second = 0;
00111
00112 if (! RangeCheck())
00113 throw new O3DBIException(O3DBI_INVALID_DATE,
00114 O3DBIErrorTxt::pchInvalidDate, _T("O3DBIDate::O3DBIDate"), this);
00115
00116 if (JumpFromJulianToGregorian())
00117 _value._day = 15;
00118 }
00119
00120 O3DBIDate::O3DBIDate(const O3DBIDate& other)
00121 {
00122 (*this) = other;
00123 }
00124
00125 O3DBIDate::~O3DBIDate()
00126 {
00127
00128 }
00129
00130
00131
00132
00133 O3DBIDate& O3DBIDate::operator=(const O3DBIDate& other)
00134 {
00135 _value._year = other._value._year;
00136 _value._month = other._value._month;
00137 _value._day = other._value._day;
00138 _value._hour = other._value._hour;
00139 _value._minute = other._value._minute;
00140 _value._second = other._value._second;
00141 return (*this);
00142 }
00143
00144 O3DBIDate& O3DBIDate::operator=(const tm& t)
00145 {
00146 _value._year = 1900 + t.tm_year;
00147 _value._month = t.tm_mon;
00148 _value._day = t.tm_mday;
00149 _value._hour = t.tm_hour;
00150 _value._minute = t.tm_min;
00151 _value._second = t.tm_sec;
00152 return (*this);
00153 }
00154
00155 O3DBIDate& O3DBIDate::operator=(time_t time)
00156 {
00157 tm* t;
00158 t = ::gmtime(&time);
00159 (*this) = *t;
00160 return (*this);
00161 }
00162
00163
00164
00165
00166 bool O3DBIDate::operator==(const O3DBIDate& other) const
00167 {
00168 return (_value._year == other._value._year &&
00169 _value._month == other._value._month &&
00170 _value._day == other._value._day &&
00171 _value._hour == other._value._hour &&
00172 _value._minute == other._value._minute &&
00173 _value._second == other._value._second);
00174 }
00175
00176 bool O3DBIDate::operator!=(const O3DBIDate& other) const
00177 {
00178 return (! ((*this) == other));
00179 }
00180
00181 bool O3DBIDate::operator>=(const O3DBIDate& other) const
00182 {
00183 if (_value._year < other._value._year)
00184 return false;
00185 if (_value._month < other._value._month)
00186 return false;
00187 if (_value._day < other._value._day)
00188 return false;
00189 if (_value._hour < other._value._hour)
00190 return false;
00191 if (_value._minute < other._value._minute)
00192 return false;
00193 if (_value._second < other._value._second)
00194 return false;
00195 return true;
00196 }
00197
00198 bool O3DBIDate::operator>(const O3DBIDate& other) const
00199 {
00200 if (_value._year > other._value._year)
00201 return true;
00202 if (_value._year < other._value._year)
00203 return false;
00204 if (_value._month > other._value._month)
00205 return true;
00206 if (_value._month < other._value._month)
00207 return false;
00208 if (_value._day > other._value._day)
00209 return true;
00210 if (_value._day < other._value._day)
00211 return false;
00212 if (_value._hour > other._value._hour)
00213 return true;
00214 if (_value._hour < other._value._hour)
00215 return false;
00216 if (_value._minute > other._value._minute)
00217 return true;
00218 if (_value._minute < other._value._minute)
00219 return false;
00220 if (_value._second > other._value._second)
00221 return true;
00222 return false;
00223 }
00224
00225 bool O3DBIDate::operator<(const O3DBIDate& other) const
00226 {
00227 if (_value._year < other._value._year)
00228 return true;
00229 if (_value._year > other._value._year)
00230 return false;
00231 if (_value._month < other._value._month)
00232 return true;
00233 if (_value._month > other._value._month)
00234 return false;
00235 if (_value._day < other._value._day)
00236 return true;
00237 if (_value._day > other._value._day)
00238 return false;
00239 if (_value._hour < other._value._hour)
00240 return true;
00241 if (_value._hour > other._value._hour)
00242 return false;
00243 if (_value._minute < other._value._minute)
00244 return true;
00245 if (_value._minute > other._value._minute)
00246 return false;
00247 if (_value._second < other._value._second)
00248 return true;
00249 return false;
00250 }
00251
00252 bool O3DBIDate::operator<=(const O3DBIDate& other) const
00253 {
00254 if (_value._year > other._value._year)
00255 return false;
00256 if (_value._month > other._value._month)
00257 return false;
00258 if (_value._day > other._value._day)
00259 return false;
00260 if (_value._hour > other._value._hour)
00261 return false;
00262 if (_value._minute > other._value._minute)
00263 return false;
00264 if (_value._second > other._value._second)
00265 return false;
00266 return true;
00267 }
00268
00269
00270
00271
00272 bool O3DBIDate::IsLeapYear() const
00273 {
00274 if (_value._year < 1600)
00275 {
00276
00277 return ((_value._year % 4) == 0);
00278 } else {
00279
00280
00281 if ((_value._year % 400) == 0)
00282 return true;
00283 else if ((_value._year % 100) == 0)
00284 return false;
00285 else if ((_value._year % 4) == 0)
00286 return true;
00287 }
00288 return false;
00289 }
00290
00291 int O3DBIDate::GetYear() const
00292 {
00293 return _value._year;
00294 }
00295
00296 void O3DBIDate::SetYear(int year)
00297 {
00298 if (year < O3DBI_DATE_YEAR_MIN || year > O3DBI_DATE_YEAR_MAX)
00299 throw new O3DBIException(O3DBI_VALUE_OUTOFRANGE,
00300 O3DBIErrorTxt::pchValueOutOfRange, _T("O3DBIDate::SetYear"), this);
00301 _value._year = year;
00302 if (JumpFromJulianToGregorian())
00303 _value._day = 15;
00304 }
00305
00306 int O3DBIDate::GetMonth() const
00307 {
00308 return _value._month;
00309 }
00310
00311 void O3DBIDate::SetMonth(int month)
00312 {
00313 if (month < O3DBI_DATE_MONTH_MIN || month > O3DBI_DATE_MONTH_MAX)
00314 throw new O3DBIException(O3DBI_VALUE_OUTOFRANGE,
00315 O3DBIErrorTxt::pchValueOutOfRange, _T("O3DBIDate::SetMonth"), this);
00316 _value._month = month;
00317 if (JumpFromJulianToGregorian())
00318 _value._day = 15;
00319 }
00320
00321 int O3DBIDate::GetDay() const
00322 {
00323 return _value._day;
00324 }
00325
00326 void O3DBIDate::SetDay(int day)
00327 {
00328 if (day < O3DBI_DATE_DAY_MIN || day > O3DBI_DATE_DAY_MAX)
00329 throw new O3DBIException(O3DBI_VALUE_OUTOFRANGE,
00330 O3DBIErrorTxt::pchValueOutOfRange, _T("O3DBIDate::SetDay"), this);
00331 _value._day = day;
00332 if (JumpFromJulianToGregorian())
00333 _value._day = 15;
00334 }
00335
00336 int O3DBIDate::GetHour() const
00337 {
00338 return _value._hour;
00339 }
00340
00341 void O3DBIDate::SetHour(int hour)
00342 {
00343 if (hour < O3DBI_DATE_HOUR_MIN || hour > O3DBI_DATE_HOUR_MAX)
00344 throw new O3DBIException(O3DBI_VALUE_OUTOFRANGE,
00345 O3DBIErrorTxt::pchValueOutOfRange, _T("O3DBIDate::SetHour"), this);
00346 _value._hour = hour;
00347 }
00348
00349 int O3DBIDate::GetMinute() const
00350 {
00351 return _value._minute;
00352 }
00353
00354 void O3DBIDate::SetMinute(int minute)
00355 {
00356 if (minute < O3DBI_DATE_MINUTE_MIN || minute > O3DBI_DATE_MINUTE_MAX)
00357 throw new O3DBIException(O3DBI_VALUE_OUTOFRANGE,
00358 O3DBIErrorTxt::pchValueOutOfRange, _T("O3DBIDate::SetMinute"), this);
00359 _value._minute = minute;
00360 }
00361
00362 int O3DBIDate::GetSecond() const
00363 {
00364 return _value._second;
00365 }
00366
00367 void O3DBIDate::SetSecond(int second)
00368 {
00369 if (second < O3DBI_DATE_SECOND_MIN || second > O3DBI_DATE_SECOND_MAX)
00370 throw new O3DBIException(O3DBI_VALUE_OUTOFRANGE,
00371 O3DBIErrorTxt::pchValueOutOfRange, _T("O3DBIDate::SetSecond"), this);
00372 _value._second = second;
00373 }
00374
00375 unsigned short O3DBIDate::GetDayOfWeek() const
00376 {
00377 return ((static_cast<int>(GetJulianDay() % 7L) + 1) % 7);
00378 }
00379
00380 int O3DBIDate::GetDayOfYear() const
00381 {
00382 int iDay = _value._day;
00383 int iMonth = _value._month;
00384
00385 while (iMonth > 1)
00386 {
00387 --iMonth;
00388 iDay += _arrDaysInMonth[iMonth];
00389 if (IsLeapYear() && iMonth == 2)
00390 ++iDay;
00391 }
00392 return iDay;
00393 }
00394
00395 int O3DBIDate::GetCalendarWeek() const
00396 {
00397 const O3DBIDate date1stJanuary(_value._year, 1, 1, 0, 0, 0);
00398 int iWeekdayOf1stJanuary = date1stJanuary.GetDayOfWeek() - 1;
00399 int iDayOfYear = GetDayOfYear();
00400
00401 if (iWeekdayOf1stJanuary >= 4)
00402 iWeekdayOf1stJanuary -= 7;
00403
00404 if ((iDayOfYear + iWeekdayOf1stJanuary) <= 0)
00405 {
00406
00407 O3DBIDate datePrevDay(_value._year - 1, 12, 31, 0, 0, 0);
00408 return datePrevDay.GetCalendarWeek();
00409 }
00410
00411 short iCalendarWeek = ((iDayOfYear - 1 + iWeekdayOf1stJanuary) / 7) + 1;
00412
00413 if ((iCalendarWeek == 53) && (iWeekdayOf1stJanuary != 3))
00414 return 1;
00415 return iCalendarWeek;
00416 }
00417
00418 long O3DBIDate::GetJulianDay() const
00419 {
00420 int year = _value._year;
00421 int month = _value._month;
00422 int day = _value._day;
00423
00424 int a;
00425 int b = 0;
00426 float fYearCorrection;
00427
00428 if (year < 0)
00429 ++year;
00430 fYearCorrection = (year > 0) ? 0.0 : 0.75;
00431 if (month <= 2)
00432 {
00433 --year;
00434 month += 12;
00435 }
00436
00437 if ((year * 10000.0 + month * 100.0 + day) >= 15821015.0)
00438 {
00439 a = year / 100;
00440 b = 2 - a + a / 4;
00441 }
00442 return (static_cast<long>(365.25 * year - fYearCorrection) +
00443 static_cast<long>(30.6001 * (month + 1)) + day + 1720995L + b);
00444 }
00445
00446 TO3DBIString O3DBIDate::GetAsString(PC_TCHAR pchFormat ) const
00447 {
00448 if (pchFormat != NULL && ::_tcslen(pchFormat) > MAX_TIME_FORMAT_SIZE)
00449 throw new O3DBIException(O3DBI_VALUE_FORMATSTRINGSIZE,
00450 O3DBIErrorTxt::pchValueFormatStringSize, _T("O3DBIDate::GetAsString"),
00451 this);
00452
00453 _TCHAR buffer[MAX_TIME_BUFFER_SIZE];
00454 ::memset(&buffer, 0, MAX_TIME_BUFFER_SIZE * sizeof(_TCHAR));
00455
00456 tm tmTemp;
00457 tmTemp.tm_year = _value._year - 1900;
00458 tmTemp.tm_mon = _value._month - 1;
00459 tmTemp.tm_mday = _value._day;
00460 tmTemp.tm_hour = _value._hour;
00461 tmTemp.tm_min = _value._minute;
00462 tmTemp.tm_sec = _value._second;
00463 tmTemp.tm_wday = GetDayOfWeek();
00464 tmTemp.tm_yday = GetDayOfYear();
00465 tmTemp.tm_isdst = 0;
00466
00467 if (pchFormat != NULL)
00468 {
00469 int iResult =
00470 ::_tcsftime(buffer, MAX_TIME_BUFFER_SIZE, pchFormat, &tmTemp);
00471 if (iResult == 0)
00472 ::_tcsncpy(buffer, _T("### DATE ###"), 13);
00473 return TO3DBIString(buffer);
00474 } else {
00475 return TO3DBIString(::_tasctime(&tmTemp));
00476 }
00477 }
00478
00479 TO3DBIString O3DBIDate::ToString() const
00480 {
00481 _TCHAR buffer[LARGESTRING_BUFFERSIZE];
00482 int p;
00483
00484 p = ::_stprintf(buffer, _T("O3DBIDate at 0x%x\n"), this);
00485 ::_stprintf(buffer + p, _T("\tValue: %s"),
00486 GetAsString(_T("%Y-%m-%d %H:%M:%S (%A)")).c_str());
00487
00488 return TO3DBIString(buffer);
00489 }
00490
00491
00492
00493
00494
00495 bool O3DBIDate::RangeCheck() const
00496 {
00497 if (_value._year < O3DBI_DATE_YEAR_MIN ||
00498 _value._year > O3DBI_DATE_YEAR_MAX ||
00499 _value._month < O3DBI_DATE_MONTH_MIN ||
00500 _value._month > O3DBI_DATE_MONTH_MAX)
00501 return false;
00502
00503 int iDay = (_arrDaysInMonth[_value._month] + (IsLeapYear() ? 1 : 0));
00504
00505 if (_value._day < O3DBI_DATE_DAY_MIN ||
00506 _value._day > iDay ||
00507 _value._hour < O3DBI_DATE_HOUR_MIN ||
00508 _value._hour > O3DBI_DATE_HOUR_MAX ||
00509 _value._minute < O3DBI_DATE_MINUTE_MIN ||
00510 _value._minute > O3DBI_DATE_MINUTE_MAX ||
00511 _value._second < O3DBI_DATE_SECOND_MIN ||
00512 _value._second > O3DBI_DATE_SECOND_MAX)
00513 return false;
00514 return true;
00515 }
00516
00517
00518
00519
00520
00521 bool O3DBIDate::JumpFromJulianToGregorian() const
00522 {
00523 if (_value._year == 1582 && _value._month == 10)
00524 return (_value._day > 4 && _value._day < 15);
00525 return false;
00526 }
00527