#399: change JS date 2-digit year base

This commit is contained in:
Cameron Kaiser 2017-08-17 18:02:23 -07:00
parent e5a4aa65bf
commit a7518d26c4
4 changed files with 106 additions and 229 deletions

View File

@ -1076,55 +1076,48 @@ ParseDate(const CharT* s, size_t length, ClippedTime* result)
* Case 1. The input string contains an English month name.
* The form of the string can be month f l, or f month l, or
* f l month which each evaluate to the same date.
* If f and l are both greater than or equal to 70, or
* both less than 70, the date is invalid.
* The year is taken to be the greater of the values f, l.
* If the year is greater than or equal to 70 and less than 100,
* it is considered to be the number of years after 1900.
* If f and l are both greater than or equal to 100 the date
* is invalid.
*
* The year is taken to be either the greater of the values f, l or
* whichever is set to zero. If the year is greater than or equal to
* 50 and less than 100, it is considered to be the number of years
* after 1900. If the year is less than 50 it is considered to be the
* number of years after 2000, otherwise it is considered to be the
* number of years after 0.
*
* Case 2. The input string is of the form "f/m/l" where f, m and l are
* integers, e.g. 7/16/45.
* Adjust the mon, mday and year values to achieve 100% MSIE
* compatibility.
* a. If 0 <= f < 70, f/m/l is interpreted as month/day/year.
* i. If year < 100, it is the number of years after 1900
* ii. If year >= 100, it is the number of years after 0.
* b. If 70 <= f < 100
* i. If m < 70, f/m/l is interpreted as
* year/month/day where year is the number of years after
* 1900.
* ii. If m >= 70, the date is invalid.
* c. If f >= 100
* i. If m < 70, f/m/l is interpreted as
* year/month/day where year is the number of years after 0.
* ii. If m >= 70, the date is invalid.
* integers, e.g. 7/16/45. mon, mday and year values are adjusted
* to achieve Chrome compatibility.
*
* a. If 0 < f <= 12 and 0 < l <= 31, f/m/l is interpreted as
* month/day/year.
* i. If year < 50, it is the number of years after 2000
* ii. If year >= 50, it is the number of years after 1900.
* iii. If year >= 100, it is the number of years after 0.
* b. If 31 < f and 0 < m <= 12 and 0 < l <= 31 f/m/l is
* interpreted as year/month/day
* i. If year < 50, it is the number of years after 2000
* ii. If year >= 50, it is the number of years after 1900.
* iii. If year >= 100, it is the number of years after 0.
*/
if (seenMonthName) {
if ((mday >= 70 && year >= 70) || (mday < 70 && year < 70))
if (mday >= 100 && mon >= 100)
return false;
if (mday > year) {
if (year > 0 && (mday == 0 || mday > year)) {
int temp = year;
year = mday;
mday = temp;
}
if (year >= 70 && year < 100) {
year += 1900;
}
} else if (mon < 70) { /* (a) month/day/year */
if (year < 100) {
year += 1900;
}
} else if (mon < 100) { /* (b) year/month/day */
if (mday < 70) {
int temp = year;
year = mon + 1900;
mon = mday;
mday = temp;
} else {
if (mday <= 0 || mday > 31)
return false;
}
} else { /* (c) year/month/day */
if (mday < 70) {
} else if (0 < mon && mon <= 12 && 0 < mday && mday <= 31) {
/* (a) month/day/year */
} else {
/* (b) year/month/day */
if (mon > 31 && mday <= 12 && year <= 31) {
int temp = year;
year = mon;
mon = mday;
@ -1134,6 +1127,11 @@ ParseDate(const CharT* s, size_t length, ClippedTime* result)
}
}
if (year < 50)
year += 2000;
else if (year >= 50 && year < 100)
year += 1900;
mon -= 1; /* convert month to 0-based */
if (sec < 0)
sec = 0;

View File

@ -1,60 +0,0 @@
/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributor: Bob Clary
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 273292;
var summary = '15.9.3.2 new Date(value)';
var actual = '';
var expect = '';
var date1;
var date2;
var i;
var validDateStrings = [
"11/69/2004",
"11/70/2004",
"69/69/2004",
"69/69/69",
"69/69/1969",
"70/69/70",
"70/69/1970",
"70/69/2004"
];
var invalidDateStrings = [
"70/70/70",
"70/70/1970",
"70/70/2004"
];
printBugNumber(BUGNUMBER);
printStatus (summary);
expect = 0;
for (i = 0; i < validDateStrings.length; i++)
{
date1 = new Date(validDateStrings[i]);
date2 = new Date(date1.toDateString());
actual = date2 - date1;
reportCompare(expect, actual, inSection(i) + ' ' +
validDateStrings[i]);
}
expect = true;
var offset = validDateStrings.length;
for (i = 0; i < invalidDateStrings.length; i++)
{
date1 = new Date(invalidDateStrings[i]);
actual = isNaN(date1);
reportCompare(expect, actual, inSection(i + offset) + ' ' +
invalidDateStrings[i] + ' is invalid.');
}

View File

@ -0,0 +1,69 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommonn.org/licenses/publicdomain/
*/
/*
* For the sake of cross compatibility with other implementations we
* implement date parsing heuristics which support single and double
* digit years. See bug: 1265136
*/
/**************
* BEGIN TEST *
**************/
for (let year of Array(100).keys()) {
for (let month of Array(12).keys()) {
for (let day of Array(31).keys()) {
let fullYear = year >= 50 ? year + 1900 : year + 2000;
let fullDate = new Date(`${month + 1}/${day + 1}/${fullYear}`);
// mm/dd/yy
let d1 = new Date(`${month + 1}/${day + 1}/${year}`);
assertEq(d1.getTime(), fullDate.getTime())
// yy/mm/dd
let d2 = new Date(`${year}/${month + 1}/${day + 1}`);
if (year > 31) {
assertEq(d2.getTime(), fullDate.getTime())
} else if (year > 12) {
assertEq(d2.getTime(), new Date(NaN).getTime())
}
}
}
}
assertEq(new Date("99/1/99").getTime(), new Date(NaN).getTime());
assertEq(new Date("13/13/13").getTime(), new Date(NaN).getTime());
assertEq(new Date("0/10/0").getTime(), new Date(NaN).getTime());
// Written months.
for (let year of Array(1000).keys()) {
let fullDate = new Date(`5/1/${year}`);
let d1 = new Date(`may ${year} 1`);
let d2 = new Date(`may 1 ${year}`);
let d3 = new Date(`1 may ${year}`);
let d4 = new Date(`${year} may 1`);
let d5 = new Date(`1 ${year} may`);
let d6 = new Date(`${year} 1 may`);
assertEq(d1.getTime(), fullDate.getTime())
assertEq(d2.getTime(), fullDate.getTime())
assertEq(d3.getTime(), fullDate.getTime())
assertEq(d4.getTime(), fullDate.getTime())
assertEq(d5.getTime(), fullDate.getTime())
assertEq(d6.getTime(), fullDate.getTime())
}
assertEq(new Date("may 1999 1999").getTime(), new Date(NaN).getTime());
assertEq(new Date("may 0 0").getTime(), new Date(NaN).getTime());
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

View File

@ -1,130 +0,0 @@
/* -*- 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/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 301738;
var summary = 'Date parse compatibilty with MSIE';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
printStatus (summary);
/*
Case 2. The input string is of the form "f/m/l" where f, m and l are
integers, e.g. 7/16/45.
Adjust the mon, mday and year values to achieve 100% MSIE
compatibility.
a. If 0 <= f < 70, f/m/l is interpreted as month/day/year.
i. If year < 100, it is the number of years after 1900
ii. If year >= 100, it is the number of years after 0.
b. If 70 <= f < 100
i. If m < 70, f/m/l is interpreted as
year/month/day where year is the number of years after
1900.
ii. If m >= 70, the date is invalid.
c. If f >= 100
i. If m < 70, f/m/l is interpreted as
year/month/day where year is the number of years after 0.
ii. If m >= 70, the date is invalid.
*/
var f;
var m;
var l;
function newDate(f, m, l)
{
return new Date(f + '/' + m + '/' + l);
}
function newDesc(f, m, l)
{
return f + '/' + m + '/' + l;
}
// 2.a.i
f = 0;
m = 0;
l = 0;
expect = (new Date(l, f-1, m)).toDateString();
actual = newDate(f, m, l).toDateString();
reportCompare(expect, actual, newDesc(f, m, l));
f = 0;
m = 0;
l = 100;
expect = (new Date(l, f-1, m)).toDateString();
actual = newDate(f, m, l).toDateString();
reportCompare(expect, actual, newDesc(f, m, l));
// 2.a.ii
f = 0;
m = 24;
l = 100;
expect = (new Date(l, f-1, m)).toDateString();
actual = newDate(f, m, l).toDateString();
reportCompare(expect, actual, newDesc(f, m, l));
f = 0;
m = 24;
l = 2100;
expect = (new Date(l, f-1, m)).toDateString();
actual = newDate(f, m, l).toDateString();
reportCompare(expect, actual, newDesc(f, m, l));
// 2.b.i
f = 70;
m = 24;
l = 100;
expect = (new Date(f, m-1, l)).toDateString();
actual = newDate(f, m, l).toDateString();
reportCompare(expect, actual, newDesc(f, m, l));
f = 99;
m = 12;
l = 1;
expect = (new Date(f, m-1, l)).toDateString();
actual = newDate(f, m, l).toDateString();
reportCompare(expect, actual, newDesc(f, m, l));
// 2.b.ii.
f = 99;
m = 70;
l = 1;
expect = true;
actual = isNaN(newDate(f, m, l));
reportCompare(expect, actual, newDesc(f, m, l) + ' is an invalid date');
// 2.c.i
f = 100;
m = 12;
l = 1;
expect = (new Date(f, m-1, l)).toDateString();
actual = newDate(f, m, l).toDateString();
reportCompare(expect, actual, newDesc(f, m, l));
// 2.c.ii
f = 100;
m = 70;
l = 1;
expect = true;
actual = isNaN(newDate(f, m, l));
reportCompare(expect, actual, newDesc(f, m, l) + ' is an invalid date');