Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 627180f

Browse files
committed
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
1 parent 841feb0 commit 627180f

File tree

2 files changed

+66
-18
lines changed

2 files changed

+66
-18
lines changed

src/ng/directive/input.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -1415,7 +1415,7 @@ function weekParser(isoWeek, existingDate) {
14151415
}
14161416

14171417
function createDateParser(regexp, mapping) {
1418-
return function(iso, date) {
1418+
return function(iso, previousDate) {
14191419
var parts, map;
14201420

14211421
if (isDate(iso)) {
@@ -1437,15 +1437,15 @@ function createDateParser(regexp, mapping) {
14371437

14381438
if (parts) {
14391439
parts.shift();
1440-
if (date) {
1440+
if (previousDate) {
14411441
map = {
1442-
yyyy: date.getFullYear(),
1443-
MM: date.getMonth() + 1,
1444-
dd: date.getDate(),
1445-
HH: date.getHours(),
1446-
mm: date.getMinutes(),
1447-
ss: date.getSeconds(),
1448-
sss: date.getMilliseconds() / 1000
1442+
yyyy: previousDate.getFullYear(),
1443+
MM: previousDate.getMonth() + 1,
1444+
dd: previousDate.getDate(),
1445+
HH: previousDate.getHours(),
1446+
mm: previousDate.getMinutes(),
1447+
ss: previousDate.getSeconds(),
1448+
sss: previousDate.getMilliseconds() / 1000
14491449
};
14501450
} else {
14511451
map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
@@ -1456,7 +1456,15 @@ function createDateParser(regexp, mapping) {
14561456
map[mapping[index]] = +part;
14571457
}
14581458
});
1459-
return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
1459+
1460+
var date = new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
1461+
if (map.yyyy < 100) {
1462+
// In the constructor, 2-digit years map to 1900-1999.
1463+
// Use `setFullYear()` to set the correct year.
1464+
date.setFullYear(map.yyyy);
1465+
}
1466+
1467+
return date;
14601468
}
14611469
}
14621470

test/ng/directive/inputSpec.js

+48-8
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,18 @@
33
/* globals generateInputCompilerHelper: false */
44

55
describe('input', function() {
6-
var helper = {}, $compile, $rootScope, $browser, $sniffer, $timeout, $q;
6+
var helper = {}, $compile, $rootScope, $browser, $sniffer;
77

88
// UA sniffing to exclude Edge from some date input tests
99
var isEdge = /\bEdge\//.test(window.navigator.userAgent);
1010

1111
generateInputCompilerHelper(helper);
1212

13-
beforeEach(inject(function(_$compile_, _$rootScope_, _$browser_, _$sniffer_, _$timeout_, _$q_) {
13+
beforeEach(inject(function(_$compile_, _$rootScope_, _$browser_, _$sniffer_) {
1414
$compile = _$compile_;
1515
$rootScope = _$rootScope_;
1616
$browser = _$browser_;
1717
$sniffer = _$sniffer_;
18-
$timeout = _$timeout_;
19-
$q = _$q_;
2018
}));
2119

2220

@@ -763,6 +761,8 @@ describe('input', function() {
763761
});
764762

765763

764+
// Support: Edge 16
765+
// Edge does not support years with any number of digits other than 4.
766766
if (!isEdge) {
767767
it('should allow four or more digits in year', function() {
768768
var inputElm = helper.compileInput('<input type="month" ng-model="value" ng-model-options="{timezone: \'UTC\'}"/>');
@@ -992,6 +992,8 @@ describe('input', function() {
992992
expect(inputElm).toBeValid();
993993
});
994994

995+
// Support: Edge 16
996+
// Edge does not support years with any number of digits other than 4.
995997
if (!isEdge) {
996998
it('should allow four or more digits in year', function() {
997999
var inputElm = helper.compileInput('<input type="week" ng-model="value" ng-model-options="{timezone: \'UTC\'}"/>');
@@ -1353,6 +1355,8 @@ describe('input', function() {
13531355
});
13541356

13551357

1358+
// Support: Edge 16
1359+
// Edge does not support years with any number of digits other than 4.
13561360
if (!isEdge) {
13571361
it('should allow four or more digits in year', function() {
13581362
var inputElm = helper.compileInput('<input type="datetime-local" ng-model="value" />');
@@ -1556,6 +1560,24 @@ describe('input', function() {
15561560

15571561
expect(inputElm).toBeValid();
15581562
});
1563+
1564+
1565+
// Support: Edge 16
1566+
// Edge does not support years with any number of digits other than 4.
1567+
if (!isEdge) {
1568+
it('should correctly handle 2-digit years', function() {
1569+
helper.compileInput('<input type="datetime-local" ng-model="value" name="alias" />');
1570+
1571+
helper.changeInputValueTo('0001-01-01T12:34:00');
1572+
expect($rootScope.value.getFullYear()).toBe(1);
1573+
1574+
helper.changeInputValueTo('0099-01-01T12:34:00');
1575+
expect($rootScope.value.getFullYear()).toBe(99);
1576+
1577+
helper.changeInputValueTo('0100-01-01T12:34:00');
1578+
expect($rootScope.value.getFullYear()).toBe(100);
1579+
});
1580+
}
15591581
});
15601582

15611583

@@ -2323,9 +2345,9 @@ describe('input', function() {
23232345

23242346
it('should allow Date objects as valid ng-max values', function() {
23252347
$rootScope.max = new Date(2012, 1, 1, 1, 2, 0);
2326-
var inputElm = helper.compileInput('<input type="datetime-local" ng-model="value" name="alias" ng-max="max" />');
2348+
var inputElm = helper.compileInput('<input type="date" ng-model="value" name="alias" ng-max="max" />');
23272349

2328-
helper.changeInputValueTo('2014-01-01T12:34:00');
2350+
helper.changeInputValueTo('2014-01-01');
23292351
expect(inputElm).toBeInvalid();
23302352

23312353
$rootScope.max = new Date(2013, 1, 1, 1, 2, 0);
@@ -2342,9 +2364,9 @@ describe('input', function() {
23422364

23432365
it('should allow Date objects as valid ng-min values', function() {
23442366
$rootScope.min = new Date(2013, 1, 1, 1, 2, 0);
2345-
var inputElm = helper.compileInput('<input type="datetime-local" ng-model="value" name="alias" ng-min="min" />');
2367+
var inputElm = helper.compileInput('<input type="date" ng-model="value" name="alias" ng-min="min" />');
23462368

2347-
helper.changeInputValueTo('2010-01-01T12:34:00');
2369+
helper.changeInputValueTo('2010-01-01');
23482370
expect(inputElm).toBeInvalid();
23492371

23502372
$rootScope.min = new Date(2014, 1, 1, 1, 2, 0);
@@ -2358,6 +2380,24 @@ describe('input', function() {
23582380
expect(inputElm).toBeValid();
23592381
});
23602382

2383+
// Support: Edge 16
2384+
// Edge does not support years with any number of digits other than 4.
2385+
if (!isEdge) {
2386+
it('should correctly handle 2-digit years', function() {
2387+
helper.compileInput('<input type="date" ng-model="value" name="alias" />');
2388+
2389+
helper.changeInputValueTo('0001-01-01');
2390+
expect($rootScope.value.getFullYear()).toBe(1);
2391+
2392+
helper.changeInputValueTo('0099-01-01');
2393+
expect($rootScope.value.getFullYear()).toBe(99);
2394+
2395+
helper.changeInputValueTo('0100-01-01');
2396+
expect($rootScope.value.getFullYear()).toBe(100);
2397+
});
2398+
}
2399+
2400+
23612401
describe('ISO_DATE_REGEXP', function() {
23622402
var dates = [
23632403
// Validate date

0 commit comments

Comments
 (0)