diff --git a/.changeset/eight-ties-fetch.md b/.changeset/eight-ties-fetch.md new file mode 100644 index 0000000..b407d13 --- /dev/null +++ b/.changeset/eight-ties-fetch.md @@ -0,0 +1,5 @@ +--- +'@sumup/intl': major +--- + +Added support for Temporal objects to the date and time formatting functions. The [`temporal-polyfill`](https://www.npmjs.com/package/temporal-polyfill) package is now a required peer dependency. diff --git a/README.md b/README.md index 5530779..c4dfdfd 100644 --- a/README.md +++ b/README.md @@ -30,18 +30,16 @@ Creating instances of `Intl.*` formatters is an [expensive operation](https://bl `@sumup/intl` works in [modern browsers](https://caniuse.com/mdn-javascript_builtins_intl_numberformat_numberformat,mdn-javascript_builtins_intl_datetimeformat_datetimeformat) as well as server runtimes with support for the `Intl` APIs (such as Node 10+[^1]). When the `Intl` APIs aren't (fully) available, `@sumup/intl` tries to gracefully degrade. Please refer to the [API reference](#api-reference) to learn how certain functions behave when the runtime doesn't support the necessary APIs. If you need to support legacy browsers, consider including [polyfills](https://formatjs.io/docs/polyfills/). +`@sumup/intl` integrates [`temporal-polyfill`](https://www.npmjs.com/package/temporal-polyfill) to support formatting [`Temporal`](https://github.com/tc39/proposal-temporal) date-time objects. + [^1]: [Node](https://nodejs.org/en/) supports the `Intl` APIs since v8, however, it includes only the English localizations up to v12. Node v13 and above support all locales. If you're unable to use Node v13+, you can either include [polyfills](https://formatjs.io/docs/polyfills/) or use a [custom Node build](https://nodejs.org/docs/latest-v8.x/api/intl.html#intl_options_for_building_node_js). ## Installation -[`@sumup/intl`](https://www.npmjs.com/package/@sumup/intl) can be installed as a dependency via the [npm](https://www.npmjs.com) or [Yarn](https://classic.yarnpkg.com) package managers. Depending on your preference, run one of the following: +[`@sumup/intl`](https://www.npmjs.com/package/@sumup/intl) can be installed as a dependency via the [npm](https://www.npmjs.com) package manager. The [`temporal-polyfill`](https://www.npmjs.com/package/temporal-polyfill) package is a required peer dependency. ```sh -# With npm -npm install @sumup/intl - -# With Yarn v1 -yarn add @sumup/intl +npm install @sumup/intl temporal-polyfill ``` `@sumup/intl` requires Node v10+. diff --git a/package-lock.json b/package-lock.json index 9261517..2eee29c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "eslint-plugin-prettier": "^5.1.3", "jest-extended": "^4.0.2", "license-checker": "^25.0.1", + "temporal-polyfill": "^0.2.5", "typedoc": "^0.26.3", "typedoc-github-wiki-theme": "^2.0.0", "typedoc-plugin-markdown": "^4.0.3", @@ -29,6 +30,9 @@ }, "engines": { "node": ">=10" + }, + "peerDependencies": { + "temporal-polyfill": "0.2.x" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -12677,6 +12681,21 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/temporal-polyfill": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.2.5.tgz", + "integrity": "sha512-ye47xp8Cb0nDguAhrrDS1JT1SzwEV9e26sSsrWzVu+yPZ7LzceEcH0i2gci9jWfOfSCCgM3Qv5nOYShVUUFUXA==", + "dev": true, + "dependencies": { + "temporal-spec": "^0.2.4" + } + }, + "node_modules/temporal-spec": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.2.4.tgz", + "integrity": "sha512-lDMFv4nKQrSjlkHKAlHVqKrBG4DyFfa9F74cmBZ3Iy3ed8yvWnlWSIdi4IKfSqwmazAohBNwiN64qGx4y5Q3IQ==", + "dev": true + }, "node_modules/term-size": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", @@ -23141,6 +23160,21 @@ } } }, + "temporal-polyfill": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.2.5.tgz", + "integrity": "sha512-ye47xp8Cb0nDguAhrrDS1JT1SzwEV9e26sSsrWzVu+yPZ7LzceEcH0i2gci9jWfOfSCCgM3Qv5nOYShVUUFUXA==", + "dev": true, + "requires": { + "temporal-spec": "^0.2.4" + } + }, + "temporal-spec": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.2.4.tgz", + "integrity": "sha512-lDMFv4nKQrSjlkHKAlHVqKrBG4DyFfa9F74cmBZ3Iy3ed8yvWnlWSIdi4IKfSqwmazAohBNwiN64qGx4y5Q3IQ==", + "dev": true + }, "term-size": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", diff --git a/package.json b/package.json index a2fc010..668a740 100644 --- a/package.json +++ b/package.json @@ -52,10 +52,14 @@ "eslint-plugin-prettier": "^5.1.3", "jest-extended": "^4.0.2", "license-checker": "^25.0.1", + "temporal-polyfill": "^0.2.5", "typedoc": "^0.26.3", "typedoc-github-wiki-theme": "^2.0.0", "typedoc-plugin-markdown": "^4.0.3", "typescript": "^5.4.5", "vitest": "^2.0.5" + }, + "peerDependencies": { + "temporal-polyfill": "0.2.x" } } diff --git a/src/lib/date-time-format/intl.ts b/src/lib/date-time-format/intl.ts index 5abb333..8b861a1 100644 --- a/src/lib/date-time-format/intl.ts +++ b/src/lib/date-time-format/intl.ts @@ -13,6 +13,7 @@ * limitations under the License. */ +import { Intl as IntlWithTemporal } from 'temporal-polyfill'; import memoizeFormatConstructor from 'intl-format-cache'; import { Locale } from '../../types'; @@ -61,8 +62,8 @@ export const isDateTimeStyleSupported = (() => { })(); export const getDateTimeFormat = memoizeFormatConstructor( - Intl.DateTimeFormat, + IntlWithTemporal.DateTimeFormat, ) as ( locales?: Locale | Locale[], options?: Intl.DateTimeFormatOptions, -) => Intl.DateTimeFormat; +) => IntlWithTemporal.DateTimeFormat; diff --git a/src/lib/date-time-format/tests/format-to-parts.spec.ts b/src/lib/date-time-format/tests/format-to-parts.spec.ts index 000a306..ed20769 100644 --- a/src/lib/date-time-format/tests/format-to-parts.spec.ts +++ b/src/lib/date-time-format/tests/format-to-parts.spec.ts @@ -14,6 +14,7 @@ */ import { describe, it, expect } from 'vitest'; +import { Intl } from 'temporal-polyfill'; import { formatDateTimeToParts } from '..'; diff --git a/src/lib/date-time-format/tests/format.spec.ts b/src/lib/date-time-format/tests/format.spec.ts index b1fcc6e..6627be7 100644 --- a/src/lib/date-time-format/tests/format.spec.ts +++ b/src/lib/date-time-format/tests/format.spec.ts @@ -14,6 +14,7 @@ */ import { describe, it, expect } from 'vitest'; +import { Intl } from 'temporal-polyfill'; import { formatDateTime, formatDate, formatTime } from '..'; diff --git a/src/lib/date-time-format/tests/resolve-format.spec.ts b/src/lib/date-time-format/tests/resolve-format.spec.ts index b74a712..458e2d1 100644 --- a/src/lib/date-time-format/tests/resolve-format.spec.ts +++ b/src/lib/date-time-format/tests/resolve-format.spec.ts @@ -14,6 +14,7 @@ */ import { describe, it, expect } from 'vitest'; +import { Intl } from 'temporal-polyfill'; import { resolveDateTimeFormat } from '..'; diff --git a/src/lib/date-time-format/tests/unsupported-styles.spec.ts b/src/lib/date-time-format/tests/unsupported-styles.spec.ts index 8df94e8..f1d122e 100644 --- a/src/lib/date-time-format/tests/unsupported-styles.spec.ts +++ b/src/lib/date-time-format/tests/unsupported-styles.spec.ts @@ -14,6 +14,7 @@ */ import { vi, describe, it, expect } from 'vitest'; +import { Intl } from 'temporal-polyfill'; import { formatDateTime } from '..'; diff --git a/vitest.setup.js b/vitest.setup.js index 16380bc..a3f5586 100644 --- a/vitest.setup.js +++ b/vitest.setup.js @@ -1,10 +1,11 @@ import { vi, expect } from 'vitest'; import * as matchers from 'jest-extended'; +import { Intl as IntlWithTemporal } from 'temporal-polyfill'; expect.extend(matchers); vi.spyOn(Intl, 'NumberFormat'); -vi.spyOn(Intl, 'DateTimeFormat'); +vi.spyOn(IntlWithTemporal, 'DateTimeFormat'); // Apparently, Node.js doesn't implement these APIs. // The mocked return value is based on the test value `1001001001.11111`