00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "base/date.h"
00029 #include "base/string.hpp"
00030 #include "base/memory.hpp"
00031
00032 BEGIN_TERIMBER_NAMESPACE
00033 #pragma pack(4)
00034
00036
00037
00038 const sb8_t date::_70years = 25569;
00039
00040 const sb8_t date::_1899years = 693959;
00041
00042 const sb8_t date::_daymillisecond = 86400000;
00043
00044
00045 ub2_t date::_month_days[13] =
00046 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
00047
00048 date::date(bool utc)
00049 {
00050 timeb cur_time;
00051 ftime(&cur_time);
00052
00053
00054 if (utc)
00055 {
00056 cur_time.timezone = 0;
00057 cur_time.dstflag = 0;
00058 }
00059
00060
00061
00062 _ticks = (_1899years + _70years) * _daymillisecond +
00063 ((sb8_t)cur_time.dstflag * 60 * 60 + (sb8_t)cur_time.time - cur_time.timezone * 60) * 1000 +
00064 (sb8_t)cur_time.millitm;
00065 }
00066
00067 date::date(const char* x, size_t len) :
00068 _ticks(0)
00069 {
00070 if (!x)
00071 return;
00072
00073 len = (len == os_minus_one) ? str_template::strlen(x) : len;
00074 char buf[64] = {0};
00075 str_template::strcpy(buf, x, __min(len, sizeof(buf) - 1));
00076 set_date(buf);
00077 }
00078
00079 date::date(const wchar_t* x, size_t len) :
00080 _ticks(0)
00081 {
00082 if (!x)
00083 return;
00084
00085 len = (len == os_minus_one) ? str_template::strlen(x) : len;
00086 wchar_t buf[64] = {0};
00087 str_template::strcpy(buf, x, __min(len, sizeof(buf) - 1));
00088 set_date(buf);
00089 }
00090
00091 date::date(sb8_t x) :
00092 _ticks(x)
00093 {
00094 _ticks = x;
00095 }
00096
00097 date::date(const double* x) :
00098 _ticks(0)
00099 {
00100 if (x)
00101 set_double(*x);
00102 }
00103
00104 date::date(double x) :
00105 _ticks(0)
00106 {
00107 set_double(x);
00108 }
00109
00110 date::operator double() const
00111 {
00112 sb8_t date_part = _ticks / _daymillisecond;
00113 sb8_t time_part = _ticks % _daymillisecond;
00114
00115 return (double)(date_part - _1899years) + (double)(time_part) / _daymillisecond;
00116 }
00117
00118 void
00119 date::set_double(double x)
00120 {
00121 double date_part = floor(x);
00122 _ticks = ((sb8_t)date_part + _1899years) * _daymillisecond;
00123 _ticks += (sb8_t)((x - date_part) * _daymillisecond);
00124 }
00125
00126 date::operator sb8_t() const
00127 {
00128 return _ticks;
00129 }
00130
00131 bool
00132 date::operator<(const date& x) const
00133 {
00134 return _ticks < x._ticks;
00135 }
00136
00137 bool
00138 date::operator!=(const date& x) const
00139 {
00140 return _ticks != x._ticks;
00141 }
00142
00143 bool
00144 date::operator==(const date& x) const
00145 {
00146 return _ticks == x._ticks;
00147 }
00148
00149 bool
00150 date::operator<=(const date& x) const
00151 {
00152 return _ticks <= x._ticks;
00153 }
00154
00155 bool
00156 date::operator>(const date& x) const
00157 {
00158 return _ticks > x._ticks;
00159 }
00160
00161 bool
00162 date::operator>=(const date& x) const
00163 {
00164 return _ticks >= x._ticks;
00165 }
00166
00167 bool
00168 date::is_time_over(sb8_t x) const
00169 {
00170 return get_difference(_ticks) >= x;
00171 }
00172
00173
00174
00175 sb8_t
00176 date::get_difference(sb8_t old_date)
00177 {
00178 return (sb8_t)date() - old_date;
00179 }
00180
00181 date&
00182 date::operator+=(sb8_t interval)
00183 {
00184 _ticks += interval;
00185 return *this;
00186 }
00187
00188 date&
00189 date::operator-=(sb8_t interval)
00190 {
00191 _ticks -= interval;
00192 return *this;
00193 }
00194
00195
00196 bool
00197 date::convert_to( ub4_t year,
00198 ub1_t month,
00199 ub1_t day,
00200 ub1_t hour,
00201 ub1_t minute,
00202 ub1_t second,
00203 ub2_t millisec,
00204 sb8_t& dt)
00205 {
00206
00207 if (year > 1000000
00208 || month < 1 || month > 12
00209 || day < 1 || day > 31
00210 || hour > 23
00211 || minute > 59
00212 || second > 59
00213 || millisec > 999 )
00214 return false;
00215
00216
00217 bool leap_year = ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0);
00218
00219
00220 ub2_t days_in_month =
00221 _month_days[month] - _month_days[month - 1] +
00222 ((leap_year && day == 29 && month == 2) ? 1 : 0);
00223
00224
00225 if (day > days_in_month)
00226 return false;
00227
00228
00229 sb8_t date_part;
00230 sb8_t time_part;
00231
00232
00233
00234 date_part = year * 365 + year/4 - year/100 + year/400 +
00235 _month_days[month - 1] + day;
00236
00237
00238 if (month <= 2 && leap_year)
00239 --date_part;
00240
00241
00242 time_part = ((hour * 60 + minute) * 60 + second) * 1000 + millisec;
00243
00244
00245 dt = date_part * _daymillisecond + time_part;
00246 return true;
00247 }
00248
00249
00250 bool
00251 date::convert_from(sb8_t dt,
00252 ub4_t& year,
00253 ub1_t& month,
00254 ub1_t& day,
00255 ub1_t& hour,
00256 ub1_t& minute,
00257 ub1_t& second,
00258 ub2_t& millisec,
00259 ub1_t& wday,
00260 ub2_t& yday)
00261 {
00262 sb8_t date_part = dt / _daymillisecond;
00263 sb8_t time_part = dt % _daymillisecond;
00264
00265
00266
00267 wday = (ub1_t)((date_part - 1) % 7) + 1;
00268
00269
00270 sb8_t years400 = date_part / 146097;
00271
00272
00273 date_part %= 146097;
00274
00275
00276
00277 sb8_t years100 = (date_part - 1) / 36524;
00278
00279
00280 sb8_t years4 = date_part / 1461;
00281 sb8_t day4 = date_part % 1461;
00282 bool leap_year = true;
00283
00284
00285 if (years100 != 0)
00286 {
00287
00288 date_part = (date_part - 1) % 36524;
00289
00290
00291 years4 = (date_part + 1) / 1461;
00292
00293 if (years4 != 0)
00294 day4 = (date_part + 1) % 1461;
00295 else
00296 {
00297 leap_year = false;
00298 day4 = date_part;
00299 }
00300 }
00301
00302
00303 sb8_t yr;
00304
00305 if (leap_year)
00306 {
00307
00308 yr = (day4 - 1) / 365;
00309
00310 if (yr)
00311 day4 = (day4 - 1) % 365;
00312 }
00313 else
00314 {
00315 yr = day4 / 365;
00316 day4 %= 365;
00317 }
00318
00319
00320
00321 yday = (ub2_t)day4 + 1;
00322 year = (ub4_t)(years400 * 400 + years100 * 100 + years4 * 4 + yr);
00323
00324
00325 if (!yr && leap_year && day4 == 59)
00326 {
00327
00328 month = 2;
00329 day = 29;
00330 }
00331 else
00332 {
00333
00334
00335 if (yr || !leap_year || day4 < 60)
00336 ++day4;
00337
00338
00339 for (month = ((ub1_t)day4 >> 5) + 1; (ub2_t)day4 > _month_days[month] && month <= 12; ++month);
00340
00341 day = (ub1_t)(day4 - _month_days[month - 1]);
00342 }
00343
00344 if (!time_part)
00345 {
00346 hour = minute = second = 0;
00347 millisec = 0;
00348 }
00349 else
00350 {
00351 millisec = (ub2_t)(time_part % 1000);
00352 time_part /= 1000;
00353 second = (ub1_t)(time_part % 60);
00354 time_part /= 60;
00355 minute = (ub1_t)(time_part % 60);
00356 hour = (ub1_t)(time_part / 60);
00357 }
00358
00359 return true;
00360 }
00361
00363 const char*
00364 date::get_date(char* buffer) const
00365 {
00366 ub4_t year = 1900;
00367 ub1_t month = 1, day = 1, hour = 0, minute = 0, second = 0, wday = 0;
00368 ub2_t millisec = 0, yday = 0;
00369
00370 convert_from(_ticks, year, month, day, hour, minute, second, millisec, wday, yday);
00371 str_template::strprint(buffer, 64, "%d-%02d-%02d %02d:%02d:%02d.%03d",
00372 year, month, day, hour, minute, second, millisec);
00373
00374 return buffer;
00375 }
00376
00377 const wchar_t*
00378 date::get_date(wchar_t* buffer) const
00379 {
00380 ub4_t year = 1900;
00381 ub1_t month = 1, day = 1, hour = 0, minute = 0, second = 0, wday = 0;
00382 ub2_t millisec = 0, yday = 0;
00383
00384 wchar_t buf[64] = {0};
00385
00386 convert_from(_ticks, year, month, day, hour, minute, second, millisec, wday, yday);
00387 str_template::strprint(buffer, 64, str_template::strformat(buf, "%d-%02d-%02d %02d:%02d:%02d.%03d"),
00388 year, month, day, hour, minute, second, millisec);
00389
00390 return buffer;
00391 }
00392
00393
00394 const char*
00395 date::get_date_only(char* buffer, const char* format) const
00396 {
00397 ub4_t year = 1900;
00398 ub1_t month = 1, day = 1, hour = 0, minute = 0, second = 0, wday = 0;
00399 ub2_t millisec = 0, yday = 0;
00400
00401 convert_from(_ticks, year, month, day, hour, minute, second, millisec, wday, yday);
00402 str_template::strprint(buffer, 64, format ? format : "%d-%02d-%02d",
00403 year, month, day);
00404
00405 return buffer;
00406 }
00407
00408 const wchar_t*
00409 date::get_date_only(wchar_t* buffer, const wchar_t* format) const
00410 {
00411 ub4_t year = 1900;
00412 ub1_t month = 1, day = 1, hour = 0, minute = 0, second = 0, wday = 0;
00413 ub2_t millisec = 0, yday = 0;
00414
00415 wchar_t buf[64] = {0};
00416
00417 convert_from(_ticks, year, month, day, hour, minute, second, millisec, wday, yday);
00418 str_template::strprint(buffer, 64, format ? format : str_template::strformat(buf, "%d-%02d-%02d"),
00419 year, month, day);
00420
00421 return buffer;
00422 }
00423
00424
00425 bool
00426 date::scan_buffer(const char*& x, size_t count, size_t delimeter_size, sb4_t& dest)
00427 {
00428 if (str_template::strscan(x, count, "%d", &dest))
00429 {
00430 x += count + delimeter_size;
00431 return true;
00432 }
00433 else
00434 return false;
00435 }
00436
00437
00438 bool
00439 date::scan_buffer(const wchar_t*& x, size_t count, size_t delimeter_size, sb4_t& dest)
00440 {
00441 if (str_template::strscan(x, count, L"%d", &dest))
00442 {
00443 x += count + delimeter_size;
00444 return true;
00445 }
00446 else
00447 return false;
00448 }
00449
00450 void
00451 date::set_date(const char* x)
00452 {
00453 const char* ptr = x;
00454 sb4_t year = 1900, month = 1, day = 1, hour = 0, minute = 0, second = 0, millisec = 0;
00455
00456 if (x && x[0])
00457 {
00458
00459 if (scan_buffer(ptr, 4, 1, year)
00460 && scan_buffer(ptr, 2, 1, month)
00461 && scan_buffer(ptr, 2, 1, day)
00462 && scan_buffer(ptr, 2, 1, hour)
00463 && scan_buffer(ptr, 2, 1, minute)
00464 && scan_buffer(ptr, 2, 1, second)
00465 && scan_buffer(ptr, 3, 1, millisec))
00466 {
00467 ;
00468 }
00469 convert_to(year, month, day, hour, minute, second, millisec, _ticks);
00470 }
00471 else
00472 _ticks = 0;
00473 }
00474
00475 void
00476 date::set_date(const wchar_t* x)
00477 {
00478 const wchar_t* ptr = x;
00479 sb4_t year = 1900, month = 1, day = 1, hour = 0, minute = 0, second = 0, millisec = 0;
00480
00481 if (x && x[0])
00482 {
00483
00484 if (scan_buffer(ptr, 4, 1, year)
00485 && scan_buffer(ptr, 2, 1, month)
00486 && scan_buffer(ptr, 2, 1, day)
00487 && scan_buffer(ptr, 2, 1, hour)
00488 && scan_buffer(ptr, 2, 1, minute)
00489 && scan_buffer(ptr, 2, 1, second)
00490 && scan_buffer(ptr, 3, 1, millisec))
00491 {
00492 ;
00493 }
00494 convert_to(year, month, day, hour, minute, second, millisec, _ticks);
00495 }
00496 else
00497 _ticks = 0;
00498 }
00499
00500 #pragma pack()
00501 END_TERIMBER_NAMESPACE
00502