angular-cn/packages/common/test/pipes/date_pipe_spec.ts
Ajit Singh 26f28200bf fix(common): do not round up fractions of a millisecond in DatePipe (#38009)
Currently, the `DatePipe` (via `formatDate()`) rounds fractions of a millisecond to the
nearest millisecond. This can cause dates that are less than a millisecond before midnight
to be incremented to the following day.

The [ECMAScript specification](https://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.11)
defines that `DateTime` milliseconds should always be rounded down, so that `999.9ms`
becomes `999ms`.

This change brings `formatDate()` and so `DatePipe` inline with the ECMAScript
specification.

Fixes #37989

BREAKING CHANGE:

When passing a date-time formatted string to the `DatePipe` in a format that contains
fractions of a millisecond, the milliseconds will now always be rounded down rather than
to the nearest millisecond.

Most applications will not be affected by this change. If this is not the desired behaviour
then consider pre-processing the string to round the millisecond part before passing
it to the `DatePipe`.

PR Close #38009
2020-09-10 10:55:37 -07:00

98 lines
3.5 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {DatePipe} from '@angular/common';
import localeEn from '@angular/common/locales/en';
import localeEnExtra from '@angular/common/locales/extra/en';
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
import {ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_reflector';
{
let date: Date;
describe('DatePipe', () => {
const isoStringWithoutTime = '2015-01-01';
let pipe: DatePipe;
beforeAll(() => ɵregisterLocaleData(localeEn, localeEnExtra));
afterAll(() => ɵunregisterLocaleData());
beforeEach(() => {
date = new Date(2015, 5, 15, 9, 3, 1, 550);
pipe = new DatePipe('en-US');
});
it('should be marked as pure', () => {
expect(new PipeResolver(new JitReflector()).resolve(DatePipe)!.pure).toEqual(true);
});
describe('supports', () => {
it('should support date', () => {
expect(() => pipe.transform(date)).not.toThrow();
});
it('should support int', () => {
expect(() => pipe.transform(123456789)).not.toThrow();
});
it('should support numeric strings', () => {
expect(() => pipe.transform('123456789')).not.toThrow();
});
it('should support decimal strings', () => {
expect(() => pipe.transform('123456789.11')).not.toThrow();
});
it('should support ISO string',
() => expect(() => pipe.transform('2015-06-15T21:43:11Z')).not.toThrow());
it('should return null for empty string', () => {
expect(pipe.transform('')).toEqual(null);
});
it('should return null for NaN', () => {
expect(pipe.transform(Number.NaN)).toEqual(null);
});
it('should support ISO string without time', () => {
expect(() => pipe.transform(isoStringWithoutTime)).not.toThrow();
});
it('should not support other objects', () => {
expect(() => pipe.transform({})).toThrowError(/InvalidPipeArgument/);
});
});
describe('transform', () => {
it('should use "mediumDate" as the default format',
() => expect(pipe.transform('2017-01-11T10:14:39+0000')).toEqual('Jan 11, 2017'));
it('should return first week if some dates fall in previous year but belong to next year according to ISO 8601 format',
() => {
expect(pipe.transform('2019-12-28T00:00:00', 'w')).toEqual('52');
expect(pipe.transform('2019-12-29T00:00:00', 'w')).toEqual('1');
expect(pipe.transform('2019-12-30T00:00:00', 'w')).toEqual('1');
});
it('should return first week if some dates fall in previous leap year but belong to next year according to ISO 8601 format',
() => {
expect(pipe.transform('2012-12-29T00:00:00', 'w')).toEqual('52');
expect(pipe.transform('2012-12-30T00:00:00', 'w')).toEqual('1');
expect(pipe.transform('2012-12-31T00:00:00', 'w')).toEqual('1');
});
it('should round milliseconds down to the nearest millisecond', () => {
expect(pipe.transform('2020-08-01T23:59:59.999', 'yyyy-MM-dd')).toEqual('2020-08-01');
expect(pipe.transform('2020-08-01T23:59:59.9999', 'yyyy-MM-dd, h:mm:ss SSS'))
.toEqual('2020-08-01, 11:59:59 999');
});
});
});
}