Skip to content

Commit dd49fa6

Browse files
authored
fix(material/core): incorrectly formatting dates in the years 0 to 99 (#20612)
We were formatting dates in the years 0 to 99 incorrectly, because we pass it through the `Date` constructor which infers them as 19xx. We already had logic to handle cases like this when creating dates, but the formatting logic didn't go through the same code path. These changes extend the logic to the formatting utilities. This fix resolves part of #20418, but we'll also have to make some changes to the datepicker calendar so it doesn't generate out-of-bounds years.
1 parent 8cacf64 commit dd49fa6

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

src/material/core/datetime/native-date-adapter.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,16 @@ describe('NativeDateAdapter', () => {
152152
expect(adapter.getYearName(new Date(2017, JAN, 1))).toBe('2017');
153153
});
154154

155+
it('should year name for low year numbers', () => {
156+
const createAndFormat = (year: number) => {
157+
return adapter.getYearName(adapter.createDate(year, JAN, 1));
158+
};
159+
160+
expect(createAndFormat(50)).toBe('50');
161+
expect(createAndFormat(99)).toBe('99');
162+
expect(createAndFormat(100)).toBe('100');
163+
});
164+
155165
it('should get year name in a different locale', () => {
156166
adapter.setLocale('ja-JP');
157167
if (SUPPORTS_INTL) {
@@ -187,6 +197,22 @@ describe('NativeDateAdapter', () => {
187197
expect(adapter.createDate(100, JAN, 1).getFullYear()).toBe(100);
188198
});
189199

200+
it('should format Date with low year number', () => {
201+
const createAndFormat = (year: number) => {
202+
return adapter.format(adapter.createDate(year, JAN, 1), {});
203+
};
204+
205+
if (SUPPORTS_INTL) {
206+
expect(createAndFormat(50)).toBe('1/1/50');
207+
expect(createAndFormat(99)).toBe('1/1/99');
208+
expect(createAndFormat(100)).toBe('1/1/100');
209+
} else {
210+
expect(createAndFormat(50)).toBe('Sat Jan 01 0050');
211+
expect(createAndFormat(99)).toBe('Thu Jan 01 0099');
212+
expect(createAndFormat(100)).toBe('Fri Jan 01 0100');
213+
}
214+
});
215+
190216
it("should get today's date", () => {
191217
expect(adapter.sameDate(adapter.today(), new Date()))
192218
.toBe(true, "should be equal to today's date");

src/material/core/datetime/native-date-adapter.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,14 +283,7 @@ export class NativeDateAdapter extends DateAdapter<Date> {
283283

284284
/** Creates a date but allows the month and date to overflow. */
285285
private _createDateWithOverflow(year: number, month: number, date: number) {
286-
const result = new Date(year, month, date);
287-
288-
// We need to correct for the fact that JS native Date treats years in range [0, 99] as
289-
// abbreviations for 19xx.
290-
if (year >= 0 && year < 100) {
291-
result.setFullYear(this.getYear(result) - 1900);
292-
}
293-
return result;
286+
return this._correctYear(new Date(year, month, date), year);
294287
}
295288

296289
/**
@@ -325,9 +318,22 @@ export class NativeDateAdapter extends DateAdapter<Date> {
325318
* @returns A Date object with its UTC representation based on the passed in date info
326319
*/
327320
private _format(dtf: Intl.DateTimeFormat, date: Date) {
321+
const year = date.getFullYear();
328322
const d = new Date(Date.UTC(
329-
date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(),
323+
year, date.getMonth(), date.getDate(), date.getHours(),
330324
date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
331-
return dtf.format(d);
325+
return dtf.format(this._correctYear(d, year));
326+
}
327+
328+
/**
329+
* Corrects the year of a date, accounting for the fact that JS
330+
* native Date treats years between 0 and 99 as abbreviations for 19xx.
331+
*/
332+
private _correctYear(date: Date, intendedYear: number): Date {
333+
if (intendedYear >= 0 && intendedYear < 100) {
334+
date.setFullYear(this.getYear(date) - 1900);
335+
}
336+
337+
return date;
332338
}
333339
}

0 commit comments

Comments
 (0)