/** * @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 {Inject, InjectionToken, LOCALE_ID, Optional, Pipe, PipeTransform} from '@angular/core'; import {formatDate} from '../i18n/format_date'; import {DatePipeConfig, DEFAULT_DATE_FORMAT} from './date_pipe_config'; import {invalidPipeArgumentError} from './invalid_pipe_argument_error'; /** * Optionally-provided default timezone to use for all instances of `DatePipe` (such as `'+0430'`). * If the value isn't provided, the `DatePipe` will use the end-user's local system timezone. * * @deprecated use DATE_PIPE_DEFAULT_OPTIONS token to configure DatePipe */ export const DATE_PIPE_DEFAULT_TIMEZONE = new InjectionToken( ngDevMode ? 'DATE_PIPE_DEFAULT_TIMEZONE' : '', ); /** * DI token that allows to provide default configuration for the `DatePipe` instances in an * application. The value is an object which can include the following fields: * - `dateFormat`: configures the default date format. If not provided, the `DatePipe` * will use the 'mediumDate' as a value. * - `timezone`: configures the default timezone. If not provided, the `DatePipe` will * use the end-user's local system timezone. * * @see {@link DatePipeConfig} * * @usageNotes * * Various date pipe default values can be overwritten by providing this token with * the value that has this interface. * * For example: * * Override the default date format by providing a value using the token: * ```typescript * providers: [ * {provide: DATE_PIPE_DEFAULT_OPTIONS, useValue: {dateFormat: 'shortDate'}} * ] * ``` * * Override the default timezone by providing a value using the token: * ```typescript * providers: [ * {provide: DATE_PIPE_DEFAULT_OPTIONS, useValue: {timezone: '-1200'}} * ] * ``` */ export const DATE_PIPE_DEFAULT_OPTIONS = new InjectionToken( ngDevMode ? 'DATE_PIPE_DEFAULT_OPTIONS' : '', ); // clang-format off /** * @ngModule CommonModule * @description * * Formats a date value according to locale rules. * * `DatePipe` is executed only when it detects a pure change to the input value. * A pure change is either a change to a primitive input value * (such as `String`, `Number`, `Boolean`, or `Symbol`), * or a changed object reference (such as `Date`, `Array`, `Function`, or `Object`). * * Note that mutating a `Date` object does not cause the pipe to be rendered again. * To ensure that the pipe is executed, you must create a new `Date` object. * * Only the `en-US` locale data comes with Angular. To localize dates * in another language, you must import the corresponding locale data. * See the [I18n guide](guide/i18n-common-format-data-locale) for more information. * * The time zone of the formatted value can be specified either by passing it in as the second * parameter of the pipe, or by setting the default through the `DATE_PIPE_DEFAULT_OPTIONS` * injection token. The value that is passed in as the second parameter takes precedence over * the one defined using the injection token. * * @see {@link formatDate} * * * @usageNotes * * The result of this pipe is not reevaluated when the input is mutated. To avoid the need to * reformat the date on every change-detection cycle, treat the date as an immutable object * and change the reference when the pipe needs to run again. * * ### Pre-defined format options * * | Option | Equivalent to | Examples (given in `en-US` locale) | * |---------------|-------------------------------------|-------------------------------------------------| * | `'short'` | `'M/d/yy, h:mm a'` | `6/15/15, 9:03 AM` | * | `'medium'` | `'MMM d, y, h:mm:ss a'` | `Jun 15, 2015, 9:03:01 AM` | * | `'long'` | `'MMMM d, y, h:mm:ss a z'` | `June 15, 2015 at 9:03:01 AM GMT+1` | * | `'full'` | `'EEEE, MMMM d, y, h:mm:ss a zzzz'` | `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00` | * | `'shortDate'` | `'M/d/yy'` | `6/15/15` | * | `'mediumDate'`| `'MMM d, y'` | `Jun 15, 2015` | * | `'longDate'` | `'MMMM d, y'` | `June 15, 2015` | * | `'fullDate'` | `'EEEE, MMMM d, y'` | `Monday, June 15, 2015` | * | `'shortTime'` | `'h:mm a'` | `9:03 AM` | * | `'mediumTime'`| `'h:mm:ss a'` | `9:03:01 AM` | * | `'longTime'` | `'h:mm:ss a z'` | `9:03:01 AM GMT+1` | * | `'fullTime'` | `'h:mm:ss a zzzz'` | `9:03:01 AM GMT+01:00` | * * ### Custom format options * * You can construct a format string using symbols to specify the components * of a date-time value, as described in the following table. * Format details depend on the locale. * Fields marked with (*) are only available in the extra data set for the given locale. * * | Field type | Format | Description | Example Value | * |-------------------------|-------------|---------------------------------------------------------------|------------------------------------------------------------| * | Era | G, GG & GGG | Abbreviated | AD | * | | GGGG | Wide | Anno Domini | * | | GGGGG | Narrow | A | * | Year | y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 | * | | yy | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 | * | | yyy | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 | * | | yyyy | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 | * | ISO Week-numbering year | Y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 | * | | YY | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 | * | | YYY | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 | * | | YYYY | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 | * | Month | M | Numeric: 1 digit | 9, 12 | * | | MM | Numeric: 2 digits + zero padded | 09, 12 | * | | MMM | Abbreviated | Sep | * | | MMMM | Wide | September | * | | MMMMM | Narrow | S | * | Month standalone | L | Numeric: 1 digit | 9, 12 | * | | LL | Numeric: 2 digits + zero padded | 09, 12 | * | | LLL | Abbreviated | Sep | * | | LLLL | Wide | September | * | | LLLLL | Narrow | S | * | ISO Week of year | w | Numeric: minimum digits | 1... 53 | * | | ww | Numeric: 2 digits + zero padded | 01... 53 | * | Week of month | W | Numeric: 1 digit | 1... 5 | * | Day of month | d | Numeric: minimum digits | 1 | * | | dd | Numeric: 2 digits + zero padded | 01 | * | Week day | E, EE & EEE | Abbreviated | Tue | * | | EEEE | Wide | Tuesday | * | | EEEEE | Narrow | T | * | | EEEEEE | Short | Tu | * | Week day standalone | c, cc | Numeric: 1 digit | 2 | * | | ccc | Abbreviated | Tue | * | | cccc | Wide | Tuesday | * | | ccccc | Narrow | T | * | | cccccc | Short | Tu | * | Period | a, aa & aaa | Abbreviated | am/pm or AM/PM | * | | aaaa | Wide (fallback to `a` when missing) | ante meridiem/post meridiem | * | | aaaaa | Narrow | a/p | * | Period* | B, BB & BBB | Abbreviated | mid. | * | | BBBB | Wide | am, pm, midnight, noon, morning, afternoon, evening, night | * | | BBBBB | Narrow | md | * | Period standalone* | b, bb & bbb | Abbreviated | mid. | * | | bbbb | Wide | am, pm, midnight, noon, morning, afternoon, evening, night | * | | bbbbb | Narrow | md | * | Hour 1-12 | h | Numeric: minimum digits | 1, 12 | * | | hh | Numeric: 2 digits + zero padded | 01, 12 | * | Hour 0-23 | H | Numeric: minimum digits | 0, 23 | * | | HH | Numeric: 2 digits + zero padded | 00, 23 | * | Minute | m | Numeric: minimum digits | 8, 59 | * | | mm | Numeric: 2 digits + zero padded | 08, 59 | * | Second | s | Numeric: minimum digits | 0... 59 | * | | ss | Numeric: 2 digits + zero padded | 00... 59 | * | Fractional seconds | S | Numeric: 1 digit | 0... 9 | * | | SS | Numeric: 2 digits + zero padded | 00... 99 | * | | SSS | Numeric: 3 digits + zero padded (= milliseconds) | 000... 999 | * | Zone | z, zz & zzz | Short specific non location format (fallback to O) | GMT-8 | * | | zzzz | Long specific non location format (fallback to OOOO) | GMT-08:00 | * | | Z, ZZ & ZZZ | ISO8601 basic format | -0800 | * | | ZZZZ | Long localized GMT format | GMT-8:00 | * | | ZZZZZ | ISO8601 extended format + Z indicator for offset 0 (= XXXXX) | -08:00 | * | | O, OO & OOO | Short localized GMT format | GMT-8 | * | | OOOO | Long localized GMT format | GMT-08:00 | * * * ### Format examples * * These examples transform a date into various formats, * assuming that `dateObj` is a JavaScript `Date` object for * year: 2015, month: 6, day: 15, hour: 21, minute: 43, second: 11, * given in the local time for the `en-US` locale. * * ``` * {{ dateObj | date }} // output is 'Jun 15, 2015' * {{ dateObj | date:'medium' }} // output is 'Jun 15, 2015, 9:43:11 PM' * {{ dateObj | date:'shortTime' }} // output is '9:43 PM' * {{ dateObj | date:'mm:ss' }} // output is '43:11' * {{ dateObj | date:"MMM dd, yyyy 'at' hh:mm a" }} // output is 'Jun 15, 2015 at 09:43 PM' * ``` * * ### Usage example * * The following component uses a date pipe to display the current date in different formats. * * ``` * @Component({ * selector: 'date-pipe', * template: `
*

