зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1860425 - Adjust parsing for timezone numbers without "GMT" prefix r=arai
Differential Revision: https://phabricator.services.mozilla.com/D191618
This commit is contained in:
Родитель
a28468e526
Коммит
c7283bdb04
|
@ -1398,6 +1398,8 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
|||
bool seenMonthName = false;
|
||||
bool seenFullYear = false;
|
||||
bool negativeYear = false;
|
||||
// Includes "GMT", "UTC", "UT", and "Z" timezone keywords
|
||||
bool seenGmtAbbr = false;
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
|
@ -1412,16 +1414,8 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
|||
TryParseDashedDatePrefix(s, length, &index, &year, &mon, &mday) ||
|
||||
TryParseDashedNumericDatePrefix(s, length, &index, &year, &mon, &mday);
|
||||
|
||||
if (isDashedDate && index < length) {
|
||||
if (strchr("T:+", s[index])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the next char is a '-', we need to skip it so that the next number
|
||||
// doesn't get parsed as a time zone
|
||||
if (s[index] == '-') {
|
||||
index++;
|
||||
}
|
||||
if (isDashedDate && index < length && strchr("T:+", s[index])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (index < length) {
|
||||
|
@ -1435,6 +1429,17 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
|||
c = ' ';
|
||||
}
|
||||
|
||||
if ((c == '+' || c == '-') &&
|
||||
// Reject + or - after timezone (still allowing for negative year)
|
||||
((seenPlusMinus && year != -1) ||
|
||||
// Reject timezones like "1995-09-26 -04:30" (if the - is right up
|
||||
// against the previous number, it will get parsed as a time,
|
||||
// see the other comment below)
|
||||
(year != -1 && hour == -1 && !seenGmtAbbr &&
|
||||
!IsAsciiDigit(s[index - 2])))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spaces, ASCII control characters, periods, and commas are simply ignored.
|
||||
if (c <= ' ' || c == '.' || c == ',') {
|
||||
continue;
|
||||
|
@ -1515,7 +1520,10 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
|||
year = n;
|
||||
seenFullYear = true;
|
||||
negativeYear = true;
|
||||
} else if ((prevc == '+' || prevc == '-') /* && year>=0 */) {
|
||||
} else if ((prevc == '+' || prevc == '-') &&
|
||||
// "1995-09-26-04:30" needs to be parsed as a time,
|
||||
// not a time zone
|
||||
(seenGmtAbbr || hour != -1)) {
|
||||
/* Make ':' case below change tzOffset. */
|
||||
seenPlusMinus = true;
|
||||
|
||||
|
@ -1564,8 +1572,9 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
|||
}
|
||||
} else if (index < length && c != ',' && c > ' ' && c != '-' &&
|
||||
c != '(' &&
|
||||
// Allow zulu time e.g. "09/26/1995 16:00Z"
|
||||
!(hour != -1 && strchr("Zz", c)) &&
|
||||
// Allow zulu time e.g. "09/26/1995 16:00Z", or
|
||||
// '+' directly after time e.g. 00:00+0500
|
||||
!(hour != -1 && strchr("Zz+", c)) &&
|
||||
// Allow '.' after day of month i.e. DD.Mon.YYYY/Mon.DD.YYYY,
|
||||
// or after year/month in YYYY/MM/DD
|
||||
(c != '.' || mday != -1) &&
|
||||
|
@ -1636,6 +1645,10 @@ static bool ParseDate(DateTimeInfo::ForceUTC forceUTC, const CharT* s,
|
|||
break;
|
||||
}
|
||||
|
||||
if (action == 10000) {
|
||||
seenGmtAbbr = true;
|
||||
}
|
||||
|
||||
// Perform action tests from smallest action values to largest.
|
||||
|
||||
// Adjust a previously-specified hour for AM/PM accordingly (taking care
|
||||
|
|
|
@ -44,11 +44,6 @@ const tests = [
|
|||
["24-Apr-2023 12:34:56 -04:30", "2023-04-24T12:34:56-04:30"],
|
||||
|
||||
["24-Apr-2023 GMT", "2023-04-24T00:00:00Z"],
|
||||
["24-Apr-2023 +04", "2023-04-24T00:00:00+04:00"],
|
||||
["24-Apr-2023 +04:30", "2023-04-24T00:00:00+04:30"],
|
||||
["24-Apr-2023 -04", "2023-04-24T00:00:00-04:00"],
|
||||
["24-Apr-2023 -04:30", "2023-04-24T00:00:00-04:30"],
|
||||
|
||||
["24-Apr-2023GMT", "2023-04-24T00:00:00Z"],
|
||||
["24-Apr-2023GMT-04", "2023-04-24T00:00:00-04:00"],
|
||||
["24-Apr-2023GMT-04:30", "2023-04-24T00:00:00-04:30"],
|
||||
|
@ -56,13 +51,9 @@ const tests = [
|
|||
["24-Apr-2023GMT+04:30", "2023-04-24T00:00:00+04:30"],
|
||||
|
||||
["24-Apr-2023,GMT", "2023-04-24T00:00:00Z"],
|
||||
["24-Apr-2023,+04", "2023-04-24T00:00:00+04:00"],
|
||||
["24-Apr-2023,+04:30", "2023-04-24T00:00:00+04:30"],
|
||||
["24-Apr-2023,-04", "2023-04-24T00:00:00-04:00"],
|
||||
["24-Apr-2023,-04:30", "2023-04-24T00:00:00-04:30"],
|
||||
["24-Apr-2023/GMT", "2023-04-24T00:00:00Z"],
|
||||
|
||||
["24-Apr-2023/12:34:56", "2023-04-24T12:34:56"],
|
||||
["24-Apr-2023/GMT", "2023-04-24T00:00:00Z"],
|
||||
|
||||
// ==== non dd-MMM-yyyy. Uses fallback path ====
|
||||
|
||||
|
@ -100,6 +91,10 @@ const tests = [
|
|||
["24-Apr-2312()10:13:14", "2312-04-24T10:13:14"],
|
||||
// Open paren only comments out the time
|
||||
["24-Apr-2312(10:13:14", "2312-04-24T00:00:00"],
|
||||
|
||||
// mday being 3+ digits, while year being 2-3 digits.
|
||||
["024-Apr-23", "2023-04-24T00:00:00"],
|
||||
["024-Apr-023", "2023-04-24T00:00:00"],
|
||||
];
|
||||
|
||||
for (const [testString, isoString] of tests) {
|
||||
|
@ -114,10 +109,6 @@ const invalidTests = [
|
|||
// mday being out of range.
|
||||
"32-01-32",
|
||||
|
||||
// mday being 3+ digits, while year being 2-3 digits.
|
||||
"024-Apr-22",
|
||||
"024-Apr-023",
|
||||
|
||||
// Duplicate date.
|
||||
"2012-Apr-08 12/12/12",
|
||||
|
||||
|
@ -133,11 +124,6 @@ const invalidTests = [
|
|||
"24-Apr-2312+10:13:14",
|
||||
"24-Apr-2312=10:13:14",
|
||||
"24-Apr-2312?10:13:14",
|
||||
|
||||
// No space between date and time zone w/o GMT
|
||||
"24-Apr-2023+04",
|
||||
"24-Apr-2023+04:30",
|
||||
"24-Apr-2023-04",
|
||||
];
|
||||
|
||||
for (const testString of invalidTests) {
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const accepted = {
|
||||
"1995-09-26T00:00:00-0500": [
|
||||
"Sep 26 1995 GMT-0500",
|
||||
"Sep 26 1995 00:00:00 GMT-0500",
|
||||
"Sep 26 1995 00:00:00 gmt-0500",
|
||||
"Sep 26 1995 00:00:00 Z-0500",
|
||||
"Sep 26 1995 00:00:00 UT-0500",
|
||||
"Sep 26 1995 00:00:00 UTC-0500",
|
||||
"Sep 26 1995 00:00:00 -0500",
|
||||
"Sep 26 1995 00:00:00 -05",
|
||||
"Sep 26 1995 00:00:00-0500",
|
||||
"Sep 26 1995 00:00:00-05",
|
||||
"Sep 26 1995 00:00 -0500",
|
||||
"Sep 26 1995 00:00 -05",
|
||||
"Sep 26 1995 00:00-0500",
|
||||
"Sep 26 1995 00:00-05",
|
||||
],
|
||||
|
||||
"1995-09-26T00:00:00+0500": [
|
||||
"Sep 26 1995 GMT+0500",
|
||||
"Sep 26 1995 00:00:00 GMT+0500",
|
||||
"Sep 26 1995 00:00:00 gmt+0500",
|
||||
"Sep 26 1995 00:00:00 Z+0500",
|
||||
"Sep 26 1995 00:00:00 UT+0500",
|
||||
"Sep 26 1995 00:00:00 UTC+0500",
|
||||
"Sep 26 1995 00:00:00 +0500",
|
||||
"Sep 26 1995 00:00:00 +05",
|
||||
"Sep 26 1995 00:00:00+0500",
|
||||
"Sep 26 1995 00:00:00+05",
|
||||
"Sep 26 1995 00:00 +0500",
|
||||
"Sep 26 1995 00:00 +05",
|
||||
"Sep 26 1995 00:00+0500",
|
||||
"Sep 26 1995 00:00+05",
|
||||
],
|
||||
|
||||
"1995-09-26T00:00:00-0430": [
|
||||
"Sep 26 1995 GMT-04:30",
|
||||
"Sep 26 1995 00:00:00 GMT-04:30",
|
||||
"Sep 26 1995 00:00:00 -04:30",
|
||||
"Sep 26 1995 00:00:00-04:30",
|
||||
"Sep 26 1995 00:00 -04:30",
|
||||
"Sep 26 1995 00:00-04:30",
|
||||
],
|
||||
|
||||
"1995-09-26T00:00:00+0430": [
|
||||
"Sep 26 1995 GMT+04:30",
|
||||
"Sep 26 1995 00:00:00 GMT+04:30",
|
||||
"Sep 26 1995 00:00:00 +04:30",
|
||||
"Sep 26 1995 00:00:00+04:30",
|
||||
"Sep 26 1995 00:00 +04:30",
|
||||
"Sep 26 1995 00:00+04:30",
|
||||
],
|
||||
|
||||
"1995-09-26T04:30:00": [
|
||||
"Sep 26 1995-04:30",
|
||||
"1995-09-26-04:30",
|
||||
"1995-Sep-26-04:30",
|
||||
],
|
||||
};
|
||||
const rejected = [
|
||||
"Sep 26 1995 -05",
|
||||
"Sep 26 1995-05",
|
||||
"Sep 26 1995 -04:30",
|
||||
"1995-09-26 -05",
|
||||
"1995-09-26 -04:30",
|
||||
"1995-09-26-05",
|
||||
"1995-Sep-26 -05",
|
||||
"1995-Sep-26-05",
|
||||
"1995-Sep-26,-05",
|
||||
|
||||
"Sep 26 1995 +05",
|
||||
"Sep 26 1995 +04:30",
|
||||
"Sep 26 1995+05",
|
||||
"Sep 26 1995+04:30",
|
||||
"1995-09-26 +05",
|
||||
"1995-09-26+05",
|
||||
"1995-Sep-26 +05",
|
||||
"1995-Sep-26+05",
|
||||
"1995-Sep-26,+05",
|
||||
|
||||
// These cases are allowed by V8 but are parsed as GMT-XXXX no matter the
|
||||
// abbreviation (e.g. EST-0500 is parsed as GMT-0500 and not GMT-1000). This
|
||||
// is unexpected and so we are explicitly rejecting them.
|
||||
"Sep 26 1995 00:00:00 EST-0500",
|
||||
"Sep 26 1995 00:00:00 MDT-0500",
|
||||
];
|
||||
|
||||
for (const [expected, patterns] of Object.entries(accepted)) {
|
||||
for (const test of patterns) {
|
||||
const testDate = new Date(test);
|
||||
const expectedDate = new Date(expected);
|
||||
|
||||
assertEq(
|
||||
false, isNaN(testDate),
|
||||
`${test} should be accepted.`
|
||||
);
|
||||
|
||||
assertEq(
|
||||
testDate.getTime(), expectedDate.getTime(),
|
||||
`"${test}" should be ${expectedDate} (got ${testDate}).`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (const reject of rejected) {
|
||||
assertEq(
|
||||
true, isNaN(new Date(reject)),
|
||||
`"${reject}" should be rejected.`
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const accepted = {
|
||||
"1997-11-05T00:00:00-0800": [
|
||||
"Wed Nov 05 00:00:00 GMT-0800 1997",
|
||||
"Nov 05 00:00:00 GMT-0800 1997",
|
||||
"Nov-05 00:00:00 GMT-0800 1997",
|
||||
"05-Nov 00:00:00 GMT-0800 1997",
|
||||
"05-Nov GMT-0800 1997",
|
||||
],
|
||||
|
||||
"-001997-11-05T00:00:00-0800": [
|
||||
"Wed Nov 05 00:00:00 GMT-0800 -1997",
|
||||
"Nov 05 00:00:00 GMT-0800 -1997",
|
||||
"Nov-05 00:00:00 GMT-0800 -1997",
|
||||
"05-Nov 00:00:00 GMT-0800 -1997",
|
||||
"05-Nov GMT-0800 -1997",
|
||||
],
|
||||
};
|
||||
|
||||
for (const [expected, patterns] of Object.entries(accepted)) {
|
||||
for (const test of patterns) {
|
||||
const testDate = new Date(test);
|
||||
const expectedDate = new Date(expected);
|
||||
|
||||
assertEq(
|
||||
false, isNaN(testDate),
|
||||
`${test} should be accepted.`
|
||||
);
|
||||
|
||||
assertEq(
|
||||
testDate.getTime(), expectedDate.getTime(),
|
||||
`"${test}" should be ${expectedDate} (got ${testDate}).`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
Загрузка…
Ссылка в новой задаче