From d79d17101399c8fea890528a7b27dd68afe413a1 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Thu, 13 Jul 2017 16:58:03 -0700 Subject: [PATCH 1/3] fix(datepicker): force Intl.DateTimeFormat to use UTC time zone so it doesn't display incorrect dates. --- src/lib/core/datetime/native-date-adapter.spec.ts | 8 ++++++++ src/lib/core/datetime/native-date-adapter.ts | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/lib/core/datetime/native-date-adapter.spec.ts b/src/lib/core/datetime/native-date-adapter.spec.ts index fcde1c3bcea0..31fc3f70669a 100644 --- a/src/lib/core/datetime/native-date-adapter.spec.ts +++ b/src/lib/core/datetime/native-date-adapter.spec.ts @@ -296,6 +296,14 @@ describe('NativeDateAdapter', () => { new Date(2018, FEB, 1), new Date(2018, JAN, 1), new Date(2019, JAN, 1))) .toEqual(new Date(2018, FEB, 1)); }); + + it('should use UTC for formatting by default', () => { + expect(adapter.format(new Date(1800, 7, 14), {day: 'numeric'})).toBe('14'); + + adapter.useUtcForDisplay = false; + + expect(adapter.format(new Date(1800, 7, 14), {day: 'numeric'})).toBe('13'); + }) }); diff --git a/src/lib/core/datetime/native-date-adapter.ts b/src/lib/core/datetime/native-date-adapter.ts index e6d27bc418ac..57ccff2b774f 100644 --- a/src/lib/core/datetime/native-date-adapter.ts +++ b/src/lib/core/datetime/native-date-adapter.ts @@ -56,6 +56,14 @@ export class NativeDateAdapter extends DateAdapter { super.setLocale(localeId); } + /** + * Whether to use `timeZone: 'utc'` with `Intl.DateTimeFormat` when formatting dates. + * Without this `Intl.DateTimeFormat` sometimes chooses the wrong timeZone, which can throw off + * the result. (e.g. in the en-US locale `new Date(1800, 7, 14).toLocaleDateString()` + * will produce `'8/13/1800'`. + */ + useUtcForDisplay = true; + getYear(date: Date): number { return date.getFullYear(); } @@ -154,6 +162,12 @@ export class NativeDateAdapter extends DateAdapter { format(date: Date, displayFormat: Object): string { if (SUPPORTS_INTL_API) { + if (this.useUtcForDisplay) { + date = new Date(Date.UTC( + date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), + date.getMinutes(), date.getSeconds(), date.getMilliseconds())); + displayFormat = Object.assign({}, displayFormat, {timeZone: 'utc'}); + } let dtf = new Intl.DateTimeFormat(this.locale, displayFormat); return this._stripDirectionalityCharacters(dtf.format(date)); } From e6ac030d5e250124b343bea5161f4f67f4a866da Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Fri, 14 Jul 2017 13:22:24 -0700 Subject: [PATCH 2/3] fix lint and test --- src/lib/core/datetime/native-date-adapter.spec.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/core/datetime/native-date-adapter.spec.ts b/src/lib/core/datetime/native-date-adapter.spec.ts index 31fc3f70669a..7100771f7aba 100644 --- a/src/lib/core/datetime/native-date-adapter.spec.ts +++ b/src/lib/core/datetime/native-date-adapter.spec.ts @@ -298,12 +298,12 @@ describe('NativeDateAdapter', () => { }); it('should use UTC for formatting by default', () => { - expect(adapter.format(new Date(1800, 7, 14), {day: 'numeric'})).toBe('14'); - - adapter.useUtcForDisplay = false; - - expect(adapter.format(new Date(1800, 7, 14), {day: 'numeric'})).toBe('13'); - }) + if (SUPPORTS_INTL) { + expect(adapter.format(new Date(1800, 7, 14), {day: 'numeric'})).toBe('14'); + } else { + expect(adapter.format(new Date(1800, 7, 14), {day: 'numeric'})).toBe('Thu Aug 14 1800'); + } + }); }); From d306debb817696b1ddcc6291546114c92e35734b Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Fri, 21 Jul 2017 16:22:35 -0700 Subject: [PATCH 3/3] don't use Object.assign --- src/lib/core/datetime/native-date-adapter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/core/datetime/native-date-adapter.ts b/src/lib/core/datetime/native-date-adapter.ts index 57ccff2b774f..2269942d050e 100644 --- a/src/lib/core/datetime/native-date-adapter.ts +++ b/src/lib/core/datetime/native-date-adapter.ts @@ -8,6 +8,7 @@ import {Inject, Injectable, Optional, LOCALE_ID} from '@angular/core'; import {DateAdapter} from './date-adapter'; +import {extendObject} from '../util/object-extend'; // TODO(mmalerba): Remove when we no longer support safari 9. @@ -166,7 +167,7 @@ export class NativeDateAdapter extends DateAdapter { date = new Date(Date.UTC( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds())); - displayFormat = Object.assign({}, displayFormat, {timeZone: 'utc'}); + displayFormat = extendObject({}, displayFormat, {timeZone: 'utc'}); } let dtf = new Intl.DateTimeFormat(this.locale, displayFormat); return this._stripDirectionalityCharacters(dtf.format(date));