Skip to content

Commit

Permalink
fix(common): DatePipe parses input string if it's not a valid date in…
Browse files Browse the repository at this point in the history
… browser (#13895)

Closes #12334
Closes #13874

PR Close #13895
  • Loading branch information
Dzmitry Shylovich authored and mhevery committed Feb 1, 2017
1 parent 9d2c712 commit 093cc04
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
37 changes: 33 additions & 4 deletions modules/@angular/common/src/pipes/date_pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
10 changes: 8 additions & 2 deletions modules/@angular/common/test/pipes/date_pipe_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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));
});
});
}

1 comment on commit 093cc04

@mhevery
Copy link
Contributor

@mhevery mhevery commented on 093cc04 Feb 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caretaker: fix(common): DatePipe should parses input string even if it's not a valid date in browser

Please sign in to comment.