in rhino/src/main/java/org/mozilla/javascript/NativeDate.java [1149:1355]
private static double date_parseString(Context cx, String s) {
double d = parseISOString(cx, s);
if (!Double.isNaN(d)) {
return d;
}
int year = -1;
int mon = -1;
int mday = -1;
int hour = -1;
int min = -1;
int sec = -1;
char c = 0;
char si = 0;
int i = 0;
int n = -1;
double tzoffset = -1;
char prevc = 0;
int limit = 0;
boolean seenplusminus = false;
limit = s.length();
while (i < limit) {
c = s.charAt(i);
i++;
if (c <= ' ' || c == ',' || c == '-') {
if (i < limit) {
si = s.charAt(i);
if (c == '-' && '0' <= si && si <= '9') {
prevc = c;
}
}
continue;
}
if (c == '(') {
/* comments) */
int depth = 1;
while (i < limit) {
c = s.charAt(i);
i++;
if (c == '(') depth++;
else if (c == ')') if (--depth <= 0) break;
}
continue;
}
if ('0' <= c && c <= '9') {
n = c - '0';
while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
n = n * 10 + c - '0';
i++;
}
/* allow TZA before the year, so
* 'Wed Nov 05 21:49:11 GMT-0800 1997'
* works */
/* uses of seenplusminus allow : in TZA, so Java
* no-timezone style of GMT+4:30 works
*/
if ((prevc == '+' || prevc == '-') /* && year>=0 */) {
/* make ':' case below change tzoffset */
seenplusminus = true;
/* offset */
if (n < 24) n = n * 60; /* EG. "GMT-3" */
else n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */
if (prevc == '+') /* plus means east of GMT */ n = -n;
if (tzoffset != 0 && tzoffset != -1) return ScriptRuntime.NaN;
tzoffset = n;
} else if (n >= 70 || (prevc == '/' && mon >= 0 && mday >= 0 && year < 0)) {
if (year >= 0) return ScriptRuntime.NaN;
else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
year = n < 100 ? n + 1900 : n;
else return ScriptRuntime.NaN;
} else if (c == ':') {
if (hour < 0) hour = /*byte*/ n;
else if (min < 0) min = /*byte*/ n;
else return ScriptRuntime.NaN;
} else if (c == '/') {
if (mon < 0) mon = /*byte*/ n - 1;
else if (mday < 0) mday = /*byte*/ n;
else return ScriptRuntime.NaN;
} else if (i < limit && c != ',' && c > ' ' && c != '-') {
return ScriptRuntime.NaN;
} else if (seenplusminus && n < 60) {
/* handle GMT-3:30 */
if (tzoffset < 0) tzoffset -= n;
else tzoffset += n;
} else if (hour >= 0 && min < 0) {
min = /*byte*/ n;
} else if (min >= 0 && sec < 0) {
sec = /*byte*/ n;
} else if (mday < 0) {
mday = /*byte*/ n;
} else {
return ScriptRuntime.NaN;
}
prevc = 0;
} else if (c == '/' || c == ':' || c == '+' || c == '-') {
prevc = c;
} else {
int st = i - 1;
while (i < limit) {
c = s.charAt(i);
if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))) break;
i++;
}
int letterCount = i - st;
if (letterCount < 2) return ScriptRuntime.NaN;
/*
* Use ported code from jsdate.c rather than the locale-specific
* date-parsing code from Java, to keep js and rhino consistent.
* Is this the right strategy?
*/
String wtb =
"am;pm;"
+ "monday;tuesday;wednesday;thursday;friday;"
+ "saturday;sunday;"
+ "january;february;march;april;may;june;"
+ "july;august;september;october;november;december;"
+ "gmt;ut;utc;est;edt;cst;cdt;mst;mdt;pst;pdt;";
int index = 0;
for (int wtbOffset = 0; ; ) {
int wtbNext = wtb.indexOf(';', wtbOffset);
if (wtbNext < 0) return ScriptRuntime.NaN;
if (wtb.regionMatches(true, wtbOffset, s, st, letterCount)) break;
wtbOffset = wtbNext + 1;
++index;
}
if (index < 2) {
/*
* AM/PM. Count 12:30 AM as 00:30, 12:30 PM as
* 12:30, instead of blindly adding 12 if PM.
*/
if (hour > 12 || hour < 0) {
return ScriptRuntime.NaN;
} else if (index == 0) {
// AM
if (hour == 12) hour = 0;
} else {
// PM
if (hour != 12) hour += 12;
}
} else if ((index -= 2) < 7) {
// ignore week days
} else if ((index -= 7) < 12) {
// month
if (mon < 0) {
mon = index;
} else {
return ScriptRuntime.NaN;
}
} else {
index -= 12;
// timezones
switch (index) {
case 0 /* gmt */:
tzoffset = 0;
break;
case 1 /* ut */:
tzoffset = 0;
break;
case 2 /* utc */:
tzoffset = 0;
break;
case 3 /* est */:
tzoffset = 5 * 60;
break;
case 4 /* edt */:
tzoffset = 4 * 60;
break;
case 5 /* cst */:
tzoffset = 6 * 60;
break;
case 6 /* cdt */:
tzoffset = 5 * 60;
break;
case 7 /* mst */:
tzoffset = 7 * 60;
break;
case 8 /* mdt */:
tzoffset = 6 * 60;
break;
case 9 /* pst */:
tzoffset = 8 * 60;
break;
case 10 /* pdt */:
tzoffset = 7 * 60;
break;
default:
Kit.codeBug();
}
}
}
}
if (year < 0 || mon < 0 || mday < 0) return ScriptRuntime.NaN;
if (sec < 0) sec = 0;
if (min < 0) min = 0;
if (hour < 0) hour = 0;
double msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
if (tzoffset == -1) {
/* no time zone specified, have to use local */
return internalUTC(cx, msec);
}
return msec + tzoffset * msPerMinute;
}