Skip to content

Commit

Permalink
feat(@formatjs/intl): add formatDateTimeRange per stage-3 spec
Browse files Browse the repository at this point in the history
  • Loading branch information
longlho committed Nov 5, 2020
1 parent b927f7a commit b08ee67
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 14 deletions.
2 changes: 2 additions & 0 deletions packages/intl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SRC_DEPS = [
"//packages/intl-displaynames:dist",
"//packages/intl-relativetimeformat:dist",
"//packages/intl-messageformat:dist",
"//packages/intl-datetimeformat:dist",
"@npm//fast-memoize",
"@npm//@types/node",
]
Expand Down Expand Up @@ -65,6 +66,7 @@ jest_test(
"//packages/intl-displaynames:types",
"//packages/intl-relativetimeformat:types",
"//packages/intl-messageformat:types",
"//packages/intl-datetimeformat:types",
"//packages/intl-messageformat-parser:types",
"//packages/ecma402-abstract:types",
],
Expand Down
1 change: 1 addition & 0 deletions packages/intl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@formatjs/intl-displaynames": "3.4.2",
"@formatjs/intl-listformat": "4.3.2",
"@formatjs/intl-relativetimeformat": "7.3.2",
"@formatjs/intl-datetimeformat": "2.8.0",
"fast-memoize": "^2.5.2",
"intl-messageformat": "9.3.13",
"intl-messageformat-parser": "6.0.12",
Expand Down
6 changes: 6 additions & 0 deletions packages/intl/src/create-intl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
formatDateToParts,
formatTime,
formatTimeToParts,
formatDateTimeRange,
} from './dateTime';
import {formatPlural} from './plural';
import {formatMessage} from './message';
Expand Down Expand Up @@ -97,6 +98,11 @@ export function createIntl<T = string>(
resolvedConfig,
formatters.getDateTimeFormat
),
formatDateTimeRange: formatDateTimeRange.bind(
null,
resolvedConfig,
formatters.getDateTimeFormat
),
formatTimeToParts: formatTimeToParts.bind(
null,
resolvedConfig,
Expand Down
47 changes: 37 additions & 10 deletions packages/intl/src/dateTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import {Formatters, IntlFormatters, CustomFormats, OnErrorFn} from './types';

import {filterProps, getNamedFormat} from './utils';
import {IntlError, IntlErrorCode} from './error';
import {DateTimeFormatOptions} from '@formatjs/ecma402-abstract';
import {
DateTimeFormatOptions,
DateTimeFormat,
} from '@formatjs/ecma402-abstract';

const DATE_TIME_FORMAT_OPTIONS: Array<keyof DateTimeFormatOptions> = [
'localeMatcher',
Expand Down Expand Up @@ -44,7 +47,7 @@ export function getFormatter(
type: 'date' | 'time',
getDateTimeFormat: Formatters['getDateTimeFormat'],
options: Parameters<IntlFormatters['formatDate']>[1] = {}
): Intl.DateTimeFormat {
): DateTimeFormat {
const {format} = options;
const defaults = {
...(timeZone && {timeZone}),
Expand Down Expand Up @@ -78,8 +81,7 @@ export function formatDate(
onError: OnErrorFn;
},
getDateTimeFormat: Formatters['getDateTimeFormat'],
value?: Parameters<IntlFormatters['formatDate']>[0],
options: Parameters<IntlFormatters['formatDate']>[1] = {}
...[value, options = {}]: Parameters<IntlFormatters['formatDate']>
): string {
const date = typeof value === 'string' ? new Date(value || 0) : value;
try {
Expand All @@ -103,8 +105,7 @@ export function formatTime(
onError: OnErrorFn;
},
getDateTimeFormat: Formatters['getDateTimeFormat'],
value?: Parameters<IntlFormatters['formatTime']>[0],
options: Parameters<IntlFormatters['formatTime']>[1] = {}
...[value, options = {}]: Parameters<IntlFormatters['formatTime']>
): string {
const date = typeof value === 'string' ? new Date(value || 0) : value;

Expand All @@ -121,6 +122,34 @@ export function formatTime(
return String(date);
}

export function formatDateTimeRange(
config: {
locale: string;
timeZone?: string;
formats: CustomFormats;
onError: OnErrorFn;
},
getDateTimeFormat: Formatters['getDateTimeFormat'],
...[from, to, options = {}]: Parameters<IntlFormatters['formatDateTimeRange']>
): string {
try {
return getFormatter(config, 'time', getDateTimeFormat, options).formatRange(
from,
to
);
} catch (e) {
config.onError(
new IntlError(
IntlErrorCode.FORMAT_ERROR,
'Error formatting date time range.',
e
)
);
}

return String(from);
}

export function formatDateToParts(
config: {
locale: string;
Expand All @@ -129,8 +158,7 @@ export function formatDateToParts(
onError: OnErrorFn;
},
getDateTimeFormat: Formatters['getDateTimeFormat'],
value?: Parameters<IntlFormatters['formatDate']>[0],
options: Parameters<IntlFormatters['formatDate']>[1] = {}
...[value, options = {}]: Parameters<IntlFormatters['formatDate']>
): Intl.DateTimeFormatPart[] {
const date = typeof value === 'string' ? new Date(value || 0) : value;
try {
Expand All @@ -157,8 +185,7 @@ export function formatTimeToParts(
onError: OnErrorFn;
},
getDateTimeFormat: Formatters['getDateTimeFormat'],
value?: Parameters<IntlFormatters['formatTime']>[0],
options: Parameters<IntlFormatters['formatTime']>[1] = {}
...[value, options = {}]: Parameters<IntlFormatters['formatTimeToParts']>
): Intl.DateTimeFormatPart[] {
const date = typeof value === 'string' ? new Date(value || 0) : value;

Expand Down
10 changes: 8 additions & 2 deletions packages/intl/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
FormatError,
} from 'intl-messageformat';
import IntlRelativeTimeFormat from '@formatjs/intl-relativetimeformat';
import {DateTimeFormat} from '@formatjs/ecma402-abstract';
import {MessageFormatElement} from 'intl-messageformat-parser';
import IntlListFormat, {IntlListFormatOptions} from '@formatjs/intl-listformat';
import {DisplayNames, DisplayNamesOptions} from '@formatjs/intl-displaynames';
Expand Down Expand Up @@ -86,6 +87,11 @@ export type FormatDisplayNameOptions = Exclude<
>;

export interface IntlFormatters<T = any, R = T> {
formatDateTimeRange(
from: Parameters<DateTimeFormat['formatRange']>[0],
to: Parameters<DateTimeFormat['formatRange']>[1],
opts?: FormatDateOptions
): string;
formatDate(
value: Parameters<Intl.DateTimeFormat['format']>[0] | string,
opts?: FormatDateOptions
Expand Down Expand Up @@ -141,7 +147,7 @@ export interface IntlFormatters<T = any, R = T> {
export interface Formatters {
getDateTimeFormat(
...args: ConstructorParameters<typeof Intl.DateTimeFormat>
): Intl.DateTimeFormat;
): DateTimeFormat;
getNumberFormat(
...args: ConstructorParameters<typeof Intl.NumberFormat>
): Intl.NumberFormat;
Expand All @@ -167,7 +173,7 @@ export interface IntlShape<T> extends IntlConfig<T>, IntlFormatters {
}

export interface IntlCache {
dateTime: Record<string, Intl.DateTimeFormat>;
dateTime: Record<string, DateTimeFormat>;
number: Record<string, Intl.NumberFormat>;
message: Record<string, IntlMessageFormat>;
relativeTime: Record<string, IntlRelativeTimeFormat>;
Expand Down
7 changes: 5 additions & 2 deletions packages/intl/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import {IntlMessageFormat} from 'intl-messageformat';
import * as memoize from 'fast-memoize';
import {Cache} from 'fast-memoize';
import {UnsupportedFormatterError} from './error';
import {IntlRelativeTimeFormatOptions} from '@formatjs/ecma402-abstract';
import {
DateTimeFormat,
IntlRelativeTimeFormatOptions,
} from '@formatjs/ecma402-abstract';

export function filterProps<T extends Record<string, any>, K extends string>(
props: T,
Expand Down Expand Up @@ -97,7 +100,7 @@ export function createFormatters(
const ListFormat = (Intl as any).ListFormat;
const DisplayNames = (Intl as any).DisplayNames;
const getDateTimeFormat = memoizeIntl(
(...args) => new Intl.DateTimeFormat(...args),
(...args) => new Intl.DateTimeFormat(...args) as DateTimeFormat,
{
cache: createFastMemoizeCache(cache.dateTime),
strategy: memoizeIntl.strategies.variadic,
Expand Down

0 comments on commit b08ee67

Please sign in to comment.