diff --git a/README.md b/README.md index 4810707..ea20eed 100644 --- a/README.md +++ b/README.md @@ -273,7 +273,7 @@ This will used to determine the length of the unit names. This value is passed t | relative | narrow | in 1 mo. | | duration | long | 1 month, 2 days, 4 hours | | duration | short | 1 mth, 2 days, 4 hr | -| duration | narrow | 1m 2d 4h | +| duration | narrow | 1mo 2d 4h | ##### second, minute, hour, weekday, day, month, year, timeZoneName diff --git a/src/duration-format-ponyfill.ts b/src/duration-format-ponyfill.ts index 15ccd7d..122e061 100644 --- a/src/duration-format-ponyfill.ts +++ b/src/duration-format-ponyfill.ts @@ -110,7 +110,15 @@ export default class DurationFormat { : unitStyle === 'numeric' ? {} : {style: 'unit', unit: nfUnit, unitDisplay: unitStyle} - list.push(new Intl.NumberFormat(locale, nfOpts).format(value)) + + let formattedValue = new Intl.NumberFormat(locale, nfOpts).format(value) + + // Custom handling for narrow month formatting to use "mo" instead of "m" + if (unit === 'months' && (unitStyle === 'narrow' || (style === 'narrow' && formattedValue.endsWith('m')))) { + formattedValue = formattedValue.replace(/(\d+)m$/, '$1mo') + } + + list.push(formattedValue) } return new ListFormat(locale, { type: 'unit', diff --git a/src/relative-time-element.ts b/src/relative-time-element.ts index 7af34a9..b704ad8 100644 --- a/src/relative-time-element.ts +++ b/src/relative-time-element.ts @@ -170,7 +170,11 @@ export class RelativeTimeElement extends HTMLElement implements Intl.DateTimeFor if (format === 'micro') { duration = roundToSingleUnit(duration) empty = microEmptyDuration - if ((this.tense === 'past' && duration.sign !== -1) || (this.tense === 'future' && duration.sign !== 1)) { + // Allow month-level durations to pass through even with mismatched tense + if ( + duration.months === 0 && + ((this.tense === 'past' && duration.sign !== -1) || (this.tense === 'future' && duration.sign !== 1)) + ) { duration = microEmptyDuration } } else if ((tense === 'past' && duration.sign !== -1) || (tense === 'future' && duration.sign !== 1)) { diff --git a/test/duration-format-ponyfill.ts b/test/duration-format-ponyfill.ts index 5aaf496..94f018c 100644 --- a/test/duration-format-ponyfill.ts +++ b/test/duration-format-ponyfill.ts @@ -37,7 +37,7 @@ suite('duration format ponyfill', function () { locale: 'en', style: 'narrow', parts: [ - {type: 'element', value: '1m'}, + {type: 'element', value: '1mo'}, {type: 'literal', value: ' '}, {type: 'element', value: '2d'}, {type: 'literal', value: ' '}, @@ -92,6 +92,20 @@ suite('duration format ponyfill', function () { {type: 'element', value: '8s'}, ], }, + { + duration: 'P1M2DT3M30S', + locale: 'en', + style: 'narrow', + parts: [ + {type: 'element', value: '1mo'}, + {type: 'literal', value: ' '}, + {type: 'element', value: '2d'}, + {type: 'literal', value: ' '}, + {type: 'element', value: '3m'}, + {type: 'literal', value: ' '}, + {type: 'element', value: '30s'}, + ], + }, ]) for (const {duration, locale, parts, ...opts} of tests) { diff --git a/test/relative-time.js b/test/relative-time.js index 67e5cd7..ee87ea2 100644 --- a/test/relative-time.js +++ b/test/relative-time.js @@ -561,6 +561,17 @@ suite('relative-time', function () { await Promise.resolve() assert.equal(time.shadowRoot.textContent, '1d') }) + + test('micro formats months', async () => { + const datetime = new Date() + datetime.setMonth(datetime.getMonth() - 2) + const time = document.createElement('relative-time') + time.setAttribute('tense', 'past') + time.setAttribute('datetime', datetime) + time.setAttribute('format', 'micro') + await Promise.resolve() + assert.equal(time.shadowRoot.textContent, '2mo') + }) }) suite('[tense=future]', function () { @@ -1941,7 +1952,7 @@ suite('relative-time', function () { datetime: '2022-09-24T14:46:00.000Z', tense: 'future', format: 'micro', - expected: '1m', + expected: '1mo', }, { datetime: '2022-10-23T14:46:00.000Z', @@ -1991,7 +2002,7 @@ suite('relative-time', function () { datetime: '2022-11-24T14:46:00.000Z', tense: 'future', format: 'micro', - expected: '1m', + expected: '1mo', }, { datetime: '2023-10-23T14:46:00.000Z', @@ -2023,7 +2034,7 @@ suite('relative-time', function () { datetime: '2022-11-24T14:46:00.000Z', tense: 'past', format: 'micro', - expected: '1m', + expected: '1mo', }, { datetime: '2022-10-25T14:46:00.000Z', @@ -2073,7 +2084,7 @@ suite('relative-time', function () { datetime: '2022-09-23T14:46:00.000Z', tense: 'past', format: 'micro', - expected: '1m', + expected: '1mo', }, { datetime: '2021-10-25T14:46:00.000Z', @@ -2178,13 +2189,13 @@ suite('relative-time', function () { { datetime: '2021-10-30T14:46:00.000Z', format: 'elapsed', - expected: '11m 29d', + expected: '11mo 29d', }, { datetime: '2021-10-30T14:46:00.000Z', format: 'elapsed', precision: 'month', - expected: '11m', + expected: '11mo', }, { datetime: '2021-10-29T14:46:00.000Z',