fix(common): DatePipe parses input string if it's not a valid date in browser (#13895)
Closes #12334 Closes #13874 PR Close #13895
This commit is contained in:
parent
9d2c71269b
commit
093cc04748
|
@ -7,13 +7,13 @@
|
|||
*/
|
||||
|
||||
import {Inject, LOCALE_ID, Pipe, PipeTransform} from '@angular/core';
|
||||
|
||||
import {NumberWrapper} from '../facade/lang';
|
||||
|
||||
import {DateFormatter} from './intl';
|
||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||
|
||||
|
||||
const ISO8601_DATE_REGEX =
|
||||
/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
|
||||
// 1 2 3 4 5 6 7 8 9 10 11
|
||||
|
||||
/**
|
||||
* @ngModule CommonModule
|
||||
|
@ -130,7 +130,12 @@ export class DatePipe implements PipeTransform {
|
|||
}
|
||||
|
||||
if (!isDate(date)) {
|
||||
throw new InvalidPipeArgumentError(DatePipe, value);
|
||||
let match: RegExpMatchArray;
|
||||
if ((typeof value === 'string') && (match = value.match(ISO8601_DATE_REGEX))) {
|
||||
date = isoStringToDate(match);
|
||||
} else {
|
||||
throw new InvalidPipeArgumentError(DatePipe, value);
|
||||
}
|
||||
}
|
||||
|
||||
return DateFormatter.format(date, this._locale, DatePipe._ALIASES[pattern] || pattern);
|
||||
|
@ -144,3 +149,27 @@ function isBlank(obj: any): boolean {
|
|||
function isDate(obj: any): obj is Date {
|
||||
return obj instanceof Date && !isNaN(obj.valueOf());
|
||||
}
|
||||
|
||||
function isoStringToDate(match: RegExpMatchArray): Date {
|
||||
const date = new Date(0);
|
||||
let tzHour = 0;
|
||||
let tzMin = 0;
|
||||
const dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear;
|
||||
const timeSetter = match[8] ? date.setUTCHours : date.setHours;
|
||||
|
||||
if (match[9]) {
|
||||
tzHour = toInt(match[9] + match[10]);
|
||||
tzMin = toInt(match[9] + match[11]);
|
||||
}
|
||||
dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
|
||||
const h = toInt(match[4] || '0') - tzHour;
|
||||
const m = toInt(match[5] || '0') - tzMin;
|
||||
const s = toInt(match[6] || '0');
|
||||
const ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
|
||||
timeSetter.call(date, h, m, s, ms);
|
||||
return date;
|
||||
}
|
||||
|
||||
function toInt(str: string): number {
|
||||
return parseInt(str, 10);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ export function main() {
|
|||
() => { expect(() => pipe.transform(isoStringWithoutTime)).not.toThrow(); });
|
||||
|
||||
it('should not support other objects',
|
||||
() => { expect(() => pipe.transform({})).toThrowError(); });
|
||||
() => expect(() => pipe.transform({})).toThrowError(/Invalid argument/));
|
||||
});
|
||||
|
||||
describe('transform', () => {
|
||||
|
@ -190,8 +190,14 @@ export function main() {
|
|||
|
||||
});
|
||||
|
||||
it('should format invalid in IE ISO date',
|
||||
() => expect(pipe.transform('2017-01-11T09:25:14.014-0500')).toEqual('Jan 11, 2017'));
|
||||
|
||||
it('should format invalid in Safari ISO date',
|
||||
() => expect(pipe.transform('2017-01-20T19:00:00+0000')).toEqual('Jan 20, 2017'));
|
||||
|
||||
it('should remove bidi control characters',
|
||||
() => { expect(pipe.transform(date, 'MM/dd/yyyy').length).toEqual(10); });
|
||||
() => expect(pipe.transform(date, 'MM/dd/yyyy').length).toEqual(10));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue