New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@phensley/cldr-core

Package Overview
Dependencies
Maintainers
0
Versions
242
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@phensley/cldr-core - npm Package Compare versions

Comparing version 1.9.2 to 1.10.0

3

lib-es/api/api.d.ts

@@ -95,4 +95,5 @@ import { CharacterOrderType, CurrencyType, DateFieldType, DateTimePatternFieldType, LineOrderType, RelativeTimeFieldType, UnitType } from '@phensley/cldr-types';

* to choose an appropriate date or time skeleton for interval formatting.
* Returns undefined if the dates are equivalent down to the second.
*/
fieldOfVisualDifference(a: CalendarDate | ZonedDateTime | Date, b: CalendarDate | ZonedDateTime | Date): DateTimePatternFieldType;
fieldOfVisualDifference(a: CalendarDate | ZonedDateTime | Date, b: CalendarDate | ZonedDateTime | Date): DateTimePatternFieldType | undefined;
/**

@@ -99,0 +100,0 @@ * Formats a date-time value to string.

@@ -103,3 +103,3 @@ import { DateFieldType, DateTimePatternFieldType, RelativeTimeFieldType } from '@phensley/cldr-types';

*/
fieldOfVisualDifference(a: CalendarDate | ZonedDateTime | Date, b: CalendarDate | ZonedDateTime | Date): DateTimePatternFieldType;
fieldOfVisualDifference(a: CalendarDate | ZonedDateTime | Date, b: CalendarDate | ZonedDateTime | Date): DateTimePatternFieldType | undefined;
/**

@@ -106,0 +106,0 @@ * Format a calendar date to string using the given options.

@@ -368,9 +368,10 @@ import { TZ } from '@phensley/timezone';

end = this.convertDateTo(calendar, end);
var fieldDiff = this.fieldOfVisualDifference(start, end);
// const fieldDiff = this.fieldOfVisualDifference(start, end);
var wrap = options.wrap || 'medium';
var params = this.privateApi.getNumberParams(options.nu, 'default');
var req = this.manager.getDateIntervalFormatRequest(calendar, start, fieldDiff, options, params);
var req = this.manager.getDateIntervalFormatRequest(calendar, start, end, options, params);
var ctx = this._context(start, params, options.context, options.alt);
if (req.skeleton) {
var ca = options.ca, nu = options.nu;
var r = this.manager.getDateFormatRequest(start, { ca: ca, nu: nu, skeleton: req.skeleton }, params);
var ctx = this._context(start, params, options.context, options.alt);
var r = this.manager.getDateFormatRequest(start, { ca: ca, nu: nu, skeleton: req.skeleton, wrap: options.wrap, atTime: options.atTime }, params);
var _start = this.internals.calendars.formatDateTime(calendar, ctx, value, true, r.date, r.time, r.wrapper);

@@ -383,10 +384,17 @@ ctx.date = end;

}
var patterns = this.manager.getCalendarPatterns(calendar);
var atTime = options.atTime === false ? false : true;
var _date;
if (req.date) {
var ctx = this._context(start, params, options.context, options.alt);
_date = this.internals.calendars.formatDateTime(calendar, ctx, value, true, req.date);
}
if (req.time) {
var _time = this.internals.calendars.formatDateTime(calendar, ctx, value, true, req.time);
var wrapper = this.internals.general.parseWrapper(patterns.getWrapperPattern(wrap, atTime));
value.wrap(wrapper, [_time, _date]);
return value.render();
}
if (req.range) {
var ctx = this._context(start, params, options.context, options.alt);
var _range = this.internals.calendars.formatInterval(calendar, ctx, value, !_date, end, req.range);
var ctx_1 = this._context(start, params, options.context, options.alt);
var _range = this.internals.calendars.formatInterval(calendar, ctx_1, value, !_date, end, req.range);
if (!_date) {

@@ -401,5 +409,3 @@ return _range;

// https://www.unicode.org/reports/tr35/tr35-dates.html#intervalFormats
var patterns = this.manager.getCalendarPatterns(calendar);
var atTime = options.atTime === false ? false : true;
var wrapper = this.internals.general.parseWrapper(patterns.getWrapperPattern('medium', atTime));
var wrapper = this.internals.general.parseWrapper(patterns.getWrapperPattern(wrap, atTime));
value.wrap(wrapper, [_range, _date]);

@@ -406,0 +412,0 @@ return value.render();

@@ -185,2 +185,6 @@ import { ContextType, DateFieldWidthType, DayPeriodAltType, EraAltType, EraWidthType, FieldWidthType, FormatWidthType } from '@phensley/cldr-types';

/**
* Wrapper format to use, if both a date and time are being formatted.
*/
wrap?: FormatWidthType;
/**
* Wrap with 'at' if available. This defaults to true since it was

@@ -187,0 +191,0 @@ * the default datetime wrapper format in CLDR releases prior to v42.

@@ -8,2 +8,3 @@ import { DateTimePatternFieldType } from '@phensley/cldr-types';

import { CalendarPatterns } from './patterns';
import { DateSkeleton } from './skeleton';
import { DateFormatRequest, DateIntervalFormatRequest } from './types';

@@ -19,24 +20,107 @@ export declare class CalendarManager {

/**
* Best-fit match an input skeleton. The skeleton can contain both date and
* time fields.
* Formats datetime intervals.
*
* The field of greatest difference between the start and end dates can be
* either a date or time field.
* NOTE: The ICU implementation of CLDR datetime range formatting
* contains inconsistent behavior (see code at end of comment below).
*
* Given this we need to cover the following cases:
* The skeleton data for interval formatting consists of a series of
* separate date and time patterns. No interval skeletons / formats
* contain both date and time fields.
*
* 1. Input skeleton requests both date and time fields.
* a. "yMd" same: split skeleton, format date standalone, followed by time range.
* b. "yMd" differ: format full start / end with fallback format.
* For example, the data might contain the following:
*
* 2. Input skeleton requests date fields only:
* a. "yMd" same: format date standalone
* b. "yMd" differ: select and format date range
* ['y', 'yM', 'yMd', 'h', 'hm', 'H', 'Hm']
*
* 3. Input skeleton requests time fields only:
* a. "yMd" same, "ahms" same: format time standalone
* b. "yMd" same, "ahms" differ: select and format time range.
* c. "yMd" differ: prepend "yMd" to skeleton and go to (1a).
* However a caller can pass input skeleton containing a mix of date and
* time fields. We split this skeleton into separate date and time
* skeletons, and perform formatting by considering the possibilities below.
*
* Variables:
*
* start = start datetime
* end = end datetime
* skeleton = input skeleton
* fovd = fieldOfVisualDifference(start, end)
* date_differs = fovd in ('era', 'year', 'month', 'day')
* time_differs = fovd in ('dayperiod', 'hour', 'minute')
* equal = fovd in ('second', undefined)
*
* Formatting Rules:
*
* 1. Skeleton requests both date and time fields
*
* a. IF time_differs, format date followed by time range
* e.g. "date, time0 - time 1"
*
* b. ELSE IF date_differs, format generic fallback
* e.g. "date0, time0 - date1, time1"
*
* c. ELSE format the date + time standalone
* e.g. "date0, time0"
*
* 2: Skeleton only requests date fields
*
* a. IF date_differs, format date range
* e.g. "date0 - date1"
*
* b. ELSE format date standalone
*
* 3: Skeleton only requests time fields
*
* a. IF time_differs, format time range
* e.g. "time0 - time1"
*
* b. ELSE format time standalone
*
* ========================================================
*
* Example of inconsistency of ICU range formatting.
* The output was produced using Node 23.7.0 and ICU 74.
* ICU4J version 75 produces the same output.
*
* const OPTS = [
* { day: 'numeric' },
* { day: 'numeric', minute: '2-digit' }
* ];
* const start = new Date(Date.UTC(2007, 0, 1, 10, 12, 0));
* const end = new Date(Date.UTC(2008, 0, 2, 11, 13, 0));
* for (let i = 0; i < OPTS.length; i++) {
* const opts = OPTS[i];
* const fmt = new Intl.DateTimeFormat('en', opts);
* console.log(fmt.formatRange(start, end));
* }
*
* This code formats two dates two different ways:
*
* 2007-Jan-01 10:12
* 2008-Jan-02 11:13
*
* 1. Display the day: { day: 'numeric' }
*
* ICU auto-expands the selected pattern to include the year
* and month:
*
* "1/1/2007 – 1/2/2008"
*
* This adds context needed to understand the two
* dates are separated by 367 days.
*
* 2. Display day and minute: { day: 'numeric', minute: '2-digit' }
*
* No pattern expansion occurs, we get only what we
* requested. The output is highly ambiguous since it's
* missing year, month, and hour fields:
*
* "1, 12 – 2, 13"
*
* Additional context is added in one case but not in the other.
*
* IMO it makes more sense to leave the input skeleton as untouched
* as possible, leaving it up to the caller to decide which
* fields to request.
*/
getDateIntervalFormatRequest(calendar: string, start: CalendarDate, fieldDiff: DateTimePatternFieldType, options: DateIntervalFormatOptions, params: NumberParams): DateIntervalFormatRequest;
getDateIntervalFormatRequest(calendar: string, start: CalendarDate, end: CalendarDate, options: DateIntervalFormatOptions, params: NumberParams): DateIntervalFormatRequest;
largestSkeletonField(skeleton: DateSkeleton): DateTimePatternFieldType;
maskedFOVD(start: CalendarDate, end: CalendarDate, skeleton: DateSkeleton): DateTimePatternFieldType;
private dayperiodFlex;
private matchAvailablePattern;

@@ -43,0 +127,0 @@ private getAvailablePattern;

@@ -0,3 +1,15 @@

