Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 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, isDate} from '../facade/lang';

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 @@ -140,3 +145,31 @@ export class DatePipe implements PipeTransform {
function isBlank(obj: any): boolean {
return obj == null || obj === '';
}

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));
});
});
}
4 changes: 0 additions & 4 deletions modules/@angular/facade/src/lang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ export function isStrictStringMap(obj: any): boolean {
return typeof obj === 'object' && obj !== null && Object.getPrototypeOf(obj) === STRING_MAP_PROTO;
}

export function isDate(obj: any): obj is Date {
return obj instanceof Date && !isNaN(obj.valueOf());
}

export function stringify(token: any): string {
if (typeof token === 'string') {
return token;
Expand Down