From e900eacdb8a2382aa99f155167680b3398b022ab Mon Sep 17 00:00:00 2001 From: EinfachHans Date: Mon, 26 Jul 2021 09:55:32 +0200 Subject: [PATCH 1/8] feat(datetime): add TimeFormat prop closes #23661 --- angular/src/directives/proxies.ts | 4 +- core/api.txt | 1 + core/src/components.d.ts | 8 +++ core/src/components/datetime/datetime.tsx | 9 ++- core/src/components/datetime/readme.md | 1 + .../datetime/test/time-format/e2e.ts | 15 +++++ .../datetime/test/time-format/index.html | 58 +++++++++++++++++++ packages/vue/src/proxies.ts | 1 + 8 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 core/src/components/datetime/test/time-format/e2e.ts create mode 100644 core/src/components/datetime/test/time-format/index.html diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts index 47301060d43..1eeb8c21f47 100644 --- a/angular/src/directives/proxies.ts +++ b/angular/src/directives/proxies.ts @@ -244,8 +244,8 @@ export class IonContent { } export declare interface IonDatetime extends Components.IonDatetime { } -@ProxyCmp({ inputs: ["cancelText", "color", "dayValues", "disabled", "doneText", "hourValues", "locale", "max", "min", "minuteValues", "mode", "monthValues", "name", "presentation", "readonly", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "value", "yearValues"], "methods": ["confirm", "reset", "cancel"] }) -@Component({ selector: "ion-datetime", changeDetection: ChangeDetectionStrategy.OnPush, template: "", inputs: ["cancelText", "color", "dayValues", "disabled", "doneText", "hourValues", "locale", "max", "min", "minuteValues", "mode", "monthValues", "name", "presentation", "readonly", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "value", "yearValues"] }) +@ProxyCmp({ inputs: ["cancelText", "color", "dayValues", "disabled", "doneText", "hourValues", "locale", "max", "min", "minuteValues", "mode", "monthValues", "name", "presentation", "readonly", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "timeFormat", "value", "yearValues"], "methods": ["confirm", "reset", "cancel"] }) +@Component({ selector: "ion-datetime", changeDetection: ChangeDetectionStrategy.OnPush, template: "", inputs: ["cancelText", "color", "dayValues", "disabled", "doneText", "hourValues", "locale", "max", "min", "minuteValues", "mode", "monthValues", "name", "presentation", "readonly", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "timeFormat", "value", "yearValues"] }) export class IonDatetime { ionCancel!: EventEmitter; ionChange!: EventEmitter; diff --git a/core/api.txt b/core/api.txt index 62110ab2d81..457a4d2ab62 100644 --- a/core/api.txt +++ b/core/api.txt @@ -388,6 +388,7 @@ ion-datetime,prop,showDefaultButtons,boolean,false,false,false ion-datetime,prop,showDefaultTimeLabel,boolean,true,false,false ion-datetime,prop,showDefaultTitle,boolean,false,false,false ion-datetime,prop,size,"cover" | "fixed",'fixed',false,false +ion-datetime,prop,timeFormat,"12h" | "24h" | null | undefined,undefined,false,false ion-datetime,prop,value,null | string | undefined,undefined,false,false ion-datetime,prop,yearValues,number | number[] | string | undefined,undefined,false,false ion-datetime,method,cancel,cancel(closeOverlay?: boolean) => Promise diff --git a/core/src/components.d.ts b/core/src/components.d.ts index d50346b42d6..e14557c8078 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -788,6 +788,10 @@ export namespace Components { * If `cover`, the `ion-datetime` will expand to cover the full width of its container. If `fixed`, the `ion-datetime` will have a fixed width. */ "size": 'cover' | 'fixed'; + /** + * The time format of the `ion-datetime`. If no value is set, this is specified by the current locale. + */ + "timeFormat"?: '24h' | '12h' | null; /** * The value of the datetime as a valid ISO 8601 datetime string. */ @@ -4368,6 +4372,10 @@ declare namespace LocalJSX { * If `cover`, the `ion-datetime` will expand to cover the full width of its container. If `fixed`, the `ion-datetime` will have a fixed width. */ "size"?: 'cover' | 'fixed'; + /** + * The time format of the `ion-datetime`. If no value is set, this is specified by the current locale. + */ + "timeFormat"?: '24h' | '12h' | null; /** * The value of the datetime as a valid ISO 8601 datetime string. */ diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index 51efb4ef5ae..433b505cbf7 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -318,6 +318,12 @@ export class Datetime implements ComponentInterface { */ @Prop() showDefaultTimeLabel = true; + /** + * The time format of the `ion-datetime`. If no value is set, this is + * specified by the current locale. + */ + @Prop() timeFormat?: '24h' | '12h' | null; + /** * If `cover`, the `ion-datetime` will expand to cover the full width of its container. * If `fixed`, the `ion-datetime` will have a fixed width. @@ -1397,7 +1403,8 @@ export class Datetime implements ComponentInterface { * should just be the default segment. */ private renderTime(mode: Mode) { - const use24Hour = is24Hour(this.locale); + const { timeFormat } = this; + const use24Hour = timeFormat != null ? timeFormat === '24h' : is24Hour(this.locale); const { ampm } = this.workingParts; const { hours, minutes, am, pm } = generateTime(this.locale, this.workingParts, this.minParts, this.maxParts, this.parsedHourValues, this.parsedMinuteValues); return ( diff --git a/core/src/components/datetime/readme.md b/core/src/components/datetime/readme.md index a3c261c9be5..58676e6ae52 100644 --- a/core/src/components/datetime/readme.md +++ b/core/src/components/datetime/readme.md @@ -583,6 +583,7 @@ export class DatetimeExample { | `showDefaultTimeLabel` | `show-default-time-label` | If `true`, the default "Time" label will be rendered for the time selector of the `ion-datetime` component. Developers can also use the `time-label` slot if they want to customize this label. If a custom label is set in the `time-label` slot then the default label will not be rendered. | `boolean` | `true` | | `showDefaultTitle` | `show-default-title` | If `true`, a header will be shown above the calendar picker. On `ios` mode this will include the slotted title, and on `md` mode this will include the slotted title and the selected date. | `boolean` | `false` | | `size` | `size` | If `cover`, the `ion-datetime` will expand to cover the full width of its container. If `fixed`, the `ion-datetime` will have a fixed width. | `"cover" \| "fixed"` | `'fixed'` | +| `timeFormat` | `time-format` | The time format of the `ion-datetime`. If no value is set, this is specified by the current locale. | `"12h" \| "24h" \| null \| undefined` | `undefined` | | `value` | `value` | The value of the datetime as a valid ISO 8601 datetime string. | `null \| string \| undefined` | `undefined` | | `yearValues` | `year-values` | Values used to create the list of selectable years. By default the year values range between the `min` and `max` datetime inputs. However, to control exactly which years to display, the `yearValues` input can take a number, an array of numbers, or string of comma separated numbers. For example, to show upcoming and recent leap years, then this input's value would be `yearValues="2024,2020,2016,2012,2008"`. | `number \| number[] \| string \| undefined` | `undefined` | diff --git a/core/src/components/datetime/test/time-format/e2e.ts b/core/src/components/datetime/test/time-format/e2e.ts new file mode 100644 index 00000000000..bf7c4974183 --- /dev/null +++ b/core/src/components/datetime/test/time-format/e2e.ts @@ -0,0 +1,15 @@ +import { newE2EPage } from '@stencil/core/testing'; + +test('time-format', async () => { + const page = await newE2EPage({ + url: '/src/components/datetime/test/time-format?ionic:_testing=true' + }); + + const screenshotCompares = []; + + screenshotCompares.push(await page.compareScreenshot()); + + for (const screenshotCompare of screenshotCompares) { + expect(screenshotCompare).toMatchScreenshot(); + } +}); diff --git a/core/src/components/datetime/test/time-format/index.html b/core/src/components/datetime/test/time-format/index.html new file mode 100644 index 00000000000..99e7cb8b81e --- /dev/null +++ b/core/src/components/datetime/test/time-format/index.html @@ -0,0 +1,58 @@ + + + + + Datetime - Time format + + + + + + + + + + + + Datetime - Time format + + + +
+
+

