From 5b95149daaa2244540441a7e33c073e29adde581 Mon Sep 17 00:00:00 2001 From: Brandon Istenes Date: Fri, 4 Feb 2022 10:50:14 -0800 Subject: [PATCH] BREAKING: O3-1063: Change formatDate function signature. Adds support for wide format without year. (#305) --- packages/framework/esm-framework/docs/API.md | 57 ++++++------- .../esm-utils/src/omrs-dates.test.ts | 45 +++++----- .../framework/esm-utils/src/omrs-dates.ts | 84 +++++++++---------- 3 files changed, 91 insertions(+), 95 deletions(-) diff --git a/packages/framework/esm-framework/docs/API.md b/packages/framework/esm-framework/docs/API.md index ce6d1cfaf..318e33e3b 100644 --- a/packages/framework/esm-framework/docs/API.md +++ b/packages/framework/esm-framework/docs/API.md @@ -397,11 +397,11 @@ ___ ### FormatDateMode -Ƭ **FormatDateMode**: ``"standard"`` \| ``"no year"`` \| ``"no day"`` \| ``"wide"`` +Ƭ **FormatDateMode**: ``"standard"`` \| ``"wide"`` #### Defined in -[packages/framework/esm-utils/src/omrs-dates.ts:154](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L154) +[packages/framework/esm-utils/src/omrs-dates.ts:140](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L140) ___ @@ -413,11 +413,14 @@ ___ | Name | Type | Description | | :------ | :------ | :------ | +| `day` | `boolean` | Whether to include the day number | +| `mode` | [`FormatDateMode`](API.md#formatdatemode) | - `standard`: "03 Feb 2022" - `wide`: "03 — Feb — 2022" | | `time` | `boolean` \| ``"for today"`` | Whether the time should be included in the output always (`true`), never (`false`), or only when the input date is today (`for today`). | +| `year` | `boolean` | Whether to include the year | #### Defined in -[packages/framework/esm-utils/src/omrs-dates.ts:156](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L156) +[packages/framework/esm-utils/src/omrs-dates.ts:142](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L142) ___ @@ -1750,31 +1753,29 @@ ___ ### formatDate -▸ **formatDate**(`date`, `mode?`, `options?`): `string` +▸ **formatDate**(`date`, `options?`): `string` Formats the input date according to the current locale and the -given format mode. +given options. -- `standard`: "13 Dec 2021" -- `no year`: "13 Dec" -- `no day`: "Dec 2021" -- `wide`: "13 — Dec — 2021" +Default options: + - mode: "standard", + - time: "for today", + - day: true, + - year: true -Regardless of the mode, if the date is today, then "Today" is produced -(in the locale language). +If the date is today then "Today" is produced (in the locale language). -Can be used to format a date with time, also, by providing `options`. -By default, the time is included only when the input date is today. -The time is appended with a comma and a space. This agrees with the -output of `Date.prototype.toLocaleString` for *most* locales. +When time is included, it is appended with a comma and a space. This +agrees with the output of `Date.prototype.toLocaleString` for *most* +locales. #### Parameters -| Name | Type | Default value | -| :------ | :------ | :------ | -| `date` | `Date` | `undefined` | -| `mode` | [`FormatDateMode`](API.md#formatdatemode) | `"standard"` | -| `options` | [`FormatDateOptions`](API.md#formatdateoptions) | `defaultOptions` | +| Name | Type | +| :------ | :------ | +| `date` | `Date` | +| `options?` | `Partial`<[`FormatDateOptions`](API.md#formatdateoptions)\> | #### Returns @@ -1782,13 +1783,13 @@ output of `Date.prototype.toLocaleString` for *most* locales. #### Defined in -[packages/framework/esm-utils/src/omrs-dates.ts:184](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L184) +[packages/framework/esm-utils/src/omrs-dates.ts:182](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L182) ___ ### formatDatetime -▸ **formatDatetime**(`date`, `mode?`): `string` +▸ **formatDatetime**(`date`, `options?`): `string` Formats the input into a string showing the date and time, according to the current locale. The `mode` parameter is as described for @@ -1800,10 +1801,10 @@ output of `Date.prototype.toLocaleString` for *most* locales. #### Parameters -| Name | Type | Default value | -| :------ | :------ | :------ | -| `date` | `Date` | `undefined` | -| `mode` | [`FormatDateMode`](API.md#formatdatemode) | `"standard"` | +| Name | Type | +| :------ | :------ | +| `date` | `Date` | +| `options?` | `Partial`<`Omit`<[`FormatDateOptions`](API.md#formatdateoptions), ``"time"``\>\> | #### Returns @@ -1811,7 +1812,7 @@ output of `Date.prototype.toLocaleString` for *most* locales. #### Defined in -[packages/framework/esm-utils/src/omrs-dates.ts:254](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L254) +[packages/framework/esm-utils/src/omrs-dates.ts:249](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L249) ___ @@ -1834,7 +1835,7 @@ Formats the input as a time, according to the current locale. #### Defined in -[packages/framework/esm-utils/src/omrs-dates.ts:238](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L238) +[packages/framework/esm-utils/src/omrs-dates.ts:233](https://github.com/openmrs/openmrs-esm-core/blob/master/packages/framework/esm-utils/src/omrs-dates.ts#L233) ___ diff --git a/packages/framework/esm-utils/src/omrs-dates.test.ts b/packages/framework/esm-utils/src/omrs-dates.test.ts index 2b28063f4..4520e9741 100644 --- a/packages/framework/esm-utils/src/omrs-dates.test.ts +++ b/packages/framework/esm-utils/src/omrs-dates.test.ts @@ -53,9 +53,9 @@ describe("Openmrs Dates", () => { testDate.setMinutes(22); window.i18next.language = "en"; expect(formatDate(testDate)).toEqual("Today, 03:22 PM"); - expect(formatDate(testDate, "no day")).toEqual("Today, 03:22 PM"); - expect(formatDate(testDate, "no year")).toEqual("Today, 03:22 PM"); - expect(formatDate(testDate, "wide")).toEqual("Today, 03:22 PM"); + expect(formatDate(testDate, { day: false })).toEqual("Today, 03:22 PM"); + expect(formatDate(testDate, { year: false })).toEqual("Today, 03:22 PM"); + expect(formatDate(testDate, { mode: "wide" })).toEqual("Today, 03:22 PM"); window.i18next.language = "sw"; expect(formatDate(testDate)).toEqual("Leo, 15:22"); window.i18next.language = "ru"; @@ -67,18 +67,23 @@ describe("Openmrs Dates", () => { const testDate = new Date("2021-12-09T13:15:33"); window.i18next.language = "en"; expect(formatDate(testDate)).toEqual("09-Dec-2021"); - expect(formatDate(testDate, "no day")).toEqual("Dec 2021"); - expect(formatDate(testDate, "no year")).toEqual("09 Dec"); - expect(formatDate(testDate, "wide")).toEqual("09 — Dec — 2021"); + expect(formatDate(testDate, { day: false })).toEqual("Dec 2021"); + expect(formatDate(testDate, { year: false })).toEqual("09 Dec"); + expect(formatDate(testDate, { mode: "wide" })).toEqual("09 — Dec — 2021"); + expect(formatDate(testDate, { mode: "wide", year: false })).toEqual( + "09 — Dec" + ); window.i18next.language = "fr"; expect(formatDate(testDate)).toEqual("09 déc. 2021"); - expect(formatDate(testDate, "no day")).toEqual("déc. 2021"); - expect(formatDate(testDate, "no year")).toEqual("09 déc."); - expect(formatDate(testDate, "wide")).toEqual("09 — déc. — 2021"); + expect(formatDate(testDate, { day: false })).toEqual("déc. 2021"); + expect(formatDate(testDate, { year: false })).toEqual("09 déc."); + expect(formatDate(testDate, { mode: "wide" })).toEqual("09 — déc. — 2021"); window.i18next.language = "sw"; expect(formatDate(testDate)).toEqual("09 Des 2021"); window.i18next.language = "ru"; - expect(formatDate(testDate, "wide")).toEqual("09 — дек. — 2021 г."); + expect(formatDate(testDate, { mode: "wide" })).toEqual( + "09 — дек. — 2021 г." + ); }); it("respects the `time` option", () => { @@ -89,22 +94,14 @@ describe("Openmrs Dates", () => { today.setMinutes(22); window.i18next.language = "en"; expect(formatDate(testDate)).toEqual("09-Dec-2021"); - expect(formatDate(testDate, "standard", { time: true })).toEqual( + expect(formatDate(testDate, { time: true })).toEqual( "09-Dec-2021, 01:15 PM" ); - expect(formatDate(testDate, "standard", { time: false })).toEqual( - "09-Dec-2021" - ); - expect(formatDate(testDate, "standard", { time: "for today" })).toEqual( - "09-Dec-2021" - ); - expect(formatDate(today, "standard", { time: true })).toEqual( - "Today, 03:22 PM" - ); - expect(formatDate(today, "standard", { time: false })).toEqual("Today"); - expect(formatDate(today, "standard", { time: "for today" })).toEqual( - "Today, 03:22 PM" - ); + expect(formatDate(testDate, { time: false })).toEqual("09-Dec-2021"); + expect(formatDate(testDate, { time: "for today" })).toEqual("09-Dec-2021"); + expect(formatDate(today, { time: true })).toEqual("Today, 03:22 PM"); + expect(formatDate(today, { time: false })).toEqual("Today"); + expect(formatDate(today, { time: "for today" })).toEqual("Today, 03:22 PM"); }); it("formats times with respect to the locale", () => { diff --git a/packages/framework/esm-utils/src/omrs-dates.ts b/packages/framework/esm-utils/src/omrs-dates.ts index 3a0e3603c..7822e035d 100644 --- a/packages/framework/esm-utils/src/omrs-dates.ts +++ b/packages/framework/esm-utils/src/omrs-dates.ts @@ -137,63 +137,58 @@ export function parseDate(dateString: string) { return dayjs(dateString).toDate(); } -const DATE_FORMAT_YYYY_MMM_DD = { - year: "numeric", - month: "short", - day: "2-digit", -}; -const DATE_FORMAT_YYYY_MMM = { - year: "numeric", - month: "short", -}; -const DATE_FORMAT_MMM_DD = { - month: "short", - day: "2-digit", -}; - -export type FormatDateMode = "standard" | "no year" | "no day" | "wide"; +export type FormatDateMode = "standard" | "wide"; export type FormatDateOptions = { + /** + * - `standard`: "03 Feb 2022" + * - `wide`: "03 — Feb — 2022" + */ + mode: FormatDateMode; /** * Whether the time should be included in the output always (`true`), * never (`false`), or only when the input date is today (`for today`). */ time: true | false | "for today"; + /** Whether to include the day number */ + day: boolean; + /** Whether to include the year */ + year: boolean; }; + const defaultOptions: FormatDateOptions = { + mode: "standard", time: "for today", + day: true, + year: true, }; /** * Formats the input date according to the current locale and the - * given format mode. + * given options. * - * - `standard`: "13 Dec 2021" - * - `no year`: "13 Dec" - * - `no day`: "Dec 2021" - * - `wide`: "13 — Dec — 2021" + * Default options: + * - mode: "standard", + * - time: "for today", + * - day: true, + * - year: true * - * Regardless of the mode, if the date is today, then "Today" is produced - * (in the locale language). + * If the date is today then "Today" is produced (in the locale language). * - * Can be used to format a date with time, also, by providing `options`. - * By default, the time is included only when the input date is today. - * The time is appended with a comma and a space. This agrees with the - * output of `Date.prototype.toLocaleString` for *most* locales. + * When time is included, it is appended with a comma and a space. This + * agrees with the output of `Date.prototype.toLocaleString` for *most* + * locales. */ -export function formatDate( - date: Date, - mode: FormatDateMode = "standard", - options: FormatDateOptions = defaultOptions -) { - const formatterOptions = ( - { - standard: DATE_FORMAT_YYYY_MMM_DD, - wide: DATE_FORMAT_YYYY_MMM_DD, - "no year": DATE_FORMAT_MMM_DD, - "no day": DATE_FORMAT_YYYY_MMM, - } as Record - )[mode]; +export function formatDate(date: Date, options?: Partial) { + const { mode, time, day, year }: FormatDateOptions = { + ...defaultOptions, + ...options, + }; + const formatterOptions: Intl.DateTimeFormatOptions = { + year: year ? "numeric" : undefined, + month: "short", + day: day ? "2-digit" : undefined, + }; let locale = getLocale(); let localeString: string; const isToday = dayjs(date).isToday(); @@ -210,7 +205,7 @@ export function formatDate( locale = "en-GB"; } localeString = date.toLocaleDateString(locale, formatterOptions); - if (locale == "en-GB" && mode == "standard") { + if (locale == "en-GB" && mode == "standard" && year && day) { // Custom formatting for English. Use hyphens instead of spaces. localeString = localeString.replace(/ /g, "-"); } @@ -225,7 +220,7 @@ export function formatDate( } } } - if (options.time === true || (isToday && options.time === "for today")) { + if (time === true || (isToday && time === "for today")) { localeString += `, ${formatTime(date)}`; } return localeString; @@ -251,8 +246,11 @@ export function formatTime(date: Date) { * and `formatTime` with a comma and space. This agrees with the * output of `Date.prototype.toLocaleString` for *most* locales. */ -export function formatDatetime(date: Date, mode: FormatDateMode = "standard") { - return formatDate(date, mode, { time: true }); +export function formatDatetime( + date: Date, + options?: Partial> +) { + return formatDate(date, { ...options, time: true }); } function getLocale() {