import { DateTimePatternField } from '@phensley/cldr-types';
import { Cache } from '@phensley/cldr-utils';
import { CalendarPatterns, GregorianPatterns } from './patterns';
var maskedFOVDFields = [
0 /* Field.ERA */,
1 /* Field.YEAR */,
3 /* Field.MONTH */,
7 /* Field.DAY */,
10 /* Field.DAYPERIOD */,
11 /* Field.HOUR */,
12 /* Field.MINUTE */,
13 /* Field.SECOND */,
];
var minutes = function (d) { return d.hourOfDay() * 60 + d.minute(); };
var CalendarManager = /** @class */ (function () {

@@ -132,120 +144,284 @@ function CalendarManager(bundle, internals) {

/**
* Best-fit match an input skeleton. The skeleton can contain both date and
* time fields.
* Formats datetime intervals.
*
* The field of greatest difference between the start and end dates can be
* either a date or time field.
* NOTE: The ICU implementation of CLDR datetime range formatting
* contains inconsistent behavior (see code at end of comment below).
*
* Given this we need to cover the following cases:
* The skeleton data for interval formatting consists of a series of
* separate date and time patterns. No interval skeletons / formats
* contain both date and time fields.
*
* 1. Input skeleton requests both date and time fields.
* a. "yMd" same: split skeleton, format date standalone, followed by time range.
* b. "yMd" differ: format full start / end with fallback format.
* For example, the data might contain the following:
*
* 2. Input skeleton requests date fields only:
* a. "yMd" same: format date standalone
* b. "yMd" differ: select and format date range
* ['y', 'yM', 'yMd', 'h', 'hm', 'H', 'Hm']
*
* 3. Input skeleton requests time fields only:
* a. "yMd" same, "ahms" same: format time standalone
* b. "yMd" same, "ahms" differ: select and format time range.
* c. "yMd" differ: prepend "yMd" to skeleton and go to (1a).
* However a caller can pass input skeleton containing a mix of date and
* time fields. We split this skeleton into separate date and time
* skeletons, and perform formatting by considering the possibilities below.
*
* Variables:
*
* start = start datetime
* end = end datetime
* skeleton = input skeleton
* fovd = fieldOfVisualDifference(start, end)
* date_differs = fovd in ('era', 'year', 'month', 'day')
* time_differs = fovd in ('dayperiod', 'hour', 'minute')
* equal = fovd in ('second', undefined)
*
* Formatting Rules:
*
* 1. Skeleton requests both date and time fields
*
* a. IF time_differs, format date followed by time range
* e.g. "date, time0 - time 1"
*
* b. ELSE IF date_differs, format generic fallback
* e.g. "date0, time0 - date1, time1"
*
* c. ELSE format the date + time standalone
* e.g. "date0, time0"
*
* 2: Skeleton only requests date fields
*
* a. IF date_differs, format date range
* e.g. "date0 - date1"
*
* b. ELSE format date standalone
*
* 3: Skeleton only requests time fields
*
* a. IF time_differs, format time range
* e.g. "time0 - time1"
*
* b. ELSE format time standalone
*
* ========================================================
*
* Example of inconsistency of ICU range formatting.
* The output was produced using Node 23.7.0 and ICU 74.
* ICU4J version 75 produces the same output.
*
* const OPTS = [
* { day: 'numeric' },
* { day: 'numeric', minute: '2-digit' }
* ];
* const start = new Date(Date.UTC(2007, 0, 1, 10, 12, 0));
* const end = new Date(Date.UTC(2008, 0, 2, 11, 13, 0));
* for (let i = 0; i < OPTS.length; i++) {
* const opts = OPTS[i];
* const fmt = new Intl.DateTimeFormat('en', opts);
* console.log(fmt.formatRange(start, end));
* }
*
* This code formats two dates two different ways:
*
* 2007-Jan-01 10:12
* 2008-Jan-02 11:13
*
* 1. Display the day: { day: 'numeric' }
*
* ICU auto-expands the selected pattern to include the year
* and month:
*
* "1/1/2007 – 1/2/2008"
*
* This adds context needed to understand the two
* dates are separated by 367 days.
*
* 2. Display day and minute: { day: 'numeric', minute: '2-digit' }
*
* No pattern expansion occurs, we get only what we
* requested. The output is highly ambiguous since it's
* missing year, month, and hour fields:
*
* "1, 12 – 2, 13"
*
* Additional context is added in one case but not in the other.
*
* IMO it makes more sense to leave the input skeleton as untouched
* as possible, leaving it up to the caller to decide which
* fields to request.
*/
CalendarManager.prototype.getDateIntervalFormatRequest = function (calendar, start, fieldDiff, options, params) {
CalendarManager.prototype.getDateIntervalFormatRequest = function (calendar, start, end, options, params) {
var patterns = this.getCalendarPatterns(calendar);
var dateDiffers = 'yMd'.indexOf(fieldDiff) !== -1;
var wrapper = patterns.getIntervalFallback();
var req = { params: params, wrapper: wrapper };
var origSkeleton = options.skeleton;
if (!origSkeleton) {
// Determine whether the largest field of visual difference (fovd)
// is a date or time field, or neither. Note that interval patterns
// in the CLDR data do not include seconds, so we consider dates
// that only differ in seconds to be equivalent.
var fovd = start.fieldOfVisualDifference(end) || 's';
var dateDiffers = 'GyMd'.indexOf(fovd) !== -1;
var timeDiffers = 'BahHm'.indexOf(fovd) !== -1;
// If main skeleton input is not used, select either date or
// time based on whether the date or time differ.
var skeleton = options.skeleton;
if (!skeleton) {
if (dateDiffers && options.date) {
origSkeleton = options.date;
skeleton = options.date;
}
else {
origSkeleton = options.time;
skeleton = options.time;
}
}
// If the skeleton is still undefined, select a reasonable default
if (!origSkeleton) {
origSkeleton = dateDiffers ? 'yMMMd' : 'hmsa';
// If no skeleton is defined, choose a simple default
var defaulted = false;
if (!skeleton) {
skeleton = dateDiffers ? 'yMMMd' : 'jm';
defaulted = true;
}
var skeleton = origSkeleton;
// Cache key consists of the input skeleton and the field of greatest difference between
// the start and end dates.
var cacheKey = "".concat(skeleton, "\t").concat(fieldDiff);
var entry = patterns.getCachedIntervalRequest(cacheKey);
if (entry) {
req.date = entry.date;
req.range = entry.range;
req.skeleton = entry.skeleton;
return req;
}
entry = {};
// At this point the skeleton contains at least one field.
// Parse the input skeleton.
var query = patterns.parseSkeleton(skeleton);
var standalone = fieldDiff === 's' || (query.isDate && !dateDiffers) || (query.isTime && dateDiffers);
if (!standalone) {
if (query.has(7 /* Field.DAY */) && !query.has(3 /* Field.MONTH */)) {
skeleton = "M".concat(skeleton);
if (!defaulted) {
// Interval skeletons for bare seconds 's' and minutes 'm' do not
// exist in the CLDR data. We fill in the gap to ensure we at least
// match on the correct hour field for the current locale.
var largest = this.largestSkeletonField(query);
if ('sm'.indexOf(largest) !== -1) {
skeleton = (largest === 's' ? 'jm' : 'j') + skeleton;
query = patterns.parseSkeleton(skeleton);
}
if (query.has(12 /* Field.MINUTE */) && !query.has(11 /* Field.HOUR */)) {
skeleton = "j".concat(skeleton);
}
}
if (!query.isDate && dateDiffers) {
// 3c. prepend "yMd" and proceed
if (fieldDiff === 'y') {
skeleton = "yMd".concat(skeleton);
// BEGIN formatting rules.
// RULE 1. Skeleton contains both date and time fields
if (query.compound()) {
if (timeDiffers) {
// RULE 1a. IF time_differs, format date followed by time range
var timeQuery = query.split();
req.date = this.matchAvailablePattern(patterns, start, query, params);
query = timeQuery;
// ... (1a) intentional fall through to format date + time range
}
else if (fieldDiff === 'M') {
skeleton = "Md".concat(skeleton);
else if (dateDiffers) {
// RULE 1b. ELSE IF date_differs, format generic fallback
req.skeleton = skeleton;
return req;
}
else {
skeleton = "d".concat(skeleton);
}
}
if (origSkeleton !== skeleton) {
query = patterns.parseSkeleton(skeleton);
}
var timeQuery;
// If both date and time fields are requested, we have two choices:
// a. date fields are the same: "<date>, <time start> - <time end>"
// b. date fields differ, format full range: "<start> - <end>"
if (query.compound()) {
if (dateDiffers) {
// 1b. format start and end dates with fallback: "<start> - <end>"
req.skeleton = skeleton;
entry.skeleton = skeleton;
patterns.setCachedIntervalRequest(cacheKey, entry);
// RULE 1c. ELSE format the date + time standalone
var timeQuery = query.split();
if (query.isDate) {
req.date = this.matchAvailablePattern(patterns, start, query, params);
}
if (timeQuery.isTime) {
req.time = this.matchAvailablePattern(patterns, start, timeQuery, params);
}
return req;
}
// 1a. split skeleton, format date standalone ..
timeQuery = query.split();
entry.date = this.matchAvailablePattern(patterns, start, query, params);
// ... followed by time range: "<date>, <time start> - <time end>"
query = timeQuery;
}
// standalone: in certain cases we cannot display a range.
standalone = fieldDiff === 's' || (query.isDate && !dateDiffers) || (query.isTime && dateDiffers);
if (standalone) {
// 2a. format date standalone: "<date>"
// 3a. format time standalone: "<time>"
entry.date = this.matchAvailablePattern(patterns, start, query, params);
}
else {
// 2b. format date interval: "<date start> - <date end>"
// 3b. format time interval: "<time start> - <time end>"
var match = patterns.matchInterval(query, fieldDiff);
if (match) {
var pattern = patterns.getIntervalPattern(fieldDiff, match.skeleton);
// RULE 2: skeleton only contains date fields
// RULE 3: skeleotn only contains time fields
if (fovd !== 's') {
// RULE 2a IF dateDiffers, format date range
// RULE 3a IF timeDiffers, format time range
var match = patterns.matchInterval(query);
if (match && match.data) {
// Compute masked field of visual difference using the found skeleton.
var fovd_1 = this.maskedFOVD(start, end, match.skeleton);
// Use fovd to select final pattern. Since it was masked by the matched
// skeleton, the fovd should completely cover the set of patterns in the data.
var pattern = match.data.patterns[fovd_1];
var parsedPattern = this.internals.calendars.parseDatePattern(pattern || '');
/* istanbul ignore else */
if (pattern.length) {
entry.range = patterns.adjustPattern(pattern, query, params.symbols.decimal);
if (parsedPattern.length) {
req.range = patterns.adjustPattern(parsedPattern, query, params.symbols.decimal);
}
}
}
patterns.setCachedIntervalRequest(cacheKey, entry);
req.date = entry.date;
req.range = entry.range;
else {
// RULE 2b ELSE format date standalone
// RULE 3b ELSE format time standalone
req.date = this.matchAvailablePattern(patterns, start, query, params);
}
return req;
};
CalendarManager.prototype.largestSkeletonField = function (skeleton) {
for (var _i = 0, maskedFOVDFields_1 = maskedFOVDFields; _i < maskedFOVDFields_1.length; _i++) {
var field = maskedFOVDFields_1[_i];
var info = skeleton.info[field];
if (info) {
return info.field;
}
}
return DateTimePatternField.SECOND;
};
CalendarManager.prototype.maskedFOVD = function (start, end, skeleton) {
var smallest;
for (var _i = 0, maskedFOVDFields_2 = maskedFOVDFields; _i < maskedFOVDFields_2.length; _i++) {
var field = maskedFOVDFields_2[_i];
var info = skeleton.info[field];
if (!info) {
continue;
}
smallest = info;
switch (field) {
case 0 /* Field.ERA */:
if (start.era() !== end.era()) {
return DateTimePatternField.ERA;
}
break;
case 1 /* Field.YEAR */:
if (start.year() !== end.year()) {
return DateTimePatternField.YEAR;
}
break;
case 3 /* Field.MONTH */:
if (start.month() !== end.month()) {
return DateTimePatternField.MONTH;
}
break;
case 7 /* Field.DAY */:
if (start.dayOfMonth() !== end.dayOfMonth()) {
return DateTimePatternField.DAY;
}
break;
case 10 /* Field.DAYPERIOD */:
switch (info.field) {
case 'a': // dayperiod
case 'b': // dayperiod extended (resolve to 'a' for now)
if (start.isAM() !== end.isAM()) {
return DateTimePatternField.DAYPERIOD;
}
break;
case 'B': // dayperiod flex
if (this.dayperiodFlex(start) !== this.dayperiodFlex(end)) {
return DateTimePatternField.DAYPERIOD_FLEX;
}
break;
}
break;
case 11 /* Field.HOUR */:
switch (info.field) {
case 'h': // hour 1-12
case 'K': // hour 0-11
if (start.hour() !== end.hour()) {
return DateTimePatternField.HOUR12;
}
break;
case 'H': // hour 0-23
case 'k': // hour 1-24
if (start.hourOfDay() !== end.hourOfDay()) {
return DateTimePatternField.HOUR24;
}
break;
}
break;
case 12 /* Field.MINUTE */:
case 13 /* Field.SECOND */:
if (start.minute() !== end.minute()) {
return DateTimePatternField.MINUTE;
}
break;
}
}
// If we exhaust all fields of the skeleton, the two dates are equivalent
// with respect to the fields masked by the skeleton. We return the smallest
// field by default.
return smallest ? smallest.field : DateTimePatternField.MINUTE;
};
CalendarManager.prototype.dayperiodFlex = function (date) {
return this.internals.calendars.flexDayPeriod(this.bundle, minutes(date)) || '';
};
CalendarManager.prototype.matchAvailablePattern = function (patterns, date, query, params) {

@@ -252,0 +428,0 @@ var match = patterns.matchAvailable(query);

import { CalendarSchema } from '@phensley/cldr-types';
import { Internals } from '../../internals';
import { Bundle } from '../../resource';
import { DateSkeleton } from './skeleton';
import { DatePatternMatcherEntry, DateSkeleton } from './skeleton';
import { DateTimeNode } from '../../parsing/date';

@@ -30,2 +30,6 @@ import { CalendarDate } from '../../systems/calendars';

};
export interface IntervalSkeleton {
skeleton: DateSkeleton;
patterns: any;
}
/**

@@ -45,3 +49,2 @@ * Caches all available date formatting patterns for a given calendar schema.

private readonly skeletonParser;
private readonly intervalRequestCache;
private readonly dateFormats;

@@ -72,4 +75,2 @@ private readonly timeFormats;

getTimePattern(width: string): DateTimeNode[];
getCachedIntervalRequest(key: string): CachedIntervalRequest | undefined;
setCachedIntervalRequest(key: string, req: CachedIntervalRequest): void;
getWrapperPattern(width: string, atTime: boolean): string;

@@ -81,3 +82,3 @@ getAvailablePattern(_d: CalendarDate, s: DateSkeleton): DateTimeNode[];

matchAvailable(skeleton: DateSkeleton): DateSkeleton;
matchInterval(skeleton: DateSkeleton, field: string): DateSkeleton | undefined;
matchInterval(skeleton: DateSkeleton): DatePatternMatcherEntry<IntervalSkeleton> | undefined;
private buildSkeletonParser;

@@ -84,0 +85,0 @@ private buildAvailableMatcher;

import { __extends } from "tslib";
import { coerceDecimal } from '@phensley/decimal';
import { LRU } from '@phensley/cldr-utils';
import { timeData, timeStrings } from './autogen.timedata';

@@ -21,3 +20,3 @@ import { DatePatternMatcher, DateSkeletonParser } from './skeleton';

this.availableMatcher = new DatePatternMatcher();
this.intervalMatcher = {};
this.intervalMatcher = new DatePatternMatcher();
this.rawIntervalFormats = {};

@@ -29,3 +28,2 @@ this.rawAvailableFormats = {};

this.skeletonParser = this.buildSkeletonParser();
this.intervalRequestCache = new LRU(cacheSize);
// Fetch this locale's main formats

@@ -68,8 +66,2 @@ this.dateFormats = schema.dateFormats.mapping(bundle);

};
CalendarPatterns.prototype.getCachedIntervalRequest = function (key) {
return this.intervalRequestCache.get(key);
};
CalendarPatterns.prototype.setCachedIntervalRequest = function (key, req) {
this.intervalRequestCache.set(key, req);
};
CalendarPatterns.prototype.getWrapperPattern = function (width, atTime) {

@@ -97,14 +89,12 @@ var w = this.wrapperFormatsAt[width];

CalendarPatterns.prototype.matchAvailable = function (skeleton) {
return this.availableMatcher.match(skeleton);
return this.availableMatcher.match(skeleton).skeleton;
};
CalendarPatterns.prototype.matchInterval = function (skeleton, field) {
field = field === 's' ? 'm' : field;
var m = this.intervalMatcher[field];
return m ? m.match(skeleton) : undefined;
CalendarPatterns.prototype.matchInterval = function (skeleton) {
return this.intervalMatcher.match(skeleton);
};
CalendarPatterns.prototype.buildSkeletonParser = function () {
var pair = this.getTimeData();
var allowedFlex = pair[0].split(' ').map(parseDatePattern);
var preferredFlex = parseDatePattern(pair[1]);
return new DateSkeletonParser(preferredFlex, allowedFlex[0]);
var allowed = pair[0].split(' ').map(parseDatePattern);
var preferred = parseDatePattern(pair[1]);
return new DateSkeletonParser(preferred, allowed[0]);
};

@@ -126,14 +116,15 @@ CalendarPatterns.prototype.buildAvailableMatcher = function () {

}
this.availableMatcher.sort();
};
CalendarPatterns.prototype.buildIntervalMatcher = function () {
for (var _i = 0, _a = Object.keys(this.rawIntervalFormats); _i < _a.length; _i++) {
var field = _a[_i];
var group = this.rawIntervalFormats[field];
var m = new DatePatternMatcher();
for (var _b = 0, _c = Object.keys(group); _b < _c.length; _b++) {
var skeleton = _c[_b];
m.add(this.skeletonParser.parse(skeleton));
var rawSkeleton = _a[_i];
var patterns = this.rawIntervalFormats[rawSkeleton];
if (Object.keys(patterns).length === 0) {
continue;
}
this.intervalMatcher[field] = m;
var skeleton = this.skeletonParser.parse(rawSkeleton);
this.intervalMatcher.add(skeleton, { skeleton: skeleton, patterns: patterns });
}
this.intervalMatcher.sort();
};

@@ -140,0 +131,0 @@ CalendarPatterns.prototype.getTimeData = function () {

@@ -47,11 +47,20 @@ import { DateTimeNode } from '../../parsing/date';

}
export interface DatePatternMatcherEntry<T> {
skeleton: DateSkeleton;
data?: T;
}
export declare const NONE: DatePatternMatcherEntry<any>;
/**
* Cache of date patterns and skeletons with ICU-compatible best-fit matching.
*/
export declare class DatePatternMatcher {
export declare class DatePatternMatcher<T> {
private exact;
private entries;
add(skeleton: DateSkeleton, _pattern?: DateTimeNode[]): void;
match(input: DateSkeleton): DateSkeleton;
add(skeleton: DateSkeleton, data?: T): void;
/**
* Sort entries once they have all been added.
*/
sort(): void;
match(input: DateSkeleton): DatePatternMatcherEntry<T>;
/**
* Make field width adjustments to pattern using the given skeleton.

@@ -58,0 +67,0 @@ */

@@ -57,13 +57,10 @@ import { DATE_PATTERN_CHARS } from '../../parsing/date';

var field = info.field;
// Skip day period for backwards-compatibility
if (field !== '' && field !== 'a') {
var repeat = info.repeat;
// Override skeleton repeat for these fields.
if ('GEzvQ'.indexOf(field) !== -1) {
repeat = 1;
}
for (var j = 0; j < repeat; j++) {
r += field;
}
var repeat = info.repeat;
// Override skeleton repeat for these fields.
if ('GEzvQ'.indexOf(field) !== -1) {
repeat = 1;
}
for (var j = 0; j < repeat; j++) {
r += field;
}
}

@@ -173,3 +170,2 @@ }

var n = meta_1[_i];
// Flex types have no static pattern fields
/* istanbul ignore else */

@@ -204,2 +200,5 @@ if (typeof n !== 'string') {

var cmp = function (a, b) { return (a < b ? -1 : a > b ? 1 : 0); };
export var NONE = {
skeleton: new DateSkeleton(),
};
/**

@@ -215,11 +214,20 @@ * Cache of date patterns and skeletons with ICU-compatible best-fit matching.

}
DatePatternMatcher.prototype.add = function (skeleton, _pattern) {
DatePatternMatcher.prototype.add = function (skeleton, data) {
var key = skeleton.skeleton;
// Avoid adding patterns with duplicate skeletons
if (this.exact[key] === undefined) {
this.exact[key] = skeleton;
this.entries.push(skeleton);
var entry = {
skeleton: skeleton,
data: data,
};
this.exact[key] = entry;
this.entries.push(entry);
}
this.entries.sort(function (a, b) { return cmp(a.skeleton.length, b.skeleton.length); });
};
/**
* Sort entries once they have all been added.
*/
DatePatternMatcher.prototype.sort = function () {
this.entries.sort(function (a, b) { return cmp(a.skeleton.skeleton.length, b.skeleton.skeleton.length); });
};
// TODO: future options to control the match

@@ -231,7 +239,7 @@ DatePatternMatcher.prototype.match = function (input) {

}
var best = EMPTY;
var best = NONE;
var bestDist = Number.MAX_SAFE_INTEGER;
for (var _i = 0, _a = this.entries; _i < _a.length; _i++) {
var entry = _a[_i];
var dist = this.getDistance(entry, input);
var dist = this.getDistance(entry.skeleton, input);
if (dist < bestDist) {

@@ -290,8 +298,2 @@ best = entry;

}
// TODO: UNREACHABLE as field replacement has been selected above
// // Metacharacters have already been replaced in the pattern.
// if ('jJC'.indexOf(adjfield) !== -1) {
// console.log('adjust skeleton', adjfield);
// adjfield = field;
// }
r.push([adjfield, adjwidth]);

@@ -298,0 +300,0 @@ }

@@ -11,2 +11,3 @@ import { DateTimeNode } from '../../parsing/date';

date?: DateTimeNode[];
time?: DateTimeNode[];
range?: DateTimeNode[];

@@ -13,0 +14,0 @@ skeleton?: string;

@@ -18,3 +18,3 @@ import { field, scope, vector, KeyIndexImpl } from '../instructions';

vector('pluralFormats', ['plural-key', "".concat(name, "-plural-format")]),
vector('intervalFormats', ['date-time-pattern-field', "".concat(name, "-interval-format")]),
vector('intervalFormats', ["".concat(name, "-interval-format"), 'date-time-pattern-field']),
vector('dateFormats', ['format-width']),

@@ -21,0 +21,0 @@ vector('timeFormats', ['format-width']),

@@ -36,3 +36,14 @@ import { KeyIndexImpl } from '../instructions';

*/
export var DateTimePatternFieldValues = ['y', 'M', 'd', 'a', 'H', 'm', 's'];
export var DateTimePatternFieldValues = [
'G',
'y',
'M',
'd',
'a',
'B',
'H',
'h',
'm',
's',
];
/**

@@ -39,0 +50,0 @@ * @public

@@ -132,3 +132,3 @@ import { DateTimePatternFieldType, MetaZoneType } from '@phensley/cldr-types';

*/
fieldOfVisualDifference(other: CalendarDate): DateTimePatternFieldType;
fieldOfVisualDifference(other: CalendarDate): DateTimePatternFieldType | undefined;
/**

@@ -135,0 +135,0 @@ * Compare two dates a and b, returning:

@@ -49,2 +49,3 @@ import { __assign } from "tslib";

var differenceFields = [
[2 /* DateField.ERA */, DateTimePatternField.ERA],
[4 /* DateField.YEAR */, DateTimePatternField.YEAR],

@@ -54,4 +55,5 @@ [7 /* DateField.MONTH */, DateTimePatternField.MONTH],

[14 /* DateField.AM_PM */, DateTimePatternField.DAYPERIOD],
[16 /* DateField.HOUR */, DateTimePatternField.HOUR],
[16 /* DateField.HOUR */, DateTimePatternField.HOUR24],
[17 /* DateField.MINUTE */, DateTimePatternField.MINUTE],
[18 /* DateField.SECOND */, DateTimePatternField.SECOND],
];

@@ -269,4 +271,3 @@ /**

for (var _i = 0, differenceFields_1 = differenceFields; _i < differenceFields_1.length; _i++) {
var pair = differenceFields_1[_i];
var key = pair[0], field = pair[1];
var _a = differenceFields_1[_i], key = _a[0], field = _a[1];
if (a[key] !== b[key]) {

@@ -276,3 +277,3 @@ return field;

}
return DateTimePatternField.SECOND;
return undefined;
};

@@ -279,0 +280,0 @@ /**

{
"name": "@phensley/cldr-core",
"version": "1.9.2",
"version": "1.10.0",
"description": "Core library for @phensley/cldr",

@@ -39,19 +39,19 @@ "main": "lib/index.js",

"dependencies": {
"@phensley/cldr-types": "workspace:~1.9.2",
"@phensley/cldr-utils": "workspace:~1.9.2",
"@phensley/decimal": "workspace:~1.9.2",
"@phensley/language-tag": "workspace:~1.9.2",
"@phensley/locale": "workspace:~1.9.2",
"@phensley/locale-matcher": "workspace:~1.9.2",
"@phensley/messageformat": "workspace:~1.9.2",
"@phensley/plurals": "workspace:~1.9.2",
"@phensley/timezone": "workspace:~1.9.2",
"tslib": "^2.7.0"
"@phensley/cldr-types": "workspace:~1.10.0",
"@phensley/cldr-utils": "workspace:~1.10.0",
"@phensley/decimal": "workspace:~1.10.0",
"@phensley/language-tag": "workspace:~1.10.0",
"@phensley/locale": "workspace:~1.10.0",
"@phensley/locale-matcher": "workspace:~1.10.0",
"@phensley/messageformat": "workspace:~1.10.0",
"@phensley/plurals": "workspace:~1.10.0",
"@phensley/timezone": "workspace:~1.10.0",
"tslib": "^2.8.1"
},
"devDependencies": {
"@microsoft/api-extractor": "~7.47.7",
"@types/jest": "^29.5.12",
"@types/node": "^22.5.2",
"@typescript-eslint/eslint-plugin": "^8.4.0",
"@typescript-eslint/parser": "^8.4.0",
"@microsoft/api-extractor": "~7.49.2",
"@types/jest": "^29.5.14",
"@types/node": "^22.13.1",
"@typescript-eslint/eslint-plugin": "^8.23.0",
"@typescript-eslint/parser": "^8.23.0",
"add": "^2.0.6",

@@ -62,10 +62,10 @@ "beautify-benchmark": "^0.2.4",

"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.3",
"jest": "^29.7.0",
"pnpm": "^9.9.0",
"prettier": "^3.3.3",
"pnpm": "^10.2.1",
"prettier": "^3.4.2",
"rimraf": "^6.0.1",
"ts-jest": "^29.2.5",
"typescript": "~5.5.4"
"typescript": "~5.7.3"
},

@@ -72,0 +72,0 @@ "jest": {

@@ -95,4 +95,5 @@ import { CharacterOrderType, CurrencyType, DateFieldType, DateTimePatternFieldType, LineOrderType, RelativeTimeFieldType, UnitType } from '@phensley/cldr-types';

* to choose an appropriate date or time skeleton for interval formatting.
* Returns undefined if the dates are equivalent down to the second.
*/
fieldOfVisualDifference(a: CalendarDate | ZonedDateTime | Date, b: CalendarDate | ZonedDateTime | Date): DateTimePatternFieldType;
fieldOfVisualDifference(a: CalendarDate | ZonedDateTime | Date, b: CalendarDate | ZonedDateTime | Date): DateTimePatternFieldType | undefined;
/**

@@ -99,0 +100,0 @@ * Formats a date-time value to string.

@@ -103,3 +103,3 @@ import { DateFieldType, DateTimePatternFieldType, RelativeTimeFieldType } from '@phensley/cldr-types';

*/
fieldOfVisualDifference(a: CalendarDate | ZonedDateTime | Date, b: CalendarDate | ZonedDateTime | Date): DateTimePatternFieldType;
fieldOfVisualDifference(a: CalendarDate | ZonedDateTime | Date, b: CalendarDate | ZonedDateTime | Date): DateTimePatternFieldType | undefined;
/**

@@ -106,0 +106,0 @@ * Format a calendar date to string using the given options.

@@ -371,9 +371,10 @@ "use strict";

end = this.convertDateTo(calendar, end);
var fieldDiff = this.fieldOfVisualDifference(start, end);
// const fieldDiff = this.fieldOfVisualDifference(start, end);
var wrap = options.wrap || 'medium';
var params = this.privateApi.getNumberParams(options.nu, 'default');
var req = this.manager.getDateIntervalFormatRequest(calendar, start, fieldDiff, options, params);
var req = this.manager.getDateIntervalFormatRequest(calendar, start, end, options, params);
var ctx = this._context(start, params, options.context, options.alt);
if (req.skeleton) {
var ca = options.ca, nu = options.nu;
var r = this.manager.getDateFormatRequest(start, { ca: ca, nu: nu, skeleton: req.skeleton }, params);
var ctx = this._context(start, params, options.context, options.alt);
var r = this.manager.getDateFormatRequest(start, { ca: ca, nu: nu, skeleton: req.skeleton, wrap: options.wrap, atTime: options.atTime }, params);
var _start = this.internals.calendars.formatDateTime(calendar, ctx, value, true, r.date, r.time, r.wrapper);

@@ -386,10 +387,17 @@ ctx.date = end;

}
var patterns = this.manager.getCalendarPatterns(calendar);
var atTime = options.atTime === false ? false : true;
var _date;
if (req.date) {
var ctx = this._context(start, params, options.context, options.alt);
_date = this.internals.calendars.formatDateTime(calendar, ctx, value, true, req.date);
}
if (req.time) {
var _time = this.internals.calendars.formatDateTime(calendar, ctx, value, true, req.time);
var wrapper = this.internals.general.parseWrapper(patterns.getWrapperPattern(wrap, atTime));
value.wrap(wrapper, [_time, _date]);
return value.render();
}
if (req.range) {
var ctx = this._context(start, params, options.context, options.alt);
var _range = this.internals.calendars.formatInterval(calendar, ctx, value, !_date, end, req.range);
var ctx_1 = this._context(start, params, options.context, options.alt);
var _range = this.internals.calendars.formatInterval(calendar, ctx_1, value, !_date, end, req.range);
if (!_date) {

@@ -404,5 +412,3 @@ return _range;

// https://www.unicode.org/reports/tr35/tr35-dates.html#intervalFormats
var patterns = this.manager.getCalendarPatterns(calendar);
var atTime = options.atTime === false ? false : true;
var wrapper = this.internals.general.parseWrapper(patterns.getWrapperPattern('medium', atTime));
var wrapper = this.internals.general.parseWrapper(patterns.getWrapperPattern(wrap, atTime));
value.wrap(wrapper, [_range, _date]);

@@ -409,0 +415,0 @@ return value.render();

@@ -185,2 +185,6 @@ import { ContextType, DateFieldWidthType, DayPeriodAltType, EraAltType, EraWidthType, FieldWidthType, FormatWidthType } from '@phensley/cldr-types';

/**
* Wrapper format to use, if both a date and time are being formatted.
*/
wrap?: FormatWidthType;
/**
* Wrap with 'at' if available. This defaults to true since it was

@@ -187,0 +191,0 @@ * the default datetime wrapper format in CLDR releases prior to v42.

@@ -8,2 +8,3 @@ import { DateTimePatternFieldType } from '@phensley/cldr-types';

import { CalendarPatterns } from './patterns';
import { DateSkeleton } from './skeleton';
import { DateFormatRequest, DateIntervalFormatRequest } from './types';

@@ -19,24 +20,107 @@ export declare class CalendarManager {

/**
* Best-fit match an input skeleton. The skeleton can contain both date and
* time fields.
* Formats datetime intervals.
*
* The field of greatest difference between the start and end dates can be
* either a date or time field.
* NOTE: The ICU implementation of CLDR datetime range formatting
* contains inconsistent behavior (see code at end of comment below).
*
* Given this we need to cover the following cases:
* The skeleton data for interval formatting consists of a series of
* separate date and time patterns. No interval skeletons / formats
* contain both date and time fields.
*
* 1. Input skeleton requests both date and time fields.
* a. "yMd" same: split skeleton, format date standalone, followed by time range.
* b. "yMd" differ: format full start / end with fallback format.
* For example, the data might contain the following:
*
* 2. Input skeleton requests date fields only:
* a. "yMd" same: format date standalone
* b. "yMd" differ: select and format date range
* ['y', 'yM', 'yMd', 'h', 'hm', 'H', 'Hm']
*
* 3. Input skeleton requests time fields only:
* a. "yMd" same, "ahms" same: format time standalone
* b. "yMd" same, "ahms" differ: select and format time range.
* c. "yMd" differ: prepend "yMd" to skeleton and go to (1a).
* However a caller can pass input skeleton containing a mix of date and
* time fields. We split this skeleton into separate date and time
* skeletons, and perform formatting by considering the possibilities below.
*
* Variables:
*
* start = start datetime
* end = end datetime
* skeleton = input skeleton
* fovd = fieldOfVisualDifference(start, end)
* date_differs = fovd in ('era', 'year', 'month', 'day')
* time_differs = fovd in ('dayperiod', 'hour', 'minute')
* equal = fovd in ('second', undefined)
*
* Formatting Rules:
*
* 1. Skeleton requests both date and time fields
*
* a. IF time_differs, format date followed by time range
* e.g. "date, time0 - time 1"
*
* b. ELSE IF date_differs, format generic fallback
* e.g. "date0, time0 - date1, time1"
*
* c. ELSE format the date + time standalone
* e.g. "date0, time0"
*
* 2: Skeleton only requests date fields
*
* a. IF date_differs, format date range
* e.g. "date0 - date1"
*
* b. ELSE format date standalone
*
* 3: Skeleton only requests time fields
*
* a. IF time_differs, format time range
* e.g. "time0 - time1"
*
* b. ELSE format time standalone
*
* ========================================================
*
* Example of inconsistency of ICU range formatting.
* The output was produced using Node 23.7.0 and ICU 74.
* ICU4J version 75 produces the same output.
*
* const OPTS = [
* { day: 'numeric' },
* { day: 'numeric', minute: '2-digit' }
* ];
* const start = new Date(Date.UTC(2007, 0, 1, 10, 12, 0));
* const end = new Date(Date.UTC(2008, 0, 2, 11, 13, 0));
* for (let i = 0; i < OPTS.length; i++) {
* const opts = OPTS[i];
* const fmt = new Intl.DateTimeFormat('en', opts);
* console.log(fmt.formatRange(start, end));
* }
*
* This code formats two dates two different ways:
*
* 2007-Jan-01 10:12
* 2008-Jan-02 11:13
*
* 1. Display the day: { day: 'numeric' }
*
* ICU auto-expands the selected pattern to include the year
* and month:
*
* "1/1/2007 – 1/2/2008"
*
* This adds context needed to understand the two
* dates are separated by 367 days.
*
* 2. Display day and minute: { day: 'numeric', minute: '2-digit' }
*
* No pattern expansion occurs, we get only what we
* requested. The output is highly ambiguous since it's
* missing year, month, and hour fields:
*
* "1, 12 – 2, 13"
*
* Additional context is added in one case but not in the other.
*
* IMO it makes more sense to leave the input skeleton as untouched
* as possible, leaving it up to the caller to decide which
* fields to request.
*/
getDateIntervalFormatRequest(calendar: string, start: CalendarDate, fieldDiff: DateTimePatternFieldType, options: DateIntervalFormatOptions, params: NumberParams): DateIntervalFormatRequest;
getDateIntervalFormatRequest(calendar: string, start: CalendarDate, end: CalendarDate, options: DateIntervalFormatOptions, params: NumberParams): DateIntervalFormatRequest;
largestSkeletonField(skeleton: DateSkeleton): DateTimePatternFieldType;
maskedFOVD(start: CalendarDate, end: CalendarDate, skeleton: DateSkeleton): DateTimePatternFieldType;
private dayperiodFlex;
private matchAvailablePattern;

@@ -43,0 +127,0 @@ private getAvailablePattern;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CalendarManager = void 0;
var cldr_types_1 = require("@phensley/cldr-types");
var cldr_utils_1 = require("@phensley/cldr-utils");
var patterns_1 = require("./patterns");
var maskedFOVDFields = [
0 /* Field.ERA */,
1 /* Field.YEAR */,
3 /* Field.MONTH */,
7 /* Field.DAY */,
10 /* Field.DAYPERIOD */,
11 /* Field.HOUR */,
12 /* Field.MINUTE */,
13 /* Field.SECOND */,
];
var minutes = function (d) { return d.hourOfDay() * 60 + d.minute(); };
var CalendarManager = /** @class */ (function () {

@@ -135,120 +147,284 @@ function CalendarManager(bundle, internals) {

/**
* Best-fit match an input skeleton. The skeleton can contain both date and
* time fields.
* Formats datetime intervals.
*
* The field of greatest difference between the start and end dates can be
* either a date or time field.
* NOTE: The ICU implementation of CLDR datetime range formatting
* contains inconsistent behavior (see code at end of comment below).
*
* Given this we need to cover the following cases:
* The skeleton data for interval formatting consists of a series of
* separate date and time patterns. No interval skeletons / formats
* contain both date and time fields.
*
* 1. Input skeleton requests both date and time fields.
* a. "yMd" same: split skeleton, format date standalone, followed by time range.
* b. "yMd" differ: format full start / end with fallback format.
* For example, the data might contain the following:
*
* 2. Input skeleton requests date fields only:
* a. "yMd" same: format date standalone
* b. "yMd" differ: select and format date range
* ['y', 'yM', 'yMd', 'h', 'hm', 'H', 'Hm']
*
* 3. Input skeleton requests time fields only:
* a. "yMd" same, "ahms" same: format time standalone
* b. "yMd" same, "ahms" differ: select and format time range.
* c. "yMd" differ: prepend "yMd" to skeleton and go to (1a).
* However a caller can pass input skeleton containing a mix of date and
* time fields. We split this skeleton into separate date and time
* skeletons, and perform formatting by considering the possibilities below.
*
* Variables:
*
* start = start datetime
* end = end datetime
* skeleton = input skeleton
* fovd = fieldOfVisualDifference(start, end)
* date_differs = fovd in ('era', 'year', 'month', 'day')
* time_differs = fovd in ('dayperiod', 'hour', 'minute')
* equal = fovd in ('second', undefined)
*
* Formatting Rules:
*
* 1. Skeleton requests both date and time fields
*
* a. IF time_differs, format date followed by time range
* e.g. "date, time0 - time 1"
*
* b. ELSE IF date_differs, format generic fallback
* e.g. "date0, time0 - date1, time1"
*
* c. ELSE format the date + time standalone
* e.g. "date0, time0"
*
* 2: Skeleton only requests date fields
*
* a. IF date_differs, format date range
* e.g. "date0 - date1"
*
* b. ELSE format date standalone
*
* 3: Skeleton only requests time fields
*
* a. IF time_differs, format time range
* e.g. "time0 - time1"
*
* b. ELSE format time standalone
*
* ========================================================
*
* Example of inconsistency of ICU range formatting.
* The output was produced using Node 23.7.0 and ICU 74.
* ICU4J version 75 produces the same output.
*
* const OPTS = [
* { day: 'numeric' },
* { day: 'numeric', minute: '2-digit' }
* ];
* const start = new Date(Date.UTC(2007, 0, 1, 10, 12, 0));
* const end = new Date(Date.UTC(2008, 0, 2, 11, 13, 0));
* for (let i = 0; i < OPTS.length; i++) {
* const opts = OPTS[i];
* const fmt = new Intl.DateTimeFormat('en', opts);
* console.log(fmt.formatRange(start, end));
* }
*
* This code formats two dates two different ways:
*
* 2007-Jan-01 10:12
* 2008-Jan-02 11:13
*
* 1. Display the day: { day: 'numeric' }
*
* ICU auto-expands the selected pattern to include the year
* and month:
*
* "1/1/2007 – 1/2/2008"
*
* This adds context needed to understand the two
* dates are separated by 367 days.
*
* 2. Display day and minute: { day: 'numeric', minute: '2-digit' }
*
* No pattern expansion occurs, we get only what we
* requested. The output is highly ambiguous since it's
* missing year, month, and hour fields:
*
* "1, 12 – 2, 13"
*
* Additional context is added in one case but not in the other.
*
* IMO it makes more sense to leave the input skeleton as untouched
* as possible, leaving it up to the caller to decide which
* fields to request.
*/
CalendarManager.prototype.getDateIntervalFormatRequest = function (calendar, start, fieldDiff, options, params) {
CalendarManager.prototype.getDateIntervalFormatRequest = function (calendar, start, end, options, params) {
var patterns = this.getCalendarPatterns(calendar);
var dateDiffers = 'yMd'.indexOf(fieldDiff) !== -1;
var wrapper = patterns.getIntervalFallback();
var req = { params: params, wrapper: wrapper };
var origSkeleton = options.skeleton;
if (!origSkeleton) {
// Determine whether the largest field of visual difference (fovd)
// is a date or time field, or neither. Note that interval patterns
// in the CLDR data do not include seconds, so we consider dates
// that only differ in seconds to be equivalent.
var fovd = start.fieldOfVisualDifference(end) || 's';
var dateDiffers = 'GyMd'.indexOf(fovd) !== -1;
var timeDiffers = 'BahHm'.indexOf(fovd) !== -1;
// If main skeleton input is not used, select either date or
// time based on whether the date or time differ.
var skeleton = options.skeleton;
if (!skeleton) {
if (dateDiffers && options.date) {
origSkeleton = options.date;
skeleton = options.date;
}
else {
origSkeleton = options.time;
skeleton = options.time;
}
}
// If the skeleton is still undefined, select a reasonable default
if (!origSkeleton) {
origSkeleton = dateDiffers ? 'yMMMd' : 'hmsa';
// If no skeleton is defined, choose a simple default
var defaulted = false;
if (!skeleton) {
skeleton = dateDiffers ? 'yMMMd' : 'jm';
defaulted = true;
}
var skeleton = origSkeleton;
// Cache key consists of the input skeleton and the field of greatest difference between
// the start and end dates.
var cacheKey = "".concat(skeleton, "\t").concat(fieldDiff);
var entry = patterns.getCachedIntervalRequest(cacheKey);
if (entry) {
req.date = entry.date;
req.range = entry.range;
req.skeleton = entry.skeleton;
return req;
}
entry = {};
// At this point the skeleton contains at least one field.
// Parse the input skeleton.
var query = patterns.parseSkeleton(skeleton);
var standalone = fieldDiff === 's' || (query.isDate && !dateDiffers) || (query.isTime && dateDiffers);
if (!standalone) {
if (query.has(7 /* Field.DAY */) && !query.has(3 /* Field.MONTH */)) {
skeleton = "M".concat(skeleton);
if (!defaulted) {
// Interval skeletons for bare seconds 's' and minutes 'm' do not
// exist in the CLDR data. We fill in the gap to ensure we at least
// match on the correct hour field for the current locale.
var largest = this.largestSkeletonField(query);
if ('sm'.indexOf(largest) !== -1) {
skeleton = (largest === 's' ? 'jm' : 'j') + skeleton;
query = patterns.parseSkeleton(skeleton);
}
if (query.has(12 /* Field.MINUTE */) && !query.has(11 /* Field.HOUR */)) {
skeleton = "j".concat(skeleton);
}
}
if (!query.isDate && dateDiffers) {
// 3c. prepend "yMd" and proceed
if (fieldDiff === 'y') {
skeleton = "yMd".concat(skeleton);
// BEGIN formatting rules.
// RULE 1. Skeleton contains both date and time fields
if (query.compound()) {
if (timeDiffers) {
// RULE 1a. IF time_differs, format date followed by time range
var timeQuery = query.split();
req.date = this.matchAvailablePattern(patterns, start, query, params);
query = timeQuery;
// ... (1a) intentional fall through to format date + time range
}
else if (fieldDiff === 'M') {
skeleton = "Md".concat(skeleton);
else if (dateDiffers) {
// RULE 1b. ELSE IF date_differs, format generic fallback
req.skeleton = skeleton;
return req;
}
else {
skeleton = "d".concat(skeleton);
}
}
if (origSkeleton !== skeleton) {
query = patterns.parseSkeleton(skeleton);
}
var timeQuery;
// If both date and time fields are requested, we have two choices:
// a. date fields are the same: "<date>, <time start> - <time end>"
// b. date fields differ, format full range: "<start> - <end>"
if (query.compound()) {
if (dateDiffers) {
// 1b. format start and end dates with fallback: "<start> - <end>"
req.skeleton = skeleton;
entry.skeleton = skeleton;
patterns.setCachedIntervalRequest(cacheKey, entry);
// RULE 1c. ELSE format the date + time standalone
var timeQuery = query.split();
if (query.isDate) {
req.date = this.matchAvailablePattern(patterns, start, query, params);
}
if (timeQuery.isTime) {
req.time = this.matchAvailablePattern(patterns, start, timeQuery, params);
}
return req;
}
// 1a. split skeleton, format date standalone ..
timeQuery = query.split();
entry.date = this.matchAvailablePattern(patterns, start, query, params);
// ... followed by time range: "<date>, <time start> - <time end>"
query = timeQuery;
}
// standalone: in certain cases we cannot display a range.
standalone = fieldDiff === 's' || (query.isDate && !dateDiffers) || (query.isTime && dateDiffers);
if (standalone) {
// 2a. format date standalone: "<date>"
// 3a. format time standalone: "<time>"
entry.date = this.matchAvailablePattern(patterns, start, query, params);
}
else {
// 2b. format date interval: "<date start> - <date end>"
// 3b. format time interval: "<time start> - <time end>"
var match = patterns.matchInterval(query, fieldDiff);
if (match) {
var pattern = patterns.getIntervalPattern(fieldDiff, match.skeleton);
// RULE 2: skeleton only contains date fields
// RULE 3: skeleotn only contains time fields
if (fovd !== 's') {
// RULE 2a IF dateDiffers, format date range
// RULE 3a IF timeDiffers, format time range
var match = patterns.matchInterval(query);
if (match && match.data) {
// Compute masked field of visual difference using the found skeleton.
var fovd_1 = this.maskedFOVD(start, end, match.skeleton);
// Use fovd to select final pattern. Since it was masked by the matched
// skeleton, the fovd should completely cover the set of patterns in the data.
var pattern = match.data.patterns[fovd_1];
var parsedPattern = this.internals.calendars.parseDatePattern(pattern || '');
/* istanbul ignore else */
if (pattern.length) {
entry.range = patterns.adjustPattern(pattern, query, params.symbols.decimal);
if (parsedPattern.length) {
req.range = patterns.adjustPattern(parsedPattern, query, params.symbols.decimal);
}
}
}
patterns.setCachedIntervalRequest(cacheKey, entry);
req.date = entry.date;
req.range = entry.range;
else {
// RULE 2b ELSE format date standalone
// RULE 3b ELSE format time standalone
req.date = this.matchAvailablePattern(patterns, start, query, params);
}
return req;
};
CalendarManager.prototype.largestSkeletonField = function (skeleton) {
for (var _i = 0, maskedFOVDFields_1 = maskedFOVDFields; _i < maskedFOVDFields_1.length; _i++) {
var field = maskedFOVDFields_1[_i];
var info = skeleton.info[field];
if (info) {
return info.field;
}
}
return cldr_types_1.DateTimePatternField.SECOND;
};
CalendarManager.prototype.maskedFOVD = function (start, end, skeleton) {
var smallest;
for (var _i = 0, maskedFOVDFields_2 = maskedFOVDFields; _i < maskedFOVDFields_2.length; _i++) {
var field = maskedFOVDFields_2[_i];
var info = skeleton.info[field];
if (!info) {
continue;
}
smallest = info;
switch (field) {
case 0 /* Field.ERA */:
if (start.era() !== end.era()) {
return cldr_types_1.DateTimePatternField.ERA;
}
break;
case 1 /* Field.YEAR */:
if (start.year() !== end.year()) {
return cldr_types_1.DateTimePatternField.YEAR;
}
break;
case 3 /* Field.MONTH */:
if (start.month() !== end.month()) {
return cldr_types_1.DateTimePatternField.MONTH;
}
break;
case 7 /* Field.DAY */:
if (start.dayOfMonth() !== end.dayOfMonth()) {
return cldr_types_1.DateTimePatternField.DAY;
}
break;
case 10 /* Field.DAYPERIOD */:
switch (info.field) {
case 'a': // dayperiod
case 'b': // dayperiod extended (resolve to 'a' for now)
if (start.isAM() !== end.isAM()) {
return cldr_types_1.DateTimePatternField.DAYPERIOD;
}
break;
case 'B': // dayperiod flex
if (this.dayperiodFlex(start) !== this.dayperiodFlex(end)) {
return cldr_types_1.DateTimePatternField.DAYPERIOD_FLEX;
}
break;
}
break;
case 11 /* Field.HOUR */:
switch (info.field) {
case 'h': // hour 1-12
case 'K': // hour 0-11
if (start.hour() !== end.hour()) {
return cldr_types_1.DateTimePatternField.HOUR12;
}
break;
case 'H': // hour 0-23
case 'k': // hour 1-24
if (start.hourOfDay() !== end.hourOfDay()) {
return cldr_types_1.DateTimePatternField.HOUR24;
}
break;
}
break;
case 12 /* Field.MINUTE */:
case 13 /* Field.SECOND */:
if (start.minute() !== end.minute()) {
return cldr_types_1.DateTimePatternField.MINUTE;
}
break;
}
}
// If we exhaust all fields of the skeleton, the two dates are equivalent
// with respect to the fields masked by the skeleton. We return the smallest
// field by default.
return smallest ? smallest.field : cldr_types_1.DateTimePatternField.MINUTE;
};
CalendarManager.prototype.dayperiodFlex = function (date) {
return this.internals.calendars.flexDayPeriod(this.bundle, minutes(date)) || '';
};
CalendarManager.prototype.matchAvailablePattern = function (patterns, date, query, params) {

@@ -255,0 +431,0 @@ var match = patterns.matchAvailable(query);

import { CalendarSchema } from '@phensley/cldr-types';
import { Internals } from '../../internals';
import { Bundle } from '../../resource';
import { DateSkeleton } from './skeleton';
import { DatePatternMatcherEntry, DateSkeleton } from './skeleton';
import { DateTimeNode } from '../../parsing/date';

@@ -30,2 +30,6 @@ import { CalendarDate } from '../../systems/calendars';

};
export interface IntervalSkeleton {
skeleton: DateSkeleton;
patterns: any;
}
/**

@@ -45,3 +49,2 @@ * Caches all available date formatting patterns for a given calendar schema.

private readonly skeletonParser;
private readonly intervalRequestCache;
private readonly dateFormats;

@@ -72,4 +75,2 @@ private readonly timeFormats;

getTimePattern(width: string): DateTimeNode[];
getCachedIntervalRequest(key: string): CachedIntervalRequest | undefined;
setCachedIntervalRequest(key: string, req: CachedIntervalRequest): void;
getWrapperPattern(width: string, atTime: boolean): string;

@@ -81,3 +82,3 @@ getAvailablePattern(_d: CalendarDate, s: DateSkeleton): DateTimeNode[];

matchAvailable(skeleton: DateSkeleton): DateSkeleton;
matchInterval(skeleton: DateSkeleton, field: string): DateSkeleton | undefined;
matchInterval(skeleton: DateSkeleton): DatePatternMatcherEntry<IntervalSkeleton> | undefined;
private buildSkeletonParser;

@@ -84,0 +85,0 @@ private buildAvailableMatcher;

@@ -6,3 +6,2 @@ "use strict";

var decimal_1 = require("@phensley/decimal");
var cldr_utils_1 = require("@phensley/cldr-utils");
var autogen_timedata_1 = require("./autogen.timedata");

@@ -25,3 +24,3 @@ var skeleton_1 = require("./skeleton");

this.availableMatcher = new skeleton_1.DatePatternMatcher();
this.intervalMatcher = {};
this.intervalMatcher = new skeleton_1.DatePatternMatcher();
this.rawIntervalFormats = {};

@@ -33,3 +32,2 @@ this.rawAvailableFormats = {};

this.skeletonParser = this.buildSkeletonParser();
this.intervalRequestCache = new cldr_utils_1.LRU(cacheSize);
// Fetch this locale's main formats

@@ -72,8 +70,2 @@ this.dateFormats = schema.dateFormats.mapping(bundle);

};
CalendarPatterns.prototype.getCachedIntervalRequest = function (key) {
return this.intervalRequestCache.get(key);
};
CalendarPatterns.prototype.setCachedIntervalRequest = function (key, req) {
this.intervalRequestCache.set(key, req);
};
CalendarPatterns.prototype.getWrapperPattern = function (width, atTime) {

@@ -101,14 +93,12 @@ var w = this.wrapperFormatsAt[width];

CalendarPatterns.prototype.matchAvailable = function (skeleton) {
return this.availableMatcher.match(skeleton);
return this.availableMatcher.match(skeleton).skeleton;
};
CalendarPatterns.prototype.matchInterval = function (skeleton, field) {
field = field === 's' ? 'm' : field;
var m = this.intervalMatcher[field];
return m ? m.match(skeleton) : undefined;
CalendarPatterns.prototype.matchInterval = function (skeleton) {
return this.intervalMatcher.match(skeleton);
};
CalendarPatterns.prototype.buildSkeletonParser = function () {
var pair = this.getTimeData();
var allowedFlex = pair[0].split(' ').map(date_1.parseDatePattern);
var preferredFlex = (0, date_1.parseDatePattern)(pair[1]);
return new skeleton_1.DateSkeletonParser(preferredFlex, allowedFlex[0]);
var allowed = pair[0].split(' ').map(date_1.parseDatePattern);
var preferred = (0, date_1.parseDatePattern)(pair[1]);
return new skeleton_1.DateSkeletonParser(preferred, allowed[0]);
};

@@ -130,14 +120,15 @@ CalendarPatterns.prototype.buildAvailableMatcher = function () {

}
this.availableMatcher.sort();
};
CalendarPatterns.prototype.buildIntervalMatcher = function () {
for (var _i = 0, _a = Object.keys(this.rawIntervalFormats); _i < _a.length; _i++) {
var field = _a[_i];
var group = this.rawIntervalFormats[field];
var m = new skeleton_1.DatePatternMatcher();
for (var _b = 0, _c = Object.keys(group); _b < _c.length; _b++) {
var skeleton = _c[_b];
m.add(this.skeletonParser.parse(skeleton));
var rawSkeleton = _a[_i];
var patterns = this.rawIntervalFormats[rawSkeleton];
if (Object.keys(patterns).length === 0) {
continue;
}
this.intervalMatcher[field] = m;
var skeleton = this.skeletonParser.parse(rawSkeleton);
this.intervalMatcher.add(skeleton, { skeleton: skeleton, patterns: patterns });
}
this.intervalMatcher.sort();
};

@@ -144,0 +135,0 @@ CalendarPatterns.prototype.getTimeData = function () {

@@ -47,11 +47,20 @@ import { DateTimeNode } from '../../parsing/date';

}
export interface DatePatternMatcherEntry<T> {
skeleton: DateSkeleton;
data?: T;
}
export declare const NONE: DatePatternMatcherEntry<any>;
/**
* Cache of date patterns and skeletons with ICU-compatible best-fit matching.
*/
export declare class DatePatternMatcher {
export declare class DatePatternMatcher<T> {
private exact;
private entries;
add(skeleton: DateSkeleton, _pattern?: DateTimeNode[]): void;
match(input: DateSkeleton): DateSkeleton;
add(skeleton: DateSkeleton, data?: T): void;
/**
* Sort entries once they have all been added.
*/
sort(): void;
match(input: DateSkeleton): DatePatternMatcherEntry<T>;
/**
* Make field width adjustments to pattern using the given skeleton.

@@ -58,0 +67,0 @@ */

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DatePatternMatcher = exports.DateSkeletonParser = exports.EMPTY = exports.DateSkeleton = void 0;
exports.DatePatternMatcher = exports.NONE = exports.DateSkeletonParser = exports.EMPTY = exports.DateSkeleton = void 0;
var date_1 = require("../../parsing/date");

@@ -60,13 +60,10 @@ var fields_1 = require("./fields");

var field = info.field;
// Skip day period for backwards-compatibility
if (field !== '' && field !== 'a') {
var repeat = info.repeat;
// Override skeleton repeat for these fields.
if ('GEzvQ'.indexOf(field) !== -1) {
repeat = 1;
}
for (var j = 0; j < repeat; j++) {
r += field;
}
var repeat = info.repeat;
// Override skeleton repeat for these fields.
if ('GEzvQ'.indexOf(field) !== -1) {
repeat = 1;
}
for (var j = 0; j < repeat; j++) {
r += field;
}
}

@@ -176,3 +173,2 @@ }

var n = meta_1[_i];
// Flex types have no static pattern fields
/* istanbul ignore else */

@@ -207,2 +203,5 @@ if (typeof n !== 'string') {

var cmp = function (a, b) { return (a < b ? -1 : a > b ? 1 : 0); };
exports.NONE = {
skeleton: new DateSkeleton(),
};
/**

@@ -218,11 +217,20 @@ * Cache of date patterns and skeletons with ICU-compatible best-fit matching.

}
DatePatternMatcher.prototype.add = function (skeleton, _pattern) {
DatePatternMatcher.prototype.add = function (skeleton, data) {
var key = skeleton.skeleton;
// Avoid adding patterns with duplicate skeletons
if (this.exact[key] === undefined) {
this.exact[key] = skeleton;
this.entries.push(skeleton);
var entry = {
skeleton: skeleton,
data: data,
};
this.exact[key] = entry;
this.entries.push(entry);
}
this.entries.sort(function (a, b) { return cmp(a.skeleton.length, b.skeleton.length); });
};
/**
* Sort entries once they have all been added.
*/
DatePatternMatcher.prototype.sort = function () {
this.entries.sort(function (a, b) { return cmp(a.skeleton.skeleton.length, b.skeleton.skeleton.length); });
};
// TODO: future options to control the match

@@ -234,7 +242,7 @@ DatePatternMatcher.prototype.match = function (input) {

}
var best = exports.EMPTY;
var best = exports.NONE;
var bestDist = Number.MAX_SAFE_INTEGER;
for (var _i = 0, _a = this.entries; _i < _a.length; _i++) {
var entry = _a[_i];
var dist = this.getDistance(entry, input);
var dist = this.getDistance(entry.skeleton, input);
if (dist < bestDist) {

@@ -293,8 +301,2 @@ best = entry;

}
// TODO: UNREACHABLE as field replacement has been selected above
// // Metacharacters have already been replaced in the pattern.
// if ('jJC'.indexOf(adjfield) !== -1) {
// console.log('adjust skeleton', adjfield);
// adjfield = field;
// }
r.push([adjfield, adjwidth]);

@@ -301,0 +303,0 @@ }

@@ -11,2 +11,3 @@ import { DateTimeNode } from '../../parsing/date';

date?: DateTimeNode[];
time?: DateTimeNode[];
range?: DateTimeNode[];

@@ -13,0 +14,0 @@ skeleton?: string;

@@ -21,3 +21,3 @@ "use strict";

(0, instructions_1.vector)('pluralFormats', ['plural-key', "".concat(name, "-plural-format")]),
(0, instructions_1.vector)('intervalFormats', ['date-time-pattern-field', "".concat(name, "-interval-format")]),
(0, instructions_1.vector)('intervalFormats', ["".concat(name, "-interval-format"), 'date-time-pattern-field']),
(0, instructions_1.vector)('dateFormats', ['format-width']),

@@ -24,0 +24,0 @@ (0, instructions_1.vector)('timeFormats', ['format-width']),

@@ -39,3 +39,14 @@ "use strict";

*/
exports.DateTimePatternFieldValues = ['y', 'M', 'd', 'a', 'H', 'm', 's'];
exports.DateTimePatternFieldValues = [
'G',
'y',
'M',
'd',
'a',
'B',
'H',
'h',
'm',
's',
];
/**

@@ -42,0 +53,0 @@ * @public

@@ -132,3 +132,3 @@ import { DateTimePatternFieldType, MetaZoneType } from '@phensley/cldr-types';

*/
fieldOfVisualDifference(other: CalendarDate): DateTimePatternFieldType;
fieldOfVisualDifference(other: CalendarDate): DateTimePatternFieldType | undefined;
/**

@@ -135,0 +135,0 @@ * Compare two dates a and b, returning:

@@ -52,2 +52,3 @@ "use strict";

var differenceFields = [
[2 /* DateField.ERA */, cldr_types_1.DateTimePatternField.ERA],
[4 /* DateField.YEAR */, cldr_types_1.DateTimePatternField.YEAR],

@@ -57,4 +58,5 @@ [7 /* DateField.MONTH */, cldr_types_1.DateTimePatternField.MONTH],

[14 /* DateField.AM_PM */, cldr_types_1.DateTimePatternField.DAYPERIOD],
[16 /* DateField.HOUR */, cldr_types_1.DateTimePatternField.HOUR],
[16 /* DateField.HOUR */, cldr_types_1.DateTimePatternField.HOUR24],
[17 /* DateField.MINUTE */, cldr_types_1.DateTimePatternField.MINUTE],
[18 /* DateField.SECOND */, cldr_types_1.DateTimePatternField.SECOND],
];

@@ -272,4 +274,3 @@ /**

for (var _i = 0, differenceFields_1 = differenceFields; _i < differenceFields_1.length; _i++) {
var pair = differenceFields_1[_i];
var key = pair[0], field = pair[1];
var _a = differenceFields_1[_i], key = _a[0], field = _a[1];
if (a[key] !== b[key]) {

@@ -279,3 +280,3 @@ return field;

}
return cldr_types_1.DateTimePatternField.SECOND;
return undefined;
};

@@ -282,0 +283,0 @@ /**

{
"name": "@phensley/cldr-core",
"version": "1.9.2",
"version": "1.10.0",
"description": "Core library for @phensley/cldr",

@@ -39,19 +39,19 @@ "main": "lib/index.js",

"dependencies": {
"@phensley/cldr-types": "workspace:~1.9.2",
"@phensley/cldr-utils": "workspace:~1.9.2",
"@phensley/decimal": "workspace:~1.9.2",
"@phensley/language-tag": "workspace:~1.9.2",
"@phensley/locale": "workspace:~1.9.2",
"@phensley/locale-matcher": "workspace:~1.9.2",
"@phensley/messageformat": "workspace:~1.9.2",
"@phensley/plurals": "workspace:~1.9.2",
"@phensley/timezone": "workspace:~1.9.2",
"tslib": "^2.7.0"
"@phensley/cldr-types": "workspace:~1.10.0",
"@phensley/cldr-utils": "workspace:~1.10.0",
"@phensley/decimal": "workspace:~1.10.0",
"@phensley/language-tag": "workspace:~1.10.0",
"@phensley/locale": "workspace:~1.10.0",
"@phensley/locale-matcher": "workspace:~1.10.0",
"@phensley/messageformat": "workspace:~1.10.0",
"@phensley/plurals": "workspace:~1.10.0",
"@phensley/timezone": "workspace:~1.10.0",
"tslib": "^2.8.1"
},
"devDependencies": {
"@microsoft/api-extractor": "~7.47.7",
"@types/jest": "^29.5.12",
"@types/node": "^22.5.2",
"@typescript-eslint/eslint-plugin": "^8.4.0",
"@typescript-eslint/parser": "^8.4.0",
"@microsoft/api-extractor": "~7.49.2",
"@types/jest": "^29.5.14",
"@types/node": "^22.13.1",
"@typescript-eslint/eslint-plugin": "^8.23.0",
"@typescript-eslint/parser": "^8.23.0",
"add": "^2.0.6",

@@ -62,10 +62,10 @@ "beautify-benchmark": "^0.2.4",

"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.3",
"jest": "^29.7.0",
"pnpm": "^9.9.0",
"prettier": "^3.3.3",
"pnpm": "^10.2.1",
"prettier": "^3.4.2",
"rimraf": "^6.0.1",
"ts-jest": "^29.2.5",
"typescript": "~5.5.4"
"typescript": "~5.7.3"
},

@@ -72,0 +72,0 @@ "jest": {

{
"name": "@phensley/cldr-core",
"version": "1.9.2",
"version": "1.10.0",
"description": "Core library for @phensley/cldr",

@@ -23,19 +23,19 @@ "main": "lib/index.js",

"dependencies": {
"@phensley/cldr-types": "~1.9.2",
"@phensley/cldr-utils": "~1.9.2",
"@phensley/decimal": "~1.9.2",
"@phensley/language-tag": "~1.9.2",
"@phensley/locale": "~1.9.2",
"@phensley/locale-matcher": "~1.9.2",
"@phensley/messageformat": "~1.9.2",
"@phensley/plurals": "~1.9.2",
"@phensley/timezone": "~1.9.2",
"tslib": "^2.7.0"
"@phensley/cldr-types": "~1.10.0",
"@phensley/cldr-utils": "~1.10.0",
"@phensley/decimal": "~1.10.0",
"@phensley/language-tag": "~1.10.0",
"@phensley/locale": "~1.10.0",
"@phensley/locale-matcher": "~1.10.0",
"@phensley/messageformat": "~1.10.0",
"@phensley/plurals": "~1.10.0",
"@phensley/timezone": "~1.10.0",
"tslib": "^2.8.1"
},
"devDependencies": {
"@microsoft/api-extractor": "~7.47.7",
"@types/jest": "^29.5.12",
"@types/node": "^22.5.2",
"@typescript-eslint/eslint-plugin": "^8.4.0",
"@typescript-eslint/parser": "^8.4.0",
"@microsoft/api-extractor": "~7.49.2",
"@types/jest": "^29.5.14",
"@types/node": "^22.13.1",
"@typescript-eslint/eslint-plugin": "^8.23.0",
"@typescript-eslint/parser": "^8.23.0",
"add": "^2.0.6",

@@ -46,10 +46,10 @@ "beautify-benchmark": "^0.2.4",

"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.3",
"jest": "^29.7.0",
"pnpm": "^9.9.0",
"prettier": "^3.3.3",
"pnpm": "^10.2.1",
"prettier": "^3.4.2",
"rimraf": "^6.0.1",
"ts-jest": "^29.2.5",
"typescript": "~5.5.4"
"typescript": "~5.7.3"
},

@@ -56,0 +56,0 @@ "jest": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc