diff --git a/modules/@angular/common/src/pipes/date_pipe.ts b/modules/@angular/common/src/pipes/date_pipe.ts index b691375c36..f95f946167 100644 --- a/modules/@angular/common/src/pipes/date_pipe.ts +++ b/modules/@angular/common/src/pipes/date_pipe.ts @@ -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); +} diff --git a/modules/@angular/common/test/pipes/date_pipe_spec.ts b/modules/@angular/common/test/pipes/date_pipe_spec.ts index 1db44aa928..3159e125e1 100644 --- a/modules/@angular/common/test/pipes/date_pipe_spec.ts +++ b/modules/@angular/common/test/pipes/date_pipe_spec.ts @@ -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)); }); }); }