angular-cn/packages/common/test/i18n/format_date_spec.ts

366 lines
11 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @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 localeAr from '@angular/common/locales/ar';
import localeDe from '@angular/common/locales/de';
import localeEn from '@angular/common/locales/en';
import localeEnExtra from '@angular/common/locales/extra/en';
import localeHu from '@angular/common/locales/hu';
import localeSr from '@angular/common/locales/sr';
import localeTh from '@angular/common/locales/th';
import {formatDate, isDate, toDate} from '@angular/common/src/i18n/format_date';
import {ɵDEFAULT_LOCALE_ID, ɵregisterLocaleData, ɵunregisterLocaleData} from '@angular/core';
describe('Format date', () => {
describe('toDate', () => {
it('should support date', () => {
expect(isDate(toDate(new Date()))).toBeTruthy();
});
it('should support int', () => {
expect(isDate(toDate(123456789))).toBeTruthy();
});
it('should support numeric strings', () => {
expect(isDate(toDate('123456789'))).toBeTruthy();
});
it('should support decimal strings', () => {
expect(isDate(toDate('123456789.11'))).toBeTruthy();
});
it('should support ISO string', () => {
expect(isDate(toDate('2015-06-15T21:43:11Z'))).toBeTruthy();
});
it('should throw for empty string', () => {
expect(() => toDate('')).toThrow();
});
it('should throw for alpha numeric strings', () => {
expect(() => toDate('123456789 hello')).toThrow();
});
it('should throw for NaN', () => {
expect(() => toDate(Number.NaN)).toThrow();
});
it('should support ISO string without time', () => {
expect(isDate(toDate('2015-01-01'))).toBeTruthy();
});
it('should throw for objects', () => {
expect(() => toDate({} as any)).toThrow();
});
});
describe('formatDate', () => {
const isoStringWithoutTime = '2015-01-01';
const defaultFormat = 'mediumDate';
let date: Date;
// Check the transformation of a date into a pattern
function expectDateFormatAs(date: Date|string, pattern: any, output: string): void {
expect(formatDate(date, pattern, ɵDEFAULT_LOCALE_ID))
.toEqual(output, `pattern: "${pattern}"`);
}
beforeAll(() => {
ɵregisterLocaleData(localeEn, localeEnExtra);
ɵregisterLocaleData(localeDe);
ɵregisterLocaleData(localeHu);
ɵregisterLocaleData(localeSr);
ɵregisterLocaleData(localeTh);
ɵregisterLocaleData(localeAr);
});
afterAll(() => ɵunregisterLocaleData());
beforeEach(() => {
date = new Date(2015, 5, 15, 9, 3, 1, 550);
});
it('should format each component correctly', () => {
const dateFixtures: any = {
G: 'AD',
GG: 'AD',
GGG: 'AD',
GGGG: 'Anno Domini',
GGGGG: 'A',
y: '2015',
yy: '15',
yyy: '2015',
yyyy: '2015',
M: '6',
MM: '06',
MMM: 'Jun',
MMMM: 'June',
MMMMM: 'J',
L: '6',
LL: '06',
LLL: 'Jun',
LLLL: 'June',
LLLLL: 'J',
w: '25',
ww: '25',
W: '3',
d: '15',
dd: '15',
E: 'Mon',
EE: 'Mon',
EEE: 'Mon',
EEEE: 'Monday',
EEEEEE: 'Mo',
h: '9',
hh: '09',
H: '9',
HH: '09',
m: '3',
mm: '03',
s: '1',
ss: '01',
S: '5',
SS: '55',
SSS: '550',
a: 'AM',
aa: 'AM',
aaa: 'AM',
aaaa: 'AM',
aaaaa: 'a',
b: 'morning',
bb: 'morning',
bbb: 'morning',
bbbb: 'morning',
bbbbb: 'morning',
B: 'in the morning',
BB: 'in the morning',
BBB: 'in the morning',
BBBB: 'in the morning',
BBBBB: 'in the morning',
};
const isoStringWithoutTimeFixtures: any = {
G: 'AD',
GG: 'AD',
GGG: 'AD',
GGGG: 'Anno Domini',
GGGGG: 'A',
y: '2015',
yy: '15',
yyy: '2015',
yyyy: '2015',
M: '1',
MM: '01',
MMM: 'Jan',
MMMM: 'January',
MMMMM: 'J',
L: '1',
LL: '01',
LLL: 'Jan',
LLLL: 'January',
LLLLL: 'J',
w: '1',
ww: '01',
W: '1',
d: '1',
dd: '01',
E: 'Thu',
EE: 'Thu',
EEE: 'Thu',
EEEE: 'Thursday',
EEEEE: 'T',
EEEEEE: 'Th',
h: '12',
hh: '12',
H: '0',
HH: '00',
m: '0',
mm: '00',
s: '0',
ss: '00',
S: '0',
SS: '00',
SSS: '000',
a: 'AM',
aa: 'AM',
aaa: 'AM',
aaaa: 'AM',
aaaaa: 'a',
b: 'midnight',
bb: 'midnight',
bbb: 'midnight',
bbbb: 'midnight',
bbbbb: 'midnight',
B: 'midnight',
BB: 'midnight',
BBB: 'midnight',
BBBB: 'midnight',
BBBBB: 'mi',
};
const midnightCrossingPeriods: any = {
b: 'night',
bb: 'night',
bbb: 'night',
bbbb: 'night',
bbbbb: 'night',
B: 'at night',
BB: 'at night',
BBB: 'at night',
BBBB: 'at night',
BBBBB: 'at night',
};
Object.keys(dateFixtures).forEach((pattern: string) => {
expectDateFormatAs(date, pattern, dateFixtures[pattern]);
});
Object.keys(isoStringWithoutTimeFixtures).forEach((pattern: string) => {
expectDateFormatAs(isoStringWithoutTime, pattern, isoStringWithoutTimeFixtures[pattern]);
});
const nightTime = new Date(2015, 5, 15, 2, 3, 1, 550);
Object.keys(midnightCrossingPeriods).forEach(pattern => {
expectDateFormatAs(nightTime, pattern, midnightCrossingPeriods[pattern]);
});
});
it('should format with timezones', () => {
const dateFixtures: any = {
z: /GMT(\+|-)\d/,
zz: /GMT(\+|-)\d/,
zzz: /GMT(\+|-)\d/,
zzzz: /GMT(\+|-)\d{2}\:30/,
Z: /(\+|-)\d{2}30/,
ZZ: /(\+|-)\d{2}30/,
ZZZ: /(\+|-)\d{2}30/,
ZZZZ: /GMT(\+|-)\d{2}\:30/,
ZZZZZ: /(\+|-)\d{2}\:30/,
O: /GMT(\+|-)\d/,
OOOO: /GMT(\+|-)\d{2}\:30/,
};
Object.keys(dateFixtures).forEach((pattern: string) => {
expect(formatDate(date, pattern, ɵDEFAULT_LOCALE_ID, '+0430'))
.toMatch(dateFixtures[pattern]);
});
});
it('should format common multi component patterns', () => {
const dateFixtures: any = {
'EEE, M/d/y': 'Mon, 6/15/2015',
'EEE, M/d': 'Mon, 6/15',
'MMM d': 'Jun 15',
'dd/MM/yyyy': '15/06/2015',
'MM/dd/yyyy': '06/15/2015',
'yMEEEd': '20156Mon15',
'MEEEd': '6Mon15',
'MMMd': 'Jun15',
'EEEE, MMMM d, y': 'Monday, June 15, 2015',
'H:mm a': '9:03 AM',
'ms': '31',
'MM/dd/yy hh:mm': '06/15/15 09:03',
'MM/dd/y': '06/15/2015'
};
Object.keys(dateFixtures).forEach((pattern: string) => {
expectDateFormatAs(date, pattern, dateFixtures[pattern]);
});
});
it('should format with pattern aliases', () => {
const dateFixtures: any = {
'MM/dd/yyyy': '06/15/2015',
shortDate: '6/15/15',
mediumDate: 'Jun 15, 2015',
longDate: 'June 15, 2015',
fullDate: 'Monday, June 15, 2015',
short: '6/15/15, 9:03 AM',
medium: 'Jun 15, 2015, 9:03:01 AM',
long: /June 15, 2015 at 9:03:01 AM GMT(\+|-)\d/,
full: /Monday, June 15, 2015 at 9:03:01 AM GMT(\+|-)\d{2}:\d{2}/,
shortTime: '9:03 AM',
mediumTime: '9:03:01 AM',
longTime: /9:03:01 AM GMT(\+|-)\d/,
fullTime: /9:03:01 AM GMT(\+|-)\d{2}:\d{2}/,
};
Object.keys(dateFixtures).forEach((pattern: string) => {
expect(formatDate(date, pattern, ɵDEFAULT_LOCALE_ID)).toMatch(dateFixtures[pattern]);
});
});
it('should format invalid in IE ISO date',
() => expect(formatDate('2017-01-11T12:00:00.014-0500', defaultFormat, ɵDEFAULT_LOCALE_ID))
.toEqual('Jan 11, 2017'));
it('should format invalid in Safari ISO date',
() => expect(formatDate('2017-01-20T12:00:00+0000', defaultFormat, ɵDEFAULT_LOCALE_ID))
.toEqual('Jan 20, 2017'));
// https://github.com/angular/angular/issues/9524
// https://github.com/angular/angular/issues/9524
it('should format correctly with iso strings that contain time',
() => expect(formatDate('2017-05-07T22:14:39', 'dd-MM-yyyy HH:mm', ɵDEFAULT_LOCALE_ID))
.toMatch(/07-05-2017 \d{2}:\d{2}/));
// https://github.com/angular/angular/issues/21491
it('should not assume UTC for iso strings in Safari if the timezone is not defined', () => {
// this test only works if the timezone is not in UTC
// which is the case for BrowserStack when we test Safari
if (new Date().getTimezoneOffset() !== 0) {
expect(formatDate('2018-01-11T13:00:00', 'HH', ɵDEFAULT_LOCALE_ID))
.not.toEqual(formatDate('2018-01-11T13:00:00Z', 'HH', ɵDEFAULT_LOCALE_ID));
}
});
// https://github.com/angular/angular/issues/16624
// https://github.com/angular/angular/issues/17478
it('should show the correct time when the timezone is fixed', () => {
expect(formatDate('2017-06-13T10:14:39+0000', 'shortTime', ɵDEFAULT_LOCALE_ID, '+0000'))
.toEqual('10:14 AM');
expect(formatDate('2017-06-13T10:14:39+0000', 'h:mm a', ɵDEFAULT_LOCALE_ID, '+0000'))
.toEqual('10:14 AM');
});
it('should remove bidi control characters',
() => expect(formatDate(date, 'MM/dd/yyyy', ɵDEFAULT_LOCALE_ID)!.length).toEqual(10));
it(`should format the date correctly in various locales`, () => {
expect(formatDate(date, 'short', 'de')).toEqual('15.06.15, 09:03');
expect(formatDate(date, 'short', 'ar')).toEqual('15/6/2015 9:03 ص');
expect(formatDate(date, 'dd-MM-yy', 'th')).toEqual('15-06-15');
expect(formatDate(date, 'a', 'hu')).toEqual('de.');
expect(formatDate(date, 'a', 'sr')).toEqual('пре подне');
// TODO(ocombe): activate this test when we support local numbers
// expect(formatDate(date, 'hh', 'mr')).toEqual('०९');
});
it('should throw if we use getExtraDayPeriods without loading extra locale data', () => {
expect(() => formatDate(date, 'b', 'de'))
.toThrowError(/Missing extra locale data for the locale "de"/);
});
// https://github.com/angular/angular/issues/24384
it('should not round fractional seconds', () => {
expect(formatDate(3999, 'm:ss', 'en')).toEqual('0:03');
expect(formatDate(3999, 'm:ss.S', 'en')).toEqual('0:03.9');
expect(formatDate(3999, 'm:ss.SS', 'en')).toEqual('0:03.99');
expect(formatDate(3999, 'm:ss.SSS', 'en')).toEqual('0:03.999');
expect(formatDate(3000, 'm:ss', 'en')).toEqual('0:03');
expect(formatDate(3000, 'm:ss.S', 'en')).toEqual('0:03.0');
expect(formatDate(3000, 'm:ss.SS', 'en')).toEqual('0:03.00');
expect(formatDate(3000, 'm:ss.SSS', 'en')).toEqual('0:03.000');
expect(formatDate(3001, 'm:ss', 'en')).toEqual('0:03');
expect(formatDate(3001, 'm:ss.S', 'en')).toEqual('0:03.0');
expect(formatDate(3001, 'm:ss.SS', 'en')).toEqual('0:03.00');
expect(formatDate(3001, 'm:ss.SSS', 'en')).toEqual('0:03.001');
});
});
});