fix(input[date]): correctly parse 2-digit years
When parsing a date string value, AngularJS uses `new Date(year, ...)` to create a Date object and assign it to the model. In the constructor, 2-digit years map to 1900-1999, so the created Date object has the wrong value for year. This commit fixes it, by explicitly using `setFullYear()` to set the year to the correct value, when necessary. Fixes #16537 Closes #16539
This commit is contained in:
+18
-10
@@ -1415,7 +1415,7 @@ function weekParser(isoWeek, existingDate) {
|
||||
}
|
||||
|
||||
function createDateParser(regexp, mapping) {
|
||||
return function(iso, date) {
|
||||
return function(iso, previousDate) {
|
||||
var parts, map;
|
||||
|
||||
if (isDate(iso)) {
|
||||
@@ -1437,15 +1437,15 @@ function createDateParser(regexp, mapping) {
|
||||
|
||||
if (parts) {
|
||||
parts.shift();
|
||||
if (date) {
|
||||
if (previousDate) {
|
||||
map = {
|
||||
yyyy: date.getFullYear(),
|
||||
MM: date.getMonth() + 1,
|
||||
dd: date.getDate(),
|
||||
HH: date.getHours(),
|
||||
mm: date.getMinutes(),
|
||||
ss: date.getSeconds(),
|
||||
sss: date.getMilliseconds() / 1000
|
||||
yyyy: previousDate.getFullYear(),
|
||||
MM: previousDate.getMonth() + 1,
|
||||
dd: previousDate.getDate(),
|
||||
HH: previousDate.getHours(),
|
||||
mm: previousDate.getMinutes(),
|
||||
ss: previousDate.getSeconds(),
|
||||
sss: previousDate.getMilliseconds() / 1000
|
||||
};
|
||||
} else {
|
||||
map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
|
||||
@@ -1456,7 +1456,15 @@ function createDateParser(regexp, mapping) {
|
||||
map[mapping[index]] = +part;
|
||||
}
|
||||
});
|
||||
return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
|
||||
|
||||
var date = new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
|
||||
if (map.yyyy < 100) {
|
||||
// In the constructor, 2-digit years map to 1900-1999.
|
||||
// Use `setFullYear()` to set the correct year.
|
||||
date.setFullYear(map.yyyy);
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,20 +3,18 @@
|
||||
/* globals generateInputCompilerHelper: false */
|
||||
|
||||
describe('input', function() {
|
||||
var helper = {}, $compile, $rootScope, $browser, $sniffer, $timeout, $q;
|
||||
var helper = {}, $compile, $rootScope, $browser, $sniffer;
|
||||
|
||||
// UA sniffing to exclude Edge from some date input tests
|
||||
var isEdge = /\bEdge\//.test(window.navigator.userAgent);
|
||||
|
||||
generateInputCompilerHelper(helper);
|
||||
|
||||
beforeEach(inject(function(_$compile_, _$rootScope_, _$browser_, _$sniffer_, _$timeout_, _$q_) {
|
||||
beforeEach(inject(function(_$compile_, _$rootScope_, _$browser_, _$sniffer_) {
|
||||
$compile = _$compile_;
|
||||
$rootScope = _$rootScope_;
|
||||
$browser = _$browser_;
|
||||
$sniffer = _$sniffer_;
|
||||
$timeout = _$timeout_;
|
||||
$q = _$q_;
|
||||
}));
|
||||
|
||||
|
||||
@@ -763,6 +761,8 @@ describe('input', function() {
|
||||
});
|
||||
|
||||
|
||||
// Support: Edge 16
|
||||
// Edge does not support years with any number of digits other than 4.
|
||||
if (!isEdge) {
|
||||
it('should allow four or more digits in year', function() {
|
||||
var inputElm = helper.compileInput('<input type="month" ng-model="value" ng-model-options="{timezone: \'UTC\'}"/>');
|
||||
@@ -992,6 +992,8 @@ describe('input', function() {
|
||||
expect(inputElm).toBeValid();
|
||||
});
|
||||
|
||||
// Support: Edge 16
|
||||
// Edge does not support years with any number of digits other than 4.
|
||||
if (!isEdge) {
|
||||
it('should allow four or more digits in year', function() {
|
||||
var inputElm = helper.compileInput('<input type="week" ng-model="value" ng-model-options="{timezone: \'UTC\'}"/>');
|
||||
@@ -1353,6 +1355,8 @@ describe('input', function() {
|
||||
});
|
||||
|
||||
|
||||
// Support: Edge 16
|
||||
// Edge does not support years with any number of digits other than 4.
|
||||
if (!isEdge) {
|
||||
it('should allow four or more digits in year', function() {
|
||||
var inputElm = helper.compileInput('<input type="datetime-local" ng-model="value" />');
|
||||
@@ -1556,6 +1560,24 @@ describe('input', function() {
|
||||
|
||||
expect(inputElm).toBeValid();
|
||||
});
|
||||
|
||||
|
||||
// Support: Edge 16
|
||||
// Edge does not support years with any number of digits other than 4.
|
||||
if (!isEdge) {
|
||||
it('should correctly handle 2-digit years', function() {
|
||||
helper.compileInput('<input type="datetime-local" ng-model="value" name="alias" />');
|
||||
|
||||
helper.changeInputValueTo('0001-01-01T12:34:00');
|
||||
expect($rootScope.value.getFullYear()).toBe(1);
|
||||
|
||||
helper.changeInputValueTo('0099-01-01T12:34:00');
|
||||
expect($rootScope.value.getFullYear()).toBe(99);
|
||||
|
||||
helper.changeInputValueTo('0100-01-01T12:34:00');
|
||||
expect($rootScope.value.getFullYear()).toBe(100);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2323,9 +2345,9 @@ describe('input', function() {
|
||||
|
||||
it('should allow Date objects as valid ng-max values', function() {
|
||||
$rootScope.max = new Date(2012, 1, 1, 1, 2, 0);
|
||||
var inputElm = helper.compileInput('<input type="datetime-local" ng-model="value" name="alias" ng-max="max" />');
|
||||
var inputElm = helper.compileInput('<input type="date" ng-model="value" name="alias" ng-max="max" />');
|
||||
|
||||
helper.changeInputValueTo('2014-01-01T12:34:00');
|
||||
helper.changeInputValueTo('2014-01-01');
|
||||
expect(inputElm).toBeInvalid();
|
||||
|
||||
$rootScope.max = new Date(2013, 1, 1, 1, 2, 0);
|
||||
@@ -2342,9 +2364,9 @@ describe('input', function() {
|
||||
|
||||
it('should allow Date objects as valid ng-min values', function() {
|
||||
$rootScope.min = new Date(2013, 1, 1, 1, 2, 0);
|
||||
var inputElm = helper.compileInput('<input type="datetime-local" ng-model="value" name="alias" ng-min="min" />');
|
||||
var inputElm = helper.compileInput('<input type="date" ng-model="value" name="alias" ng-min="min" />');
|
||||
|
||||
helper.changeInputValueTo('2010-01-01T12:34:00');
|
||||
helper.changeInputValueTo('2010-01-01');
|
||||
expect(inputElm).toBeInvalid();
|
||||
|
||||
$rootScope.min = new Date(2014, 1, 1, 1, 2, 0);
|
||||
@@ -2358,6 +2380,24 @@ describe('input', function() {
|
||||
expect(inputElm).toBeValid();
|
||||
});
|
||||
|
||||
// Support: Edge 16
|
||||
// Edge does not support years with any number of digits other than 4.
|
||||
if (!isEdge) {
|
||||
it('should correctly handle 2-digit years', function() {
|
||||
helper.compileInput('<input type="date" ng-model="value" name="alias" />');
|
||||
|
||||
helper.changeInputValueTo('0001-01-01');
|
||||
expect($rootScope.value.getFullYear()).toBe(1);
|
||||
|
||||
helper.changeInputValueTo('0099-01-01');
|
||||
expect($rootScope.value.getFullYear()).toBe(99);
|
||||
|
||||
helper.changeInputValueTo('0100-01-01');
|
||||
expect($rootScope.value.getFullYear()).toBe(100);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
describe('ISO_DATE_REGEXP', function() {
|
||||
var dates = [
|
||||
// Validate date
|
||||
|
||||
Reference in New Issue
Block a user