@@ -58,6 +58,9 @@ function range<T>(length: number, valueFunction: (index: number) => T): T[] {
58
58
/** Adapts the native JS Date for use with cdk-based components that work with dates. */
59
59
@Injectable ( )
60
60
export class NativeDateAdapter extends DateAdapter < Date > {
61
+ /** Whether to clamp the date between 1 and 9999 to avoid IE and Edge errors. */
62
+ private readonly _clampDate : boolean ;
63
+
61
64
/**
62
65
* Whether to use `timeZone: 'utc'` with `Intl.DateTimeFormat` when formatting dates.
63
66
* Without this `Intl.DateTimeFormat` sometimes chooses the wrong timeZone, which can throw off
@@ -71,10 +74,13 @@ export class NativeDateAdapter extends DateAdapter<Date> {
71
74
super . setLocale ( matDateLocale ) ;
72
75
73
76
// IE does its own time zone correction, so we disable this on IE.
74
- // TODO(mmalerba): replace with !platform.TRIDENT, logic currently duplicated to avoid breaking
75
- // change from injecting the Platform.
76
- this . useUtcForDisplay = ! ( typeof document === 'object' && ! ! document &&
77
- / ( m s i e | t r i d e n t ) / i. test ( navigator . userAgent ) ) ;
77
+ // TODO(mmalerba): replace with checks from PLATFORM, logic currently duplicated to avoid
78
+ // breaking change from injecting the Platform.
79
+ const isBrowser = typeof document === 'object' && ! ! document ;
80
+ const isIE = isBrowser && / ( m s i e | t r i d e n t ) / i. test ( navigator . userAgent ) ;
81
+
82
+ this . useUtcForDisplay = ! isIE ;
83
+ this . _clampDate = isIE || ( isBrowser && / ( e d g e ) / i. test ( navigator . userAgent ) ) ;
78
84
}
79
85
80
86
getYear ( date : Date ) : number {
@@ -179,14 +185,23 @@ export class NativeDateAdapter extends DateAdapter<Date> {
179
185
if ( ! this . isValid ( date ) ) {
180
186
throw Error ( 'NativeDateAdapter: Cannot format invalid date.' ) ;
181
187
}
188
+
182
189
if ( SUPPORTS_INTL_API ) {
190
+ // On IE and Edge the i18n API will throw a hard error that can crash the entire app
191
+ // if we attempt to format a date whose year is less than 1 or greater than 9999.
192
+ if ( this . _clampDate && ( date . getFullYear ( ) < 1 || date . getFullYear ( ) > 9999 ) ) {
193
+ date = this . clone ( date ) ;
194
+ date . setFullYear ( Math . max ( 1 , Math . min ( 9999 , date . getFullYear ( ) ) ) ) ;
195
+ }
196
+
183
197
if ( this . useUtcForDisplay ) {
184
198
date = new Date ( Date . UTC (
185
199
date . getFullYear ( ) , date . getMonth ( ) , date . getDate ( ) , date . getHours ( ) ,
186
200
date . getMinutes ( ) , date . getSeconds ( ) , date . getMilliseconds ( ) ) ) ;
187
201
displayFormat = { ...displayFormat , timeZone : 'utc' } ;
188
202
}
189
- let dtf = new Intl . DateTimeFormat ( this . locale , displayFormat ) ;
203
+
204
+ const dtf = new Intl . DateTimeFormat ( this . locale , displayFormat ) ;
190
205
return this . _stripDirectionalityCharacters ( dtf . format ( date ) ) ;
191
206
}
192
207
return this . _stripDirectionalityCharacters ( date . toDateString ( ) ) ;
0 commit comments