00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #if TIME_WITH_SYS_TIME
00028 # include <sys/time.h>
00029 # include <time.h>
00030 #else
00031 #if HAVE_SYS_TIME_H
00032 #include <sys/time.h>
00033 #else
00034 # include <time.h>
00035 # endif
00036 #endif
00037 #ifdef HAVE_SYS_TIMEB_H
00038 #include <sys/timeb.h>
00039 #endif
00040
00041 #ifdef HAVE_SYS_PARAM_H
00042 # include <sys/param.h>
00043 #endif // HAVE_SYS_PARAM_H
00044
00045 #include <math.h>
00046 #include <string.h>
00047 #ifdef HAVE_STRINGS_H
00048 # include <strings.h>
00049 #endif
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052 #include <locale.h>
00053 #include <ctype.h>
00054 #include <assert.h>
00055
00056 #include "date_object.h"
00057 #include "error_object.h"
00058 #include "operations.h"
00059
00060 #include "date_object.lut.h"
00061
00062 using namespace KJS;
00063
00064
00065 const time_t invalidDate = -1;
00066 const double hoursPerDay = 24;
00067 const double minutesPerHour = 60;
00068 const double secondsPerMinute = 60;
00069 const double msPerSecond = 1000;
00070 const double msPerMinute = msPerSecond * secondsPerMinute;
00071 const double msPerHour = msPerMinute * minutesPerHour;
00072 const double msPerDay = msPerHour * hoursPerDay;
00073
00074 static int day(double t)
00075 {
00076 return int(floor(t / msPerDay));
00077 }
00078
00079 static double dayFromYear(int year)
00080 {
00081 return 365.0 * (year - 1970)
00082 + floor((year - 1969) / 4.0)
00083 - floor((year - 1901) / 100.0)
00084 + floor((year - 1601) / 400.0);
00085 }
00086
00087
00088 static int daysInYear(int year)
00089 {
00090 if (year % 4 != 0)
00091 return 365;
00092 else if (year % 400 == 0)
00093 return 366;
00094 else if (year % 100 == 0)
00095 return 365;
00096 else
00097 return 366;
00098 }
00099
00100
00101 double timeFromYear(int year)
00102 {
00103 return msPerDay * dayFromYear(year);
00104 }
00105
00106
00107 int yearFromTime(double t)
00108 {
00109
00110
00111 int y = 1970 + int(t / (365.25 * msPerDay));
00112
00113 if (timeFromYear(y) > t) {
00114 do {
00115 --y;
00116 } while (timeFromYear(y) > t);
00117 } else {
00118 while (timeFromYear(y + 1) < t)
00119 ++y;
00120 }
00121
00122 return y;
00123 }
00124
00125
00126 int weekDay(double t)
00127 {
00128 int wd = (day(t) + 4) % 7;
00129 if (wd < 0)
00130 wd += 7;
00131 return wd;
00132 }
00133
00134 static double timeZoneOffset(const struct tm *t)
00135 {
00136 #if defined BSD || defined(__linux__) || defined(__APPLE__)
00137 return -(t->tm_gmtoff / 60);
00138 #else
00139 # if defined(__BORLANDC__)
00140
00141 #error please add daylight savings offset here!
00142 return _timezone / 60 - (t->tm_isdst > 0 ? 60 : 0);
00143 # else
00144 return timezone / 60 - (t->tm_isdst > 0 ? 60 : 0 );
00145 # endif
00146 #endif
00147 }
00148
00149
00150
00151 const ClassInfo DateInstanceImp::info = {"Date", 0, 0, 0};
00152
00153 DateInstanceImp::DateInstanceImp(ObjectImp *proto)
00154 : ObjectImp(proto)
00155 {
00156 }
00157
00158
00159
00160 const ClassInfo DatePrototypeImp::info = {"Date", 0, &dateTable, 0};
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 DatePrototypeImp::DatePrototypeImp(ExecState *,
00215 ObjectPrototypeImp *objectProto)
00216 : DateInstanceImp(objectProto)
00217 {
00218 Value protect(this);
00219 setInternalValue(Number(NaN));
00220
00221 }
00222
00223 Value DatePrototypeImp::get(ExecState *exec, const Identifier &propertyName) const
00224 {
00225 return lookupGetFunction<DateProtoFuncImp, ObjectImp>( exec, propertyName, &dateTable, this );
00226 }
00227
00228
00229
00230 DateProtoFuncImp::DateProtoFuncImp(ExecState *exec, int i, int len)
00231 : InternalFunctionImp(
00232 static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
00233 ), id(abs(i)), utc(i<0)
00234
00235 {
00236 Value protect(this);
00237 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
00238 }
00239
00240 bool DateProtoFuncImp::implementsCall() const
00241 {
00242 return true;
00243 }
00244
00245 Value DateProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
00246 {
00247 if ((id == ToString || id == ValueOf || id == GetTime || id == SetTime) &&
00248 !thisObj.inherits(&DateInstanceImp::info)) {
00249
00250
00251
00252
00253 Object err = Error::create(exec,TypeError);
00254 exec->setException(err);
00255 return err;
00256 }
00257
00258
00259 Value result;
00260 UString s;
00261 const int bufsize=100;
00262 char timebuffer[bufsize];
00263 CString oldlocale = setlocale(LC_TIME,NULL);
00264 if (!oldlocale.c_str())
00265 oldlocale = setlocale(LC_ALL, NULL);
00266 Value v = thisObj.internalValue();
00267 double milli = v.toNumber(exec);
00268
00269 if (isNaN(milli)) {
00270 switch (id) {
00271 case ToString:
00272 case ToDateString:
00273 case ToTimeString:
00274 case ToGMTString:
00275 case ToUTCString:
00276 case ToLocaleString:
00277 case ToLocaleDateString:
00278 case ToLocaleTimeString:
00279 return String("Invalid Date");
00280 case ValueOf:
00281 case GetTime:
00282 case GetYear:
00283 case GetFullYear:
00284 case GetMonth:
00285 case GetDate:
00286 case GetDay:
00287 case GetHours:
00288 case GetMinutes:
00289 case GetSeconds:
00290 case GetMilliSeconds:
00291 case GetTimezoneOffset:
00292 return Number(NaN);
00293 }
00294 }
00295
00296
00297
00298 int realYearOffset = 0;
00299 double milliOffset = 0.0;
00300 if (milli < 0 || milli >= timeFromYear(2038)) {
00301
00302 int realYear = yearFromTime(milli);
00303 int base = daysInYear(realYear) == 365 ? 2001 : 2000;
00304 milliOffset = timeFromYear(base) - timeFromYear(realYear);
00305 milli += milliOffset;
00306 realYearOffset = realYear - base;
00307 }
00308
00309 time_t tv = (time_t) floor(milli / 1000.0);
00310 int ms = int(milli - tv * 1000.0);
00311
00312 struct tm *t;
00313 if ( (id == DateProtoFuncImp::ToGMTString) ||
00314 (id == DateProtoFuncImp::ToUTCString) )
00315 t = gmtime(&tv);
00316 else if (id == DateProtoFuncImp::ToString)
00317 t = localtime(&tv);
00318 else if (utc)
00319 t = gmtime(&tv);
00320 else
00321 t = localtime(&tv);
00322
00323
00324
00325 if (realYearOffset != 0) {
00326 t->tm_year += realYearOffset;
00327 milli -= milliOffset;
00328
00329 double m = milli;
00330 if (!utc)
00331 m -= timeZoneOffset(t) * msPerMinute;
00332 t->tm_wday = weekDay(m);
00333 }
00334
00335
00336 const char xFormat[] = "%x";
00337 const char cFormat[] = "%c";
00338
00339 switch (id) {
00340 case ToString:
00341 case ToDateString:
00342 case ToTimeString:
00343 case ToGMTString:
00344 case ToUTCString:
00345 setlocale(LC_TIME,"C");
00346 if (id == DateProtoFuncImp::ToDateString) {
00347 strftime(timebuffer, bufsize, xFormat, t);
00348 } else if (id == DateProtoFuncImp::ToTimeString) {
00349 strftime(timebuffer, bufsize, "%X",t);
00350 } else {
00351 strftime(timebuffer, bufsize, "%a, %d %b %Y %H:%M:%S %z", t);
00352 }
00353 setlocale(LC_TIME,oldlocale.c_str());
00354 result = String(timebuffer);
00355 break;
00356 case ToLocaleString:
00357 strftime(timebuffer, bufsize, cFormat, t);
00358 result = String(timebuffer);
00359 break;
00360 case ToLocaleDateString:
00361 strftime(timebuffer, bufsize, xFormat, t);
00362 result = String(timebuffer);
00363 break;
00364 case ToLocaleTimeString:
00365 strftime(timebuffer, bufsize, "%X", t);
00366 result = String(timebuffer);
00367 break;
00368 case ValueOf:
00369 result = Number(milli);
00370 break;
00371 case GetTime:
00372 result = Number(milli);
00373 break;
00374 case GetYear:
00375
00376 if ( exec->interpreter()->compatMode() != Interpreter::IECompat )
00377 result = Number(t->tm_year);
00378 else
00379 result = Number(1900 + t->tm_year);
00380 break;
00381 case GetFullYear:
00382 result = Number(1900 + t->tm_year);
00383 break;
00384 case GetMonth:
00385 result = Number(t->tm_mon);
00386 break;
00387 case GetDate:
00388 result = Number(t->tm_mday);
00389 break;
00390 case GetDay:
00391 result = Number(t->tm_wday);
00392 break;
00393 case GetHours:
00394 result = Number(t->tm_hour);
00395 break;
00396 case GetMinutes:
00397 result = Number(t->tm_min);
00398 break;
00399 case GetSeconds:
00400 result = Number(t->tm_sec);
00401 break;
00402 case GetMilliSeconds:
00403 result = Number(ms);
00404 break;
00405 case GetTimezoneOffset:
00406 result = Number(timeZoneOffset(t));
00407 break;
00408 case SetTime:
00409 milli = roundValue(exec,args[0]);
00410 result = Number(milli);
00411 thisObj.setInternalValue(result);
00412 break;
00413 case SetMilliSeconds:
00414 ms = args[0].toInt32(exec);
00415 break;
00416 case SetSeconds:
00417 t->tm_sec = args[0].toInt32(exec);
00418 if (args.size() >= 2)
00419 ms = args[1].toInt32(exec);
00420 break;
00421 case SetMinutes:
00422 t->tm_min = args[0].toInt32(exec);
00423 if (args.size() >= 2)
00424 t->tm_sec = args[1].toInt32(exec);
00425 if (args.size() >= 3)
00426 ms = args[2].toInt32(exec);
00427 break;
00428 case SetHours:
00429 t->tm_hour = args[0].toInt32(exec);
00430 if (args.size() >= 2)
00431 t->tm_min = args[1].toInt32(exec);
00432 if (args.size() >= 3)
00433 t->tm_sec = args[2].toInt32(exec);
00434 if (args.size() >= 4)
00435 ms = args[3].toInt32(exec);
00436 break;
00437 case SetDate:
00438 t->tm_mday = args[0].toInt32(exec);
00439 break;
00440 case SetMonth:
00441 t->tm_mon = args[0].toInt32(exec);
00442 if (args.size() >= 2)
00443 t->tm_mday = args[1].toInt32(exec);
00444 break;
00445 case SetFullYear:
00446 t->tm_year = args[0].toInt32(exec) - 1900;
00447 if (args.size() >= 2)
00448 t->tm_mon = args[1].toInt32(exec);
00449 if (args.size() >= 3)
00450 t->tm_mday = args[2].toInt32(exec);
00451 break;
00452 case SetYear: {
00453 int a0 = args[0].toInt32(exec);
00454 if (a0 >= 0 && a0 <= 99)
00455 a0 += 1900;
00456 t->tm_year = a0 - 1900;
00457 break;
00458 }
00459 }
00460
00461 if (id == SetYear || id == SetMilliSeconds || id == SetSeconds ||
00462 id == SetMinutes || id == SetHours || id == SetDate ||
00463 id == SetMonth || id == SetFullYear ) {
00464 result = Number(makeTime(t, ms, utc));
00465 thisObj.setInternalValue(result);
00466 }
00467
00468 return result;
00469 }
00470
00471
00472
00473
00474
00475 DateObjectImp::DateObjectImp(ExecState *exec,
00476 FunctionPrototypeImp *funcProto,
00477 DatePrototypeImp *dateProto)
00478 : InternalFunctionImp(funcProto)
00479 {
00480 Value protect(this);
00481
00482
00483 putDirect(prototypePropertyName, dateProto, DontEnum|DontDelete|ReadOnly);
00484
00485 static const Identifier parsePropertyName("parse");
00486 putDirect(parsePropertyName, new DateObjectFuncImp(exec,funcProto,DateObjectFuncImp::Parse, 1), DontEnum);
00487 static const Identifier UTCPropertyName("UTC");
00488 putDirect(UTCPropertyName, new DateObjectFuncImp(exec,funcProto,DateObjectFuncImp::UTC, 7), DontEnum);
00489
00490
00491 putDirect(lengthPropertyName, 7, ReadOnly|DontDelete|DontEnum);
00492 }
00493
00494 bool DateObjectImp::implementsConstruct() const
00495 {
00496 return true;
00497 }
00498
00499
00500 Object DateObjectImp::construct(ExecState *exec, const List &args)
00501 {
00502 int numArgs = args.size();
00503
00504 #ifdef KJS_VERBOSE
00505 fprintf(stderr,"DateObjectImp::construct - %d args\n", numArgs);
00506 #endif
00507 double value;
00508
00509 if (numArgs == 0) {
00510 #ifdef HAVE_SYS_TIMEB_H
00511 # if defined(__BORLANDC__)
00512 struct timeb timebuffer;
00513 ftime(&timebuffer);
00514 # else
00515 struct _timeb timebuffer;
00516 _ftime(&timebuffer);
00517 # endif
00518 double utc = floor((double)timebuffer.time * 1000.0 + (double)timebuffer.millitm);
00519 #else
00520 struct timeval tv;
00521 gettimeofday(&tv, 0L);
00522 double utc = floor((double)tv.tv_sec * 1000.0 + (double)tv.tv_usec / 1000.0);
00523 #endif
00524 value = utc;
00525 } else if (numArgs == 1) {
00526 Value prim = args[0].toPrimitive(exec);
00527 if (prim.isA(StringType))
00528 value = parseDate(prim.toString(exec));
00529 else
00530 value = prim.toNumber(exec);
00531 } else {
00532 struct tm t;
00533 memset(&t, 0, sizeof(t));
00534 int year = args[0].toInt32(exec);
00535
00536 t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
00537 t.tm_mon = args[1].toInt32(exec);
00538 t.tm_mday = (numArgs >= 3) ? args[2].toInt32(exec) : 1;
00539 t.tm_hour = (numArgs >= 4) ? args[3].toInt32(exec) : 0;
00540 t.tm_min = (numArgs >= 5) ? args[4].toInt32(exec) : 0;
00541 t.tm_sec = (numArgs >= 6) ? args[5].toInt32(exec) : 0;
00542 t.tm_isdst = -1;
00543 int ms = (numArgs >= 7) ? args[6].toInt32(exec) : 0;
00544 value = makeTime(&t, ms, false);
00545 }
00546
00547 Object proto = exec->interpreter()->builtinDatePrototype();
00548 Object ret(new DateInstanceImp(proto.imp()));
00549 ret.setInternalValue(Number(timeClip(value)));
00550 return ret;
00551 }
00552
00553 bool DateObjectImp::implementsCall() const
00554 {
00555 return true;
00556 }
00557
00558
00559 Value DateObjectImp::call(ExecState* , Object &, const List &)
00560 {
00561 #ifdef KJS_VERBOSE
00562 fprintf(stderr,"DateObjectImp::call - current time\n");
00563 #endif
00564 time_t t = time(0L);
00565 UString s(ctime(&t));
00566
00567
00568 return String(s.substr(0, s.size() - 1));
00569 }
00570
00571
00572
00573 DateObjectFuncImp::DateObjectFuncImp(ExecState* , FunctionPrototypeImp *funcProto,
00574 int i, int len)
00575 : InternalFunctionImp(funcProto), id(i)
00576 {
00577 Value protect(this);
00578 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
00579 }
00580
00581 bool DateObjectFuncImp::implementsCall() const
00582 {
00583 return true;
00584 }
00585
00586
00587 Value DateObjectFuncImp::call(ExecState *exec, Object &, const List &args)
00588 {
00589 if (id == Parse) {
00590 return Number(parseDate(args[0].toString(exec)));
00591 } else {
00592 struct tm t;
00593 memset(&t, 0, sizeof(t));
00594 int n = args.size();
00595 int year = args[0].toInt32(exec);
00596
00597 t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
00598 t.tm_mon = args[1].toInt32(exec);
00599 t.tm_mday = (n >= 3) ? args[2].toInt32(exec) : 1;
00600 t.tm_hour = (n >= 4) ? args[3].toInt32(exec) : 0;
00601 t.tm_min = (n >= 5) ? args[4].toInt32(exec) : 0;
00602 t.tm_sec = (n >= 6) ? args[5].toInt32(exec) : 0;
00603 int ms = (n >= 7) ? args[6].toInt32(exec) : 0;
00604 return Number(makeTime(&t, ms, true));
00605 }
00606 }
00607
00608
00609
00610
00611 double KJS::parseDate(const UString &u)
00612 {
00613 #ifdef KJS_VERBOSE
00614 fprintf(stderr,"KJS::parseDate %s\n",u.ascii());
00615 #endif
00616 double seconds = KRFCDate_parseDate( u );
00617
00618 return seconds == -1 ? NaN : seconds * 1000.0;
00619 }
00620
00622
00623 static double ymdhms_to_seconds(int year, int mon, int day, int hour, int minute, int second)
00624 {
00625
00626
00627 double ret = (day - 32075)
00628 + 1461L * (year + 4800L + (mon - 14) / 12) / 4
00629 + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
00630 - 3 * ((year + 4900L + (mon - 14) / 12) / 100) / 4
00631 - 2440588;
00632 ret = 24*ret + hour;
00633 ret = 60*ret + minute;
00634 ret = 60*ret + second;
00635
00636 return ret;
00637 }
00638
00639
00640
00641 static const struct {
00642 #ifdef _WIN32
00643 char tzName[4];
00644 #else
00645 const char tzName[4];
00646 #endif
00647 int tzOffset;
00648 } known_zones[] = {
00649 { "UT", 0 },
00650 { "GMT", 0 },
00651 { "EST", -300 },
00652 { "EDT", -240 },
00653 { "CST", -360 },
00654 { "CDT", -300 },
00655 { "MST", -420 },
00656 { "MDT", -360 },
00657 { "PST", -480 },
00658 { "PDT", -420 },
00659 { { 0, 0, 0, 0 }, 0 }
00660 };
00661
00662 double KJS::makeTime(struct tm *t, int ms, bool utc)
00663 {
00664 int utcOffset;
00665 if (utc) {
00666 time_t zero = 0;
00667 #if defined BSD || defined(__linux__) || defined(__APPLE__)
00668 struct tm t3;
00669 localtime_r(&zero, &t3);
00670 utcOffset = t3.tm_gmtoff;
00671 t->tm_isdst = t3.tm_isdst;
00672 #else
00673 (void)localtime(&zero);
00674 # if defined(__BORLANDC__)
00675 utcOffset = - _timezone;
00676 # else
00677 utcOffset = - timezone;
00678 # endif
00679 t->tm_isdst = 0;
00680 #endif
00681 } else {
00682 utcOffset = 0;
00683 t->tm_isdst = -1;
00684 }
00685
00686 double yearOffset = 0.0;
00687 if (t->tm_year < (1970 - 1900) || t->tm_year > (2038 - 1900)) {
00688
00689
00690
00691
00692
00693 int y = t->tm_year + 1900;
00694 int baseYear = daysInYear(y) == 365 ? 2001 : 2000;
00695 const double baseTime = timeFromYear(baseYear);
00696 yearOffset = timeFromYear(y) - baseTime;
00697 t->tm_year = baseYear - 1900;
00698 }
00699
00700 return (mktime(t) + utcOffset) * 1000.0 + ms + yearOffset;
00701 }
00702
00703
00704 static int findMonth(const char *monthStr)
00705 {
00706 assert(monthStr);
00707 static const char haystack[37] = "janfebmaraprmayjunjulaugsepoctnovdec";
00708 char needle[4];
00709 for (int i = 0; i < 3; ++i) {
00710 if (!*monthStr)
00711 return -1;
00712 needle[i] = tolower(*monthStr++);
00713 }
00714 needle[3] = '\0';
00715 const char *str = strstr(haystack, needle);
00716 if (str) {
00717 int position = str - haystack;
00718 if (position % 3 == 0) {
00719 return position / 3;
00720 }
00721 }
00722 return -1;
00723 }
00724
00725 double KJS::KRFCDate_parseDate(const UString &_date)
00726 {
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 double result = -1;
00742 int offset = 0;
00743 bool have_tz = false;
00744 char *newPosStr;
00745 const char *dateString = _date.ascii();
00746 int day = 0;
00747 int month = -1;
00748 int year = 0;
00749 int hour = 0;
00750 int minute = 0;
00751 int second = 0;
00752 bool have_time = false;
00753
00754
00755 while(*dateString && isspace(*dateString))
00756 dateString++;
00757
00758 const char *wordStart = dateString;
00759
00760 while(*dateString && !isdigit(*dateString))
00761 {
00762 if ( isspace(*dateString) && dateString - wordStart >= 3 )
00763 {
00764 month = findMonth(wordStart);
00765 while(*dateString && isspace(*dateString))
00766 dateString++;
00767 wordStart = dateString;
00768 }
00769 else
00770 dateString++;
00771 }
00772
00773 if (month == -1 && dateString && wordStart != dateString) {
00774 month = findMonth(wordStart);
00775
00776 }
00777
00778 while(*dateString && isspace(*dateString))
00779 dateString++;
00780
00781 if (!*dateString)
00782 return invalidDate;
00783
00784
00785 day = strtol(dateString, &newPosStr, 10);
00786 dateString = newPosStr;
00787
00788 if (!*dateString)
00789 return invalidDate;
00790
00791 if (day < 1)
00792 return invalidDate;
00793 if (day > 31) {
00794
00795 if (*dateString == '/' && day >= 1000) {
00796
00797 if (!*++dateString)
00798 return invalidDate;
00799 year = day;
00800 month = strtol(dateString, &newPosStr, 10) - 1;
00801 dateString = newPosStr;
00802 if (*dateString++ != '/' || !*dateString)
00803 return invalidDate;
00804 day = strtol(dateString, &newPosStr, 10);
00805 dateString = newPosStr;
00806 } else {
00807 return invalidDate;
00808 }
00809 } else if (*dateString == '/' && day <= 12 && month == -1)
00810 {
00811 dateString++;
00812
00813 month = day - 1;
00814 day = strtol(dateString, &newPosStr, 10);
00815 dateString = newPosStr;
00816 if (*dateString == '/')
00817 dateString++;
00818 if (!*dateString)
00819 return invalidDate;
00820
00821 }
00822 else
00823 {
00824 if (*dateString == '-')
00825 dateString++;
00826
00827 while(*dateString && isspace(*dateString))
00828 dateString++;
00829
00830 if (*dateString == ',')
00831 dateString++;
00832
00833 if ( month == -1 )
00834 {
00835 month = findMonth(dateString);
00836 if (month == -1)
00837 return invalidDate;
00838
00839 while(*dateString && (*dateString != '-') && !isspace(*dateString))
00840 dateString++;
00841
00842 if (!*dateString)
00843 return invalidDate;
00844
00845
00846 if ((*dateString != '-') && (*dateString != '/') && !isspace(*dateString))
00847 return invalidDate;
00848 dateString++;
00849 }
00850
00851 if ((month < 0) || (month > 11))
00852 return invalidDate;
00853 }
00854
00855
00856 if (year <= 0 && *dateString)
00857 year = strtol(dateString, &newPosStr, 10);
00858
00859
00860 if (*newPosStr)
00861 {
00862
00863 if (!isspace(*newPosStr)) {
00864 if ( *newPosStr == ':' )
00865 year = -1;
00866 else
00867 return invalidDate;
00868 } else
00869 dateString = ++newPosStr;
00870
00871 hour = strtol(dateString, &newPosStr, 10);
00872
00873 if (newPosStr != dateString) {
00874 have_time = true;
00875 dateString = newPosStr;
00876
00877 if ((hour < 0) || (hour > 23))
00878 return invalidDate;
00879
00880 if (!*dateString)
00881 return invalidDate;
00882
00883
00884 if (*dateString++ != ':')
00885 return invalidDate;
00886
00887 minute = strtol(dateString, &newPosStr, 10);
00888 dateString = newPosStr;
00889
00890 if ((minute < 0) || (minute > 59))
00891 return invalidDate;
00892
00893
00894 if (*dateString && *dateString != ':' && !isspace(*dateString))
00895 return invalidDate;
00896
00897
00898 if (*dateString ==':') {
00899 dateString++;
00900
00901 second = strtol(dateString, &newPosStr, 10);
00902 dateString = newPosStr;
00903
00904 if ((second < 0) || (second > 59))
00905 return invalidDate;
00906 }
00907
00908 while(*dateString && isspace(*dateString))
00909 dateString++;
00910 }
00911 } else {
00912 dateString = newPosStr;
00913 }
00914
00915
00916
00917 if (*dateString) {
00918
00919 if ( (dateString[0] == 'G' && dateString[1] == 'M' && dateString[2] == 'T')
00920 || (dateString[0] == 'U' && dateString[1] == 'T' && dateString[2] == 'C') )
00921 {
00922 dateString += 3;
00923 have_tz = true;
00924 }
00925
00926 while (*dateString && isspace(*dateString))
00927 ++dateString;
00928
00929 if (strncasecmp(dateString, "GMT", 3) == 0) {
00930 dateString += 3;
00931 }
00932 if ((*dateString == '+') || (*dateString == '-')) {
00933 offset = strtol(dateString, &newPosStr, 10);
00934 dateString = newPosStr;
00935
00936 if ((offset < -9959) || (offset > 9959))
00937 return invalidDate;
00938
00939 int sgn = (offset < 0)? -1:1;
00940 offset = abs(offset);
00941 if ( *dateString == ':' ) {
00942 int offset2 = strtol(dateString, &newPosStr, 10);
00943 dateString = newPosStr;
00944 offset = (offset*60 + offset2)*sgn;
00945 }
00946 else
00947 offset = ((offset / 100)*60 + (offset % 100))*sgn;
00948 have_tz = true;
00949 } else {
00950 for (int i=0; known_zones[i].tzName != 0; i++) {
00951 if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
00952 offset = known_zones[i].tzOffset;
00953 have_tz = true;
00954 break;
00955 }
00956 }
00957 }
00958 }
00959
00960 while(*dateString && isspace(*dateString))
00961 dateString++;
00962
00963 if ( *dateString && year == -1 ) {
00964 year = strtol(dateString, &newPosStr, 10);
00965 }
00966
00967
00968 if ((year >= 0) && (year < 50))
00969 year += 2000;
00970
00971 if ((year >= 50) && (year < 100))
00972 year += 1900;
00973
00974 if ((year < 1900) || (year > 2500))
00975 return invalidDate;
00976
00977 if (!have_tz) {
00978
00979 struct tm t;
00980 memset(&t, 0, sizeof(tm));
00981 t.tm_mday = day;
00982 t.tm_mon = month;
00983 t.tm_year = year - 1900;
00984 t.tm_isdst = -1;
00985 if (have_time) {
00986 t.tm_sec = second;
00987 t.tm_min = minute;
00988 t.tm_hour = hour;
00989 }
00990
00991
00992 return makeTime(&t, 0, false) / 1000.0;
00993 }
00994
00995 offset *= 60;
00996
00997 result = ymdhms_to_seconds(year, month+1, day, hour, minute, second);
00998
00999
01000 if ((offset > 0) && (offset > result))
01001 offset = 0;
01002
01003 result -= offset;
01004
01005
01006
01007
01008 if (result < 1) result = 1;
01009
01010 return result;
01011 }
01012
01013
01014 double KJS::timeClip(double t)
01015 {
01016 if (isInf(t) || fabs(t) > 8.64E15)
01017 return NaN;
01018 return t;
01019 }
01020