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
#ifdef KJS_VERBOSE
00618
fprintf(stderr,
"KRFCDate_parseDate returned seconds=%g\n",seconds);
00619
bool withinLimits =
true;
00620
if (
sizeof(time_t) == 4 )
00621 {
00622
int limit = ((time_t)-1 < 0) ? 2038 : 2115;
00623
if ( seconds > (limit-1970) * 365.25 * 86400 ) {
00624 fprintf(stderr,
"date above time_t limit. Year seems to be %d\n", (
int)(seconds/(365.25*86400)+1970));
00625 withinLimits =
false;
00626 }
00627 }
00628
if ( withinLimits ) {
00629 time_t lsec = (time_t)seconds;
00630 fprintf(stderr,
"this is: %s\n", ctime(&lsec));
00631 }
00632
#endif
00633
00634
return seconds == -1 ? NaN : seconds * 1000.0;
00635 }
00636
00638
00639
static double ymdhms_to_seconds(
int year,
int mon,
int day,
int hour,
int minute,
int second)
00640 {
00641
00642
00643
double ret = (day - 32075)
00644 + 1461L * (year + 4800L + (mon - 14) / 12) / 4
00645 + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
00646 - 3 * ((year + 4900L + (mon - 14) / 12) / 100) / 4
00647 - 2440588;
00648 ret = 24*ret + hour;
00649 ret = 60*ret + minute;
00650 ret = 60*ret + second;
00651
00652
return ret;
00653 }
00654
00655
static const char haystack[37]=
"janfebmaraprmayjunjulaugsepoctnovdec";
00656
00657
00658
00659
static const struct {
00660
#ifdef _WIN32
00661
char tzName[4];
00662
#else
00663
const char tzName[4];
00664
#endif
00665
int tzOffset;
00666 } known_zones[] = {
00667 {
"UT", 0 },
00668 {
"GMT", 0 },
00669 {
"EST", -300 },
00670 {
"EDT", -240 },
00671 {
"CST", -360 },
00672 {
"CDT", -300 },
00673 {
"MST", -420 },
00674 {
"MDT", -360 },
00675 {
"PST", -480 },
00676 {
"PDT", -420 },
00677 { { 0, 0, 0, 0 }, 0 }
00678 };
00679
00680
double KJS::makeTime(
struct tm *t,
int ms,
bool utc)
00681 {
00682
int utcOffset;
00683
if (utc) {
00684 time_t zero = 0;
00685
#if defined BSD || defined(__linux__) || defined(__APPLE__)
00686
struct tm t3;
00687 localtime_r(&zero, &t3);
00688 utcOffset = t3.tm_gmtoff;
00689 t->tm_isdst = t3.tm_isdst;
00690
#else
00691
(
void)localtime(&zero);
00692
# if defined(__BORLANDC__)
00693
utcOffset = - _timezone;
00694
# else
00695
utcOffset = - timezone;
00696
# endif
00697
t->tm_isdst = 0;
00698
#endif
00699
}
else {
00700 utcOffset = 0;
00701 t->tm_isdst = -1;
00702 }
00703
00704
double yearOffset = 0.0;
00705
if (t->tm_year < (1970 - 1900) || t->tm_year > (2038 - 1900)) {
00706
00707
00708
00709
00710
00711
int y = t->tm_year + 1900;
00712
int baseYear = daysInYear(y) == 365 ? 2001 : 2000;
00713
const double baseTime = timeFromYear(baseYear);
00714 yearOffset = timeFromYear(y) - baseTime;
00715 t->tm_year = baseYear - 1900;
00716 }
00717
00718
return (mktime(t) + utcOffset) * 1000.0 + ms + yearOffset;
00719 }
00720
00721
double KJS::KRFCDate_parseDate(
const UString &_date)
00722 {
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
double result = -1;
00738
int offset = 0;
00739
bool have_tz =
false;
00740
char *newPosStr;
00741
const char *dateString = _date.
ascii();
00742
int day = 0;
00743
char monthStr[4];
00744
int month = -1;
00745
int year = 0;
00746
int hour = 0;
00747
int minute = 0;
00748
int second = 0;
00749
bool have_time =
false;
00750
00751
00752
while(*dateString && isspace(*dateString))
00753 dateString++;
00754
00755
const char *wordStart = dateString;
00756
00757
while(*dateString && !isdigit(*dateString))
00758 {
00759
if ( isspace(*dateString) && dateString - wordStart >= 3 )
00760 {
00761 monthStr[0] = tolower(*wordStart++);
00762 monthStr[1] = tolower(*wordStart++);
00763 monthStr[2] = tolower(*wordStart++);
00764 monthStr[3] =
'\0';
00765
00766
const char *str = strstr(haystack, monthStr);
00767
if (str) {
00768
int position = str - haystack;
00769
if (position % 3 == 0) {
00770 month = position / 3;
00771 }
00772 }
00773
while(*dateString && isspace(*dateString))
00774 dateString++;
00775 wordStart = dateString;
00776 }
00777
else
00778 dateString++;
00779 }
00780
00781
while(*dateString && isspace(*dateString))
00782 dateString++;
00783
00784
if (!*dateString)
00785
return invalidDate;
00786
00787
00788 day = strtol(dateString, &newPosStr, 10);
00789 dateString = newPosStr;
00790
00791
if (!*dateString)
00792
return invalidDate;
00793
00794
if (day < 1)
00795
return invalidDate;
00796
if (day > 31) {
00797
00798
if (*dateString ==
'/' && day >= 1000) {
00799
00800
if (!*++dateString)
00801
return invalidDate;
00802 year = day;
00803 month = strtol(dateString, &newPosStr, 10) - 1;
00804 dateString = newPosStr;
00805
if (*dateString++ !=
'/' || !*dateString)
00806
return invalidDate;
00807 day = strtol(dateString, &newPosStr, 10);
00808 dateString = newPosStr;
00809 }
else {
00810
return invalidDate;
00811 }
00812 }
else if (*dateString ==
'/' && day <= 12 && month == -1)
00813 {
00814 dateString++;
00815
00816 month = day - 1;
00817 day = strtol(dateString, &newPosStr, 10);
00818 dateString = newPosStr;
00819
if (*dateString ==
'/')
00820 dateString++;
00821
if (!*dateString)
00822
return invalidDate;
00823
00824 }
00825
else
00826 {
00827
if (*dateString ==
'-')
00828 dateString++;
00829
00830
while(*dateString && isspace(*dateString))
00831 dateString++;
00832
00833
if (*dateString ==
',')
00834 dateString++;
00835
00836
if ( month == -1 )
00837 {
00838
for(
int i=0; i < 3;i++)
00839 {
00840
if (!*dateString || (*dateString ==
'-') || isspace(*dateString))
00841
return invalidDate;
00842 monthStr[i] = tolower(*dateString++);
00843 }
00844 monthStr[3] =
'\0';
00845
00846 newPosStr = (
char*)strstr(haystack, monthStr);
00847
00848
if (!newPosStr || (newPosStr - haystack) % 3 != 0)
00849
return invalidDate;
00850
00851 month = (newPosStr-haystack)/3;
00852
00853
if ((month < 0) || (month > 11))
00854
return invalidDate;
00855
00856
while(*dateString && (*dateString !=
'-') && !isspace(*dateString))
00857 dateString++;
00858
00859
if (!*dateString)
00860
return invalidDate;
00861
00862
00863
if ((*dateString !=
'-') && (*dateString !=
'/') && !isspace(*dateString))
00864
return invalidDate;
00865 dateString++;
00866 }
00867
00868
if ((month < 0) || (month > 11))
00869
return invalidDate;
00870 }
00871
00872
00873
if (year <= 0 && *dateString)
00874 year = strtol(dateString, &newPosStr, 10);
00875
00876
00877
if (*newPosStr)
00878 {
00879
00880
if (!isspace(*newPosStr)) {
00881
if ( *newPosStr ==
':' )
00882 year = -1;
00883
else
00884
return invalidDate;
00885 }
else
00886 dateString = ++newPosStr;
00887
00888 have_time =
true;
00889 hour = strtol(dateString, &newPosStr, 10);
00890 dateString = newPosStr;
00891
00892
if ((hour < 0) || (hour > 23))
00893
return invalidDate;
00894
00895
if (!*dateString)
00896
return invalidDate;
00897
00898
00899
if (*dateString++ !=
':')
00900
return invalidDate;
00901
00902 minute = strtol(dateString, &newPosStr, 10);
00903 dateString = newPosStr;
00904
00905
if ((minute < 0) || (minute > 59))
00906
return invalidDate;
00907
00908
00909
if (*dateString && *dateString !=
':' && !isspace(*dateString))
00910
return invalidDate;
00911
00912
00913
if (*dateString ==
':') {
00914 dateString++;
00915
00916 second = strtol(dateString, &newPosStr, 10);
00917 dateString = newPosStr;
00918
00919
if ((second < 0) || (second > 59))
00920
return invalidDate;
00921 }
00922
00923
while(*dateString && isspace(*dateString))
00924 dateString++;
00925 }
00926
else
00927 dateString = newPosStr;
00928
00929
00930
00931
00932
if (*dateString) {
00933
00934
if ( (dateString[0] ==
'G' && dateString[1] ==
'M' && dateString[2] ==
'T')
00935 || (dateString[0] ==
'U' && dateString[1] ==
'T' && dateString[2] ==
'C') )
00936 {
00937 dateString += 3;
00938 have_tz =
true;
00939 }
00940
00941
while (*dateString && isspace(*dateString))
00942 ++dateString;
00943
00944
if (strncasecmp(dateString,
"GMT", 3) == 0) {
00945 dateString += 3;
00946 }
00947
if ((*dateString ==
'+') || (*dateString ==
'-')) {
00948 offset = strtol(dateString, &newPosStr, 10);
00949 dateString = newPosStr;
00950
00951
if ((offset < -9959) || (offset > 9959))
00952
return invalidDate;
00953
00954
int sgn = (offset < 0)? -1:1;
00955 offset = abs(offset);
00956
if ( *dateString ==
':' ) {
00957
int offset2 = strtol(dateString, &newPosStr, 10);
00958 dateString = newPosStr;
00959 offset = (offset*60 + offset2)*sgn;
00960 }
00961
else
00962 offset = ((offset / 100)*60 + (offset % 100))*sgn;
00963 have_tz =
true;
00964 }
else {
00965
for (
int i=0; known_zones[i].tzName != 0; i++) {
00966
if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
00967 offset = known_zones[i].tzOffset;
00968 have_tz =
true;
00969
break;
00970 }
00971 }
00972 }
00973 }
00974
00975
while(*dateString && isspace(*dateString))
00976 dateString++;
00977
00978
if ( *dateString && year == -1 ) {
00979 year = strtol(dateString, &newPosStr, 10);
00980 }
00981
00982
00983
if ((year >= 0) && (year < 50))
00984 year += 2000;
00985
00986
if ((year >= 50) && (year < 100))
00987 year += 1900;
00988
00989
if ((year < 1900) || (year > 2500))
00990
return invalidDate;
00991
00992
if (!have_tz) {
00993
00994
struct tm t;
00995 memset(&t, 0,
sizeof(tm));
00996 t.tm_mday = day;
00997 t.tm_mon = month;
00998 t.tm_year = year - 1900;
00999 t.tm_isdst = -1;
01000
if (have_time) {
01001 t.tm_sec = second;
01002 t.tm_min = minute;
01003 t.tm_hour = hour;
01004 }
01005
01006
return mktime(&t);
01007 }
01008
01009 offset *= 60;
01010
01011 result = ymdhms_to_seconds(year, month+1, day, hour, minute, second);
01012
01013
01014
if ((offset > 0) && (offset > result))
01015 offset = 0;
01016
01017 result -= offset;
01018
01019
01020
01021
01022
if (result < 1) result = 1;
01023
01024
return result;
01025 }
01026
01027
01028
double KJS::timeClip(
double t)
01029 {
01030
if (isInf(t) || fabs(t) > 8.64E15)
01031
return NaN;
01032
return t;
01033 }
01034