Today is {{today | date}}

*

Or if you prefer, {{today | date:'fullDate'}}

*

The time is {{today | date:'h:mm a z'}}

*
` * }) * // Get the current date and time as a date-time value. * export class DatePipeComponent { * today: number = Date.now(); * } * ``` * * @publicApi */ // clang-format on @Pipe({ name: 'date', standalone: true, }) export class DatePipe implements PipeTransform { constructor( @Inject(LOCALE_ID) private locale: string, @Inject(DATE_PIPE_DEFAULT_TIMEZONE) @Optional() private defaultTimezone?: string | null, @Inject(DATE_PIPE_DEFAULT_OPTIONS) @Optional() private defaultOptions?: DatePipeConfig | null, ) {} /** * @param value The date expression: a `Date` object, a number * (milliseconds since UTC epoch), or an ISO string (https://www.w3.org/TR/NOTE-datetime). * @param format The date/time components to include, using predefined options or a * custom format string. When not provided, the `DatePipe` looks for the value using the * `DATE_PIPE_DEFAULT_OPTIONS` injection token (and reads the `dateFormat` property). * If the token is not configured, the `mediumDate` is used as a value. * @param timezone A timezone offset (such as `'+0430'`), or a standard UTC/GMT, or continental US * timezone abbreviation. When not provided, the `DatePipe` looks for the value using the * `DATE_PIPE_DEFAULT_OPTIONS` injection token (and reads the `timezone` property). If the token * is not configured, the end-user's local system timezone is used as a value. * @param locale A locale code for the locale format rules to use. * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default. * See [Setting your app locale](guide/i18n-common-locale-id). * * @see {@link DATE_PIPE_DEFAULT_OPTIONS} * * @returns A date string in the desired format. */ transform( value: Date | string | number, format?: string, timezone?: string, locale?: string, ): string | null; transform(value: null | undefined, format?: string, timezone?: string, locale?: string): null; transform( value: Date | string | number | null | undefined, format?: string, timezone?: string, locale?: string, ): string | null; transform( value: Date | string | number | null | undefined, format?: string, timezone?: string, locale?: string, ): string | null { if (value == null || value === '' || value !== value) return null; try { const _format = format ?? this.defaultOptions?.dateFormat ?? DEFAULT_DATE_FORMAT; const _timezone = timezone ?? this.defaultOptions?.timezone ?? this.defaultTimezone ?? undefined; return formatDate(value, _format, locale || this.locale, _timezone); } catch (error) { throw invalidPipeArgumentError(DatePipe, (error as Error).message); } } }