Default Time format

+ +
+
+

24h Time format

+ +
+
+

12h Time format

+ +
+
+
+
+ + diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index 696e1e50f60..34b7c373d46 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -285,6 +285,7 @@ export const IonDatetime = /*@__PURE__*/ defineContainer('ion-d 'showDefaultTitle', 'showDefaultButtons', 'showDefaultTimeLabel', + 'timeFormat', 'size', 'ionCancel', 'ionChange', From 59f50bd2b58be612745b8a595b85ebef771ef29e Mon Sep 17 00:00:00 2001 From: EinfachHans Date: Mon, 26 Jul 2021 21:18:37 +0200 Subject: [PATCH 2/8] timeFormat to hourCycle --- angular/src/directives/proxies.ts | 4 +- core/api.txt | 2 +- core/src/components.d.ts | 16 ++++---- core/src/components/datetime/datetime.tsx | 8 ++-- core/src/components/datetime/readme.md | 2 +- .../components/datetime/test/helpers.spec.ts | 6 +++ core/src/components/datetime/utils/helpers.ts | 39 +++++++++++++++++-- packages/vue/src/proxies.ts | 2 +- 8 files changed, 59 insertions(+), 20 deletions(-) diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts index 1eeb8c21f47..b7268898b60 100644 --- a/angular/src/directives/proxies.ts +++ b/angular/src/directives/proxies.ts @@ -244,8 +244,8 @@ export class IonContent { } export declare interface IonDatetime extends Components.IonDatetime { } -@ProxyCmp({ inputs: ["cancelText", "color", "dayValues", "disabled", "doneText", "hourValues", "locale", "max", "min", "minuteValues", "mode", "monthValues", "name", "presentation", "readonly", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "timeFormat", "value", "yearValues"], "methods": ["confirm", "reset", "cancel"] }) -@Component({ selector: "ion-datetime", changeDetection: ChangeDetectionStrategy.OnPush, template: "", inputs: ["cancelText", "color", "dayValues", "disabled", "doneText", "hourValues", "locale", "max", "min", "minuteValues", "mode", "monthValues", "name", "presentation", "readonly", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "timeFormat", "value", "yearValues"] }) +@ProxyCmp({ inputs: ["cancelText", "color", "dayValues", "disabled", "doneText", "hourCycle", "hourValues", "locale", "max", "min", "minuteValues", "mode", "monthValues", "name", "presentation", "readonly", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "value", "yearValues"], "methods": ["confirm", "reset", "cancel"] }) +@Component({ selector: "ion-datetime", changeDetection: ChangeDetectionStrategy.OnPush, template: "", inputs: ["cancelText", "color", "dayValues", "disabled", "doneText", "hourCycle", "hourValues", "locale", "max", "min", "minuteValues", "mode", "monthValues", "name", "presentation", "readonly", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "value", "yearValues"] }) export class IonDatetime { ionCancel!: EventEmitter; ionChange!: EventEmitter; diff --git a/core/api.txt b/core/api.txt index 457a4d2ab62..99a7af12e43 100644 --- a/core/api.txt +++ b/core/api.txt @@ -374,6 +374,7 @@ ion-datetime,prop,color,string | undefined,'primary',false,false ion-datetime,prop,dayValues,number | number[] | string | undefined,undefined,false,false ion-datetime,prop,disabled,boolean,false,false,false ion-datetime,prop,doneText,string,'Done',false,false +ion-datetime,prop,hourCycle,"h12" | "h23" | undefined,undefined,false,false ion-datetime,prop,hourValues,number | number[] | string | undefined,undefined,false,false ion-datetime,prop,locale,string,'default',false,false ion-datetime,prop,max,string | undefined,undefined,false,false @@ -388,7 +389,6 @@ ion-datetime,prop,showDefaultButtons,boolean,false,false,false ion-datetime,prop,showDefaultTimeLabel,boolean,true,false,false ion-datetime,prop,showDefaultTitle,boolean,false,false,false ion-datetime,prop,size,"cover" | "fixed",'fixed',false,false -ion-datetime,prop,timeFormat,"12h" | "24h" | null | undefined,undefined,false,false ion-datetime,prop,value,null | string | undefined,undefined,false,false ion-datetime,prop,yearValues,number | number[] | string | undefined,undefined,false,false ion-datetime,method,cancel,cancel(closeOverlay?: boolean) => Promise diff --git a/core/src/components.d.ts b/core/src/components.d.ts index e14557c8078..999cc24397e 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -728,6 +728,10 @@ export namespace Components { * The text to display on the picker's "Done" button. */ "doneText": string; + /** + * The hour cycle of the `ion-datetime`. If no value is set, this is specified by the current locale. + */ + "hourCycle"?: 'h23' | 'h12'; /** * Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers. */ @@ -788,10 +792,6 @@ export namespace Components { * If `cover`, the `ion-datetime` will expand to cover the full width of its container. If `fixed`, the `ion-datetime` will have a fixed width. */ "size": 'cover' | 'fixed'; - /** - * The time format of the `ion-datetime`. If no value is set, this is specified by the current locale. - */ - "timeFormat"?: '24h' | '12h' | null; /** * The value of the datetime as a valid ISO 8601 datetime string. */ @@ -4296,6 +4296,10 @@ declare namespace LocalJSX { * The text to display on the picker's "Done" button. */ "doneText"?: string; + /** + * The hour cycle of the `ion-datetime`. If no value is set, this is specified by the current locale. + */ + "hourCycle"?: 'h23' | 'h12'; /** * Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers. */ @@ -4372,10 +4376,6 @@ declare namespace LocalJSX { * If `cover`, the `ion-datetime` will expand to cover the full width of its container. If `fixed`, the `ion-datetime` will have a fixed width. */ "size"?: 'cover' | 'fixed'; - /** - * The time format of the `ion-datetime`. If no value is set, this is specified by the current locale. - */ - "timeFormat"?: '24h' | '12h' | null; /** * The value of the datetime as a valid ISO 8601 datetime string. */ diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index 433b505cbf7..60993992362 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -319,10 +319,10 @@ export class Datetime implements ComponentInterface { @Prop() showDefaultTimeLabel = true; /** - * The time format of the `ion-datetime`. If no value is set, this is + * The hour cycle of the `ion-datetime`. If no value is set, this is * specified by the current locale. */ - @Prop() timeFormat?: '24h' | '12h' | null; + @Prop() hourCycle?: 'h23' | 'h12'; /** * If `cover`, the `ion-datetime` will expand to cover the full width of its container. @@ -1403,8 +1403,8 @@ export class Datetime implements ComponentInterface { * should just be the default segment. */ private renderTime(mode: Mode) { - const { timeFormat } = this; - const use24Hour = timeFormat != null ? timeFormat === '24h' : is24Hour(this.locale); + const { hourCycle } = this; + const use24Hour = is24Hour(this.locale, hourCycle); const { ampm } = this.workingParts; const { hours, minutes, am, pm } = generateTime(this.locale, this.workingParts, this.minParts, this.maxParts, this.parsedHourValues, this.parsedMinuteValues); return ( diff --git a/core/src/components/datetime/readme.md b/core/src/components/datetime/readme.md index 58676e6ae52..174ba7dcf4a 100644 --- a/core/src/components/datetime/readme.md +++ b/core/src/components/datetime/readme.md @@ -569,6 +569,7 @@ export class DatetimeExample { | `dayValues` | `day-values` | Values used to create the list of selectable days. By default every day is shown for the given month. However, to control exactly which days of the month to display, the `dayValues` input can take a number, an array of numbers, or a string of comma separated numbers. Note that even if the array days have an invalid number for the selected month, like `31` in February, it will correctly not show days which are not valid for the selected month. | `number \| number[] \| string \| undefined` | `undefined` | | `disabled` | `disabled` | If `true`, the user cannot interact with the datetime. | `boolean` | `false` | | `doneText` | `done-text` | The text to display on the picker's "Done" button. | `string` | `'Done'` | +| `hourCycle` | `hour-cycle` | The hour cycle of the `ion-datetime`. If no value is set, this is specified by the current locale. | `"h12" \| "h23" \| undefined` | `undefined` | | `hourValues` | `hour-values` | Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers. | `number \| number[] \| string \| undefined` | `undefined` | | `locale` | `locale` | The locale to use for `ion-datetime`. This impacts month and day name formatting. The `'default'` value refers to the default locale set by your device. | `string` | `'default'` | | `max` | `max` | The maximum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the maximum could just be the year, such as `1994`. Defaults to the end of this year. | `string \| undefined` | `undefined` | @@ -583,7 +584,6 @@ export class DatetimeExample { | `showDefaultTimeLabel` | `show-default-time-label` | If `true`, the default "Time" label will be rendered for the time selector of the `ion-datetime` component. Developers can also use the `time-label` slot if they want to customize this label. If a custom label is set in the `time-label` slot then the default label will not be rendered. | `boolean` | `true` | | `showDefaultTitle` | `show-default-title` | If `true`, a header will be shown above the calendar picker. On `ios` mode this will include the slotted title, and on `md` mode this will include the slotted title and the selected date. | `boolean` | `false` | | `size` | `size` | If `cover`, the `ion-datetime` will expand to cover the full width of its container. If `fixed`, the `ion-datetime` will have a fixed width. | `"cover" \| "fixed"` | `'fixed'` | -| `timeFormat` | `time-format` | The time format of the `ion-datetime`. If no value is set, this is specified by the current locale. | `"12h" \| "24h" \| null \| undefined` | `undefined` | | `value` | `value` | The value of the datetime as a valid ISO 8601 datetime string. | `null \| string \| undefined` | `undefined` | | `yearValues` | `year-values` | Values used to create the list of selectable years. By default the year values range between the `min` and `max` datetime inputs. However, to control exactly which years to display, the `yearValues` input can take a number, an array of numbers, or string of comma separated numbers. For example, to show upcoming and recent leap years, then this input's value would be `yearValues="2024,2020,2016,2012,2008"`. | `number \| number[] \| string \| undefined` | `undefined` | diff --git a/core/src/components/datetime/test/helpers.spec.ts b/core/src/components/datetime/test/helpers.spec.ts index 18e81eabfa7..29e6344c96c 100644 --- a/core/src/components/datetime/test/helpers.spec.ts +++ b/core/src/components/datetime/test/helpers.spec.ts @@ -42,6 +42,12 @@ describe('isLeapYear()', () => { describe('is24Hour()', () => { it('should return true if the locale uses 24 hour time', () => { expect(is24Hour('en-US')).toBe(false); + expect(is24Hour('en-US', 'h23')).toBe(true); + expect(is24Hour('en-US', 'h12')).toBe(false); + expect(is24Hour('en-US-u-hc-h23')).toBe(true); expect(is24Hour('en-GB')).toBe(true); + expect(is24Hour('en-GB', 'h23')).toBe(true); + expect(is24Hour('en-GB', 'h12')).toBe(false); + expect(is24Hour('en-GB-u-hc-h12')).toBe(false); }) }) diff --git a/core/src/components/datetime/utils/helpers.ts b/core/src/components/datetime/utils/helpers.ts index 0381306a003..a0abffdd5ed 100644 --- a/core/src/components/datetime/utils/helpers.ts +++ b/core/src/components/datetime/utils/helpers.ts @@ -1,3 +1,11 @@ +/** + * Typescript 4.x does not recognize hourCycle as a valid option. + * See https://github.com/microsoft/TypeScript/issues/34399. + */ +interface DatetimeFormatOptions extends Intl.ResolvedDateTimeFormatOptions { + hourCycle?: 'h11' | 'h12' | 'h23' | 'h24' +} + /** * Determines if given year is a * leap year. Returns `true` if year @@ -8,10 +16,35 @@ export const isLeapYear = (year: number) => { return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0); } -export const is24Hour = (locale: string) => { +export const is24Hour = (locale: string, hourCycle?: 'h23' | 'h12') => { + /** + * If developer has explicitly enabled h23 time + * then return early and do not look at the system default. + */ + if (hourCycle !== undefined) { + return hourCycle === 'h23'; + } + + /** + * If hourCycle was not specified, check the locale + * that is set on the user's device. We first check the + * Intl.DateTimeFormat hourCycle option as developers can encode this + * option into the locale string. Example: `en-US-u-hc-h23` + */ + const formatted = new Intl.DateTimeFormat(locale, { hour: 'numeric' }); + const options = formatted.resolvedOptions() as DatetimeFormatOptions; + if (options.hourCycle !== undefined) { + return options.hourCycle === 'h23'; + } + + /** + * If hourCycle is not specified (either through lack + * of browser support or locale information) then fall + * back to this slower hourCycle check. + */ const date = new Date('5/18/2021 00:00'); - const formatted = new Intl.DateTimeFormat(locale, { hour: 'numeric' }).formatToParts(date); - const hour = formatted.find(p => p.type === 'hour'); + const parts = formatted.formatToParts(date); + const hour = parts.find(p => p.type === 'hour'); if (!hour) { throw new Error('Hour value not found from DateTimeFormat'); diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index 34b7c373d46..302c2e54e8d 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -285,7 +285,7 @@ export const IonDatetime = /*@__PURE__*/ defineContainer('ion-d 'showDefaultTitle', 'showDefaultButtons', 'showDefaultTimeLabel', - 'timeFormat', + 'hourCycle', 'size', 'ionCancel', 'ionChange', From 8f0ebfc6e4ed7ab0259aa1ab5442eb12bef5ed71 Mon Sep 17 00:00:00 2001 From: EinfachHans Date: Mon, 26 Jul 2021 21:53:27 +0200 Subject: [PATCH 3/8] tests adjusted --- .../test/{time-format => hour-cycle}/e2e.ts | 4 ++-- .../test/{time-format => hour-cycle}/index.html | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) rename core/src/components/datetime/test/{time-format => hour-cycle}/e2e.ts (73%) rename core/src/components/datetime/test/{time-format => hour-cycle}/index.html (80%) diff --git a/core/src/components/datetime/test/time-format/e2e.ts b/core/src/components/datetime/test/hour-cycle/e2e.ts similarity index 73% rename from core/src/components/datetime/test/time-format/e2e.ts rename to core/src/components/datetime/test/hour-cycle/e2e.ts index bf7c4974183..74ec220816c 100644 --- a/core/src/components/datetime/test/time-format/e2e.ts +++ b/core/src/components/datetime/test/hour-cycle/e2e.ts @@ -1,8 +1,8 @@ import { newE2EPage } from '@stencil/core/testing'; -test('time-format', async () => { +test('hour-cycle', async () => { const page = await newE2EPage({ - url: '/src/components/datetime/test/time-format?ionic:_testing=true' + url: '/src/components/datetime/test/hour-cycle?ionic:_testing=true' }); const screenshotCompares = []; diff --git a/core/src/components/datetime/test/time-format/index.html b/core/src/components/datetime/test/hour-cycle/index.html similarity index 80% rename from core/src/components/datetime/test/time-format/index.html rename to core/src/components/datetime/test/hour-cycle/index.html index 99e7cb8b81e..b533a46b53a 100644 --- a/core/src/components/datetime/test/time-format/index.html +++ b/core/src/components/datetime/test/hour-cycle/index.html @@ -2,7 +2,7 @@ - Datetime - Time format + Datetime - Hour cycle @@ -34,22 +34,22 @@ - Datetime - Time format + Datetime - Hour Cycle
-

Default Time format

+

Default Hour cycle

-

24h Time format

- +

h23 Hour cycle

+
-

12h Time format

- +

h12 Hour cycle

+
From c9f9ba2abefb59676599e6c987df890a13918fdd Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 9 Aug 2021 15:25:43 -0400 Subject: [PATCH 4/8] fix: avoid extra is24Hour check --- core/src/components/datetime/datetime.tsx | 2 +- .../src/components/datetime/test/data.spec.ts | 26 +++++++------------ core/src/components/datetime/utils/data.ts | 9 +++---- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index 60993992362..cbb2b4455c8 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -1406,7 +1406,7 @@ export class Datetime implements ComponentInterface { const { hourCycle } = this; const use24Hour = is24Hour(this.locale, hourCycle); const { ampm } = this.workingParts; - const { hours, minutes, am, pm } = generateTime(this.locale, this.workingParts, this.minParts, this.maxParts, this.parsedHourValues, this.parsedMinuteValues); + const { hours, minutes, am, pm } = generateTime(this.workingParts, use24Hour, this.minParts, this.maxParts, this.parsedHourValues, this.parsedMinuteValues); return (
diff --git a/core/src/components/datetime/test/data.spec.ts b/core/src/components/datetime/test/data.spec.ts index 03fdcca961b..71d831fa38d 100644 --- a/core/src/components/datetime/test/data.spec.ts +++ b/core/src/components/datetime/test/data.spec.ts @@ -41,11 +41,10 @@ describe('generateTime()', () => { hour: 5, minute: 43 } - const { hours, minutes, use24Hour } = generateTime('en-US', today); + const { hours, minutes } = generateTime(today); expect(hours.length).toEqual(12); expect(minutes.length).toEqual(60); - expect(use24Hour).toEqual(false); }); it('should filter according to min', () => { const today = { @@ -62,11 +61,10 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes, use24Hour } = generateTime('en-US', today, min); + const { hours, minutes } = generateTime(today, false, min); expect(hours.length).toEqual(11); expect(minutes.length).toEqual(20); - expect(use24Hour).toEqual(false); }) it('should not filter according to min if not on reference day', () => { const today = { @@ -83,11 +81,10 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes, use24Hour } = generateTime('en-US', today, min); + const { hours, minutes } = generateTime(today, false, min); expect(hours.length).toEqual(12); expect(minutes.length).toEqual(60); - expect(use24Hour).toEqual(false); }) it('should filter according to max', () => { const today = { @@ -104,11 +101,10 @@ describe('generateTime()', () => { hour: 7, minute: 44 } - const { hours, minutes, use24Hour } = generateTime('en-US', today, undefined, max); + const { hours, minutes } = generateTime(today, false, undefined, max); expect(hours.length).toEqual(7); expect(minutes.length).toEqual(45); - expect(use24Hour).toEqual(false); }) it('should not filter according to min if not on reference day', () => { const today = { @@ -125,11 +121,10 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes, use24Hour } = generateTime('en-US', today, undefined, max); + const { hours, minutes } = generateTime(today, false, undefined, max); expect(hours.length).toEqual(12); expect(minutes.length).toEqual(60); - expect(use24Hour).toEqual(false); }) it('should return no values for a day less than the min', () => { const today = { @@ -146,11 +141,10 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes, use24Hour } = generateTime('en-US', today, min); + const { hours, minutes } = generateTime(today, false, min); expect(hours.length).toEqual(0); expect(minutes.length).toEqual(0); - expect(use24Hour).toEqual(false); }) it('should return no values for a day greater than the max', () => { const today = { @@ -167,11 +161,10 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes, use24Hour } = generateTime('en-US', today, undefined, max); + const { hours, minutes } = generateTime(today, false, undefined, max); expect(hours.length).toEqual(0); expect(minutes.length).toEqual(0); - expect(use24Hour).toEqual(false); }) it('should allow all hours and minutes if not set in min/max', () => { const today = { @@ -192,11 +185,10 @@ describe('generateTime()', () => { year: 2021 } - const { hours, minutes, use24Hour } = generateTime('en-US', today, min, max); + const { hours, minutes } = generateTime(today, false, min, max); expect(hours.length).toEqual(12); expect(minutes.length).toEqual(60); - expect(use24Hour).toEqual(false); }) it('should allow certain hours and minutes based on minuteValues and hourValues', () => { const today = { @@ -207,7 +199,7 @@ describe('generateTime()', () => { minute: 43 } - const { hours, minutes, use24Hour } = generateTime('en-US', today, undefined, undefined, [1,2,3], [10,15,20]); + const { hours, minutes, use24Hour } = generateTime(today, false, undefined, undefined, [1,2,3], [10,15,20]); expect(hours).toStrictEqual([1,2,3]); expect(minutes).toStrictEqual([10,15,20]); diff --git a/core/src/components/datetime/utils/data.ts b/core/src/components/datetime/utils/data.ts index ce5ab4520f3..194bc3adde0 100644 --- a/core/src/components/datetime/utils/data.ts +++ b/core/src/components/datetime/utils/data.ts @@ -7,8 +7,7 @@ import { isSameDay } from './comparison'; import { - getNumDaysInMonth, - is24Hour + getNumDaysInMonth } from './helpers'; import { getNextMonth, @@ -109,14 +108,13 @@ export const getDaysOfMonth = (month: number, year: number) => { * hour and minute values according to the bounds and locale. */ export const generateTime = ( - locale: string, refParts: DatetimeParts, + use24Hour: boolean = false, minParts?: DatetimeParts, maxParts?: DatetimeParts, hourValues?: number[], minuteValues?: number[] ) => { - const use24Hour = is24Hour(locale); let processedHours = use24Hour ? hour24 : hour12; let processedMinutes = minutes; let isAMAllowed = true; @@ -202,8 +200,7 @@ export const generateTime = ( hours: processedHours, minutes: processedMinutes, am: isAMAllowed, - pm: isPMAllowed, - use24Hour + pm: isPMAllowed } } From d7a0e956174a536118d232e984edc19beaedf2c7 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 9 Aug 2021 15:29:08 -0400 Subject: [PATCH 5/8] fix: add base support for additional hour cycle types --- core/src/components/datetime/datetime.tsx | 2 +- core/src/components/datetime/test/data.spec.ts | 14 +++++++------- core/src/components/datetime/utils/data.ts | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx index cbb2b4455c8..5f0861cde90 100644 --- a/core/src/components/datetime/datetime.tsx +++ b/core/src/components/datetime/datetime.tsx @@ -1406,7 +1406,7 @@ export class Datetime implements ComponentInterface { const { hourCycle } = this; const use24Hour = is24Hour(this.locale, hourCycle); const { ampm } = this.workingParts; - const { hours, minutes, am, pm } = generateTime(this.workingParts, use24Hour, this.minParts, this.maxParts, this.parsedHourValues, this.parsedMinuteValues); + const { hours, minutes, am, pm } = generateTime(this.workingParts, use24Hour ? 'h23' : 'h12', this.minParts, this.maxParts, this.parsedHourValues, this.parsedMinuteValues); return (
diff --git a/core/src/components/datetime/test/data.spec.ts b/core/src/components/datetime/test/data.spec.ts index 71d831fa38d..23f1c903f8a 100644 --- a/core/src/components/datetime/test/data.spec.ts +++ b/core/src/components/datetime/test/data.spec.ts @@ -81,7 +81,7 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes } = generateTime(today, false, min); + const { hours, minutes } = generateTime(today, 'h12', min); expect(hours.length).toEqual(12); expect(minutes.length).toEqual(60); @@ -101,7 +101,7 @@ describe('generateTime()', () => { hour: 7, minute: 44 } - const { hours, minutes } = generateTime(today, false, undefined, max); + const { hours, minutes } = generateTime(today, 'h12', undefined, max); expect(hours.length).toEqual(7); expect(minutes.length).toEqual(45); @@ -121,7 +121,7 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes } = generateTime(today, false, undefined, max); + const { hours, minutes } = generateTime(today, 'h12', undefined, max); expect(hours.length).toEqual(12); expect(minutes.length).toEqual(60); @@ -141,7 +141,7 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes } = generateTime(today, false, min); + const { hours, minutes } = generateTime(today, 'h12', min); expect(hours.length).toEqual(0); expect(minutes.length).toEqual(0); @@ -161,7 +161,7 @@ describe('generateTime()', () => { hour: 2, minute: 40 } - const { hours, minutes } = generateTime(today, false, undefined, max); + const { hours, minutes } = generateTime(today, 'h12', undefined, max); expect(hours.length).toEqual(0); expect(minutes.length).toEqual(0); @@ -185,7 +185,7 @@ describe('generateTime()', () => { year: 2021 } - const { hours, minutes } = generateTime(today, false, min, max); + const { hours, minutes } = generateTime(today, 'h12', min, max); expect(hours.length).toEqual(12); expect(minutes.length).toEqual(60); @@ -199,7 +199,7 @@ describe('generateTime()', () => { minute: 43 } - const { hours, minutes, use24Hour } = generateTime(today, false, undefined, undefined, [1,2,3], [10,15,20]); + const { hours, minutes, use24Hour } = generateTime(today, 'h12', undefined, undefined, [1,2,3], [10,15,20]); expect(hours).toStrictEqual([1,2,3]); expect(minutes).toStrictEqual([10,15,20]); diff --git a/core/src/components/datetime/utils/data.ts b/core/src/components/datetime/utils/data.ts index 194bc3adde0..bce2d0a7c00 100644 --- a/core/src/components/datetime/utils/data.ts +++ b/core/src/components/datetime/utils/data.ts @@ -42,7 +42,7 @@ export const getToday = () => { const minutes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]; const hour12 = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; -const hour24 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]; +const hour23 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]; /** * Given a locale and a mode, @@ -109,13 +109,13 @@ export const getDaysOfMonth = (month: number, year: number) => { */ export const generateTime = ( refParts: DatetimeParts, - use24Hour: boolean = false, + hourCycle: 'h12' | 'h23' = 'h12', minParts?: DatetimeParts, maxParts?: DatetimeParts, hourValues?: number[], minuteValues?: number[] ) => { - let processedHours = use24Hour ? hour24 : hour12; + let processedHours = hourCycle === 'h23' ? hour23 : hour12; let processedMinutes = minutes; let isAMAllowed = true; let isPMAllowed = true; From c0230a9aae6ee71525cda91ad52758c7e07aadd6 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 9 Aug 2021 15:48:24 -0400 Subject: [PATCH 6/8] docs: add hourCycle usage --- core/src/components/datetime/readme.md | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/core/src/components/datetime/readme.md b/core/src/components/datetime/readme.md index 174ba7dcf4a..d6bb2f7dddb 100644 --- a/core/src/components/datetime/readme.md +++ b/core/src/components/datetime/readme.md @@ -78,6 +78,39 @@ For instances where you need a specific locale, you can use the `locale` propert ``` +## Controlling the Hour Cycle + +By default, `ion-datetime` will use the hour cycle that is specified by the `locale` property. For example, if `locale` is set to `en-US`, then `ion-datetime` will use a 12 hour cycle. However, there may be scenarios where you need to have more control over which hour cycle is used. This is where the `hour-cycle` property can help. The `hour-cycle` property can be used to override whatever hour cycle is set by the locale: + +```html + +``` + +In the example above, `ion-datetime` will use a 12 hour cycle even though the local is `en-GB` which uses a 24 hour cycle by default. + +`ion-datetime` also supports [locale extension tags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale). These tags let you encode information about the locale in the locale string itself. + +For example, if you wanted to use a 12 hour cycle with the `en-GB` locale, you could alternatively do: + +```html + +``` + +Developers may prefer to use the extension tag approach if they are using the [Intl.Locale](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale) API in their app. + +There are 4 primary hour cycle types: + +| Hour cycle type | Description | +| --------------- | ----------- | +| `'h12` | Hour system using 1–12; corresponds to 'h' in patterns. The 12 hour clock, with midnight starting at 12:00 am. | +| `'h23'` | Hour system using 0–23; corresponds to 'H' in patterns. The 24 hour clock, with midnight starting at 0:00. | +| `'h11'` | Hour system using 0–11; corresponds to 'K' in patterns. The 12 hour clock, with midnight starting at 0:00 am. | +| `'h24'` | Hour system using 1–24; corresponds to 'k' in pattern. The 24 hour clock, with midnight starting at 24:00. | + +> Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle + +`ion-datetime` currently supports the `'h12'` and `'h23'` hour cycle types. Interested in seeing support for `'h11'` and `'h24'` added to `ion-datetime`? [Let us know!](https://github.com/ionic-team/ionic-framework/issues/23750) + ## Parsing Dates When `ionChange` is emitted, we provide an ISO-8601 string in the event payload. From there, it is the developer's responsibility to format it as they see fit. We recommend using a library like [date-fns](https://date-fns.org) to format their dates properly. From 73211e59a8dac16c63c402cef397325f6206a5f9 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 9 Aug 2021 15:56:29 -0400 Subject: [PATCH 7/8] docs: update usage examples --- core/src/components/datetime/readme.md | 15 +++++++++++++++ core/src/components/datetime/usage/angular.md | 3 +++ core/src/components/datetime/usage/javascript.md | 3 +++ core/src/components/datetime/usage/react.md | 3 +++ core/src/components/datetime/usage/stencil.md | 3 +++ core/src/components/datetime/usage/vue.md | 3 +++ 6 files changed, 30 insertions(+) diff --git a/core/src/components/datetime/readme.md b/core/src/components/datetime/readme.md index d6bb2f7dddb..5f52f06990d 100644 --- a/core/src/components/datetime/readme.md +++ b/core/src/components/datetime/readme.md @@ -209,6 +209,9 @@ dates in JavaScript. + + +
My Custom Title
@@ -291,6 +294,9 @@ export class MyComponent { + + +
My Custom Title
@@ -385,6 +391,9 @@ export const DateTimeExamples: React.FC = () => { {/* Full width size */} + {/* Custom Hour Cycle */} + + {/* Custom title */}
My Custom Title
@@ -469,6 +478,9 @@ export class DatetimeExample { {/* Full width size */} , + {/* Custom Hour Cycle */} + , + {/* Custom title */}
My Custom Title
@@ -529,6 +541,9 @@ export class DatetimeExample { + + +
My Custom Title
diff --git a/core/src/components/datetime/usage/angular.md b/core/src/components/datetime/usage/angular.md index d99376256e6..97375206d72 100644 --- a/core/src/components/datetime/usage/angular.md +++ b/core/src/components/datetime/usage/angular.md @@ -29,6 +29,9 @@ + + +
My Custom Title
diff --git a/core/src/components/datetime/usage/javascript.md b/core/src/components/datetime/usage/javascript.md index bb5c6cc18f4..8b40cede0ae 100644 --- a/core/src/components/datetime/usage/javascript.md +++ b/core/src/components/datetime/usage/javascript.md @@ -29,6 +29,9 @@ + + +
My Custom Title
diff --git a/core/src/components/datetime/usage/react.md b/core/src/components/datetime/usage/react.md index d092d2b5164..dda79ca4e57 100644 --- a/core/src/components/datetime/usage/react.md +++ b/core/src/components/datetime/usage/react.md @@ -56,6 +56,9 @@ export const DateTimeExamples: React.FC = () => { {/* Full width size */} + {/* Custom Hour Cycle */} + + {/* Custom title */}
My Custom Title
diff --git a/core/src/components/datetime/usage/stencil.md b/core/src/components/datetime/usage/stencil.md index 313799156f5..5a767caf670 100644 --- a/core/src/components/datetime/usage/stencil.md +++ b/core/src/components/datetime/usage/stencil.md @@ -54,6 +54,9 @@ export class DatetimeExample { {/* Full width size */} , + {/* Custom Hour Cycle */} + , + {/* Custom title */}
My Custom Title
diff --git a/core/src/components/datetime/usage/vue.md b/core/src/components/datetime/usage/vue.md index e49e9775303..43fefa05e67 100644 --- a/core/src/components/datetime/usage/vue.md +++ b/core/src/components/datetime/usage/vue.md @@ -30,6 +30,9 @@ + + +
My Custom Title
From 811f262424cde6145e8cb7280890a2f8fed74bb3 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 9 Aug 2021 16:15:26 -0400 Subject: [PATCH 8/8] docs: update docs --- core/src/components/datetime/readme.md | 38 +++++++++---------- .../datetime/test/hour-cycle/index.html | 6 ++- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/core/src/components/datetime/readme.md b/core/src/components/datetime/readme.md index 5f52f06990d..1b4ba44d433 100644 --- a/core/src/components/datetime/readme.md +++ b/core/src/components/datetime/readme.md @@ -78,17 +78,30 @@ For instances where you need a specific locale, you can use the `locale` propert ``` -## Controlling the Hour Cycle +### Controlling the Hour Cycle -By default, `ion-datetime` will use the hour cycle that is specified by the `locale` property. For example, if `locale` is set to `en-US`, then `ion-datetime` will use a 12 hour cycle. However, there may be scenarios where you need to have more control over which hour cycle is used. This is where the `hour-cycle` property can help. The `hour-cycle` property can be used to override whatever hour cycle is set by the locale: +`ion-datetime` will use the hour cycle that is specified by the `locale` property by default. For example, if `locale` is set to `en-US`, then `ion-datetime` will use a 12 hour cycle. + +There are 4 primary hour cycle types: + +| Hour cycle type | Description | +| --------------- | ------------------------------------------------------------ | +| `'h12` | Hour system using 1–12; corresponds to 'h' in patterns. The 12 hour clock, with midnight starting at 12:00 am. | +| `'h23'` | Hour system using 0–23; corresponds to 'H' in patterns. The 24 hour clock, with midnight starting at 0:00. | +| `'h11'` | Hour system using 0–11; corresponds to 'K' in patterns. The 12 hour clock, with midnight starting at 0:00 am. | +| `'h24'` | Hour system using 1–24; corresponds to 'k' in pattern. The 24 hour clock, with midnight starting at 24:00. | + +> Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle + +There may be scenarios where you need to have more control over which hour cycle is used. This is where the `hour-cycle` property can help. + +In the following example, we can use the `hour-cycle` property to force `ion-datetime` to use the 12 hour cycle even though the locale is `en-GB`, which uses a 24 hour cycle by default: ```html ``` -In the example above, `ion-datetime` will use a 12 hour cycle even though the local is `en-GB` which uses a 24 hour cycle by default. - -`ion-datetime` also supports [locale extension tags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale). These tags let you encode information about the locale in the locale string itself. +`ion-datetime` also supports [locale extension tags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale). These tags let you encode information about the locale in the locale string itself. Developers may prefer to use the extension tag approach if they are using the [Intl.Locale API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale) in their apps. For example, if you wanted to use a 12 hour cycle with the `en-GB` locale, you could alternatively do: @@ -96,21 +109,8 @@ For example, if you wanted to use a 12 hour cycle with the `en-GB` locale, you c ``` -Developers may prefer to use the extension tag approach if they are using the [Intl.Locale](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale) API in their app. - -There are 4 primary hour cycle types: - -| Hour cycle type | Description | -| --------------- | ----------- | -| `'h12` | Hour system using 1–12; corresponds to 'h' in patterns. The 12 hour clock, with midnight starting at 12:00 am. | -| `'h23'` | Hour system using 0–23; corresponds to 'H' in patterns. The 24 hour clock, with midnight starting at 0:00. | -| `'h11'` | Hour system using 0–11; corresponds to 'K' in patterns. The 12 hour clock, with midnight starting at 0:00 am. | -| `'h24'` | Hour system using 1–24; corresponds to 'k' in pattern. The 24 hour clock, with midnight starting at 24:00. | - -> Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle +`ion-datetime` currently supports the `h12` and `h23` hour cycle types. Interested in seeing support for `h11` and `h24` added to `ion-datetime`? [Let us know!](https://github.com/ionic-team/ionic-framework/issues/23750) -`ion-datetime` currently supports the `'h12'` and `'h23'` hour cycle types. Interested in seeing support for `'h11'` and `'h24'` added to `ion-datetime`? [Let us know!](https://github.com/ionic-team/ionic-framework/issues/23750) - ## Parsing Dates When `ionChange` is emitted, we provide an ISO-8601 string in the event payload. From there, it is the developer's responsibility to format it as they see fit. We recommend using a library like [date-fns](https://date-fns.org) to format their dates properly. diff --git a/core/src/components/datetime/test/hour-cycle/index.html b/core/src/components/datetime/test/hour-cycle/index.html index b533a46b53a..af7f1c12828 100644 --- a/core/src/components/datetime/test/hour-cycle/index.html +++ b/core/src/components/datetime/test/hour-cycle/index.html @@ -12,7 +12,7 @@ .grid { display: grid; grid-template-columns: repeat(3, minmax(250px, 1fr)); - grid-gap: 20px; + grid-gap: 60px 20px; } h2 { font-size: 12px; @@ -51,6 +51,10 @@

h23 Hour cycle

h12 Hour cycle

+
+

h23 Hour cycle (Extension Tag)

+ +