diff --git a/src/duration.ts b/src/duration.ts index d0d4781..7098bc9 100644 --- a/src/duration.ts +++ b/src/duration.ts @@ -130,28 +130,25 @@ export function roundToSingleUnit(duration: Duration): Duration { let seconds = Math.abs(duration.seconds) let milliseconds = Math.abs(duration.milliseconds) - if (milliseconds >= 500) seconds += Math.round(milliseconds / 1000) + if (milliseconds >= 900) seconds += Math.round(milliseconds / 1000) if (seconds || minutes || hours || days || weeks || months || years) milliseconds = 0 - if (seconds >= 30) minutes += Math.round(seconds / 60) + if (seconds >= 55) minutes += Math.round(seconds / 60) if (minutes || hours || days || weeks || months || years) seconds = 0 - if (minutes >= 30) hours += Math.round(minutes / 60) + if (minutes >= 55) hours += Math.round(minutes / 60) if (hours || days || weeks || months || years) minutes = 0 - if (hours >= 12) days += Math.round(hours / 24) + if (hours >= 21) days += Math.round(hours / 24) if (days || weeks || months || years) hours = 0 - if (days >= 15) months += Math.round(days / 30) + if (days >= 6) weeks += Math.round(days / 7) if (weeks || months || years) days = 0 - if (days >= 4) weeks += Math.round(days / 7) - if (weeks || months || years) days = 0 - - if (weeks >= 2) months += Math.round(weeks / 4) + if (weeks >= 4) months += Math.round(weeks / 4) if (months || years) weeks = 0 - if (months >= 6) years += Math.round(months / 12) + if (months >= 11) years += Math.round(months / 12) if (years) months = 0 const sign = duration.sign diff --git a/test/duration.ts b/test/duration.ts index d55c247..82c0c9f 100644 --- a/test/duration.ts +++ b/test/duration.ts @@ -124,19 +124,35 @@ suite('duration', function () { suite('roundToSingleUnit', function () { const roundTests = new Set([ ['PT20S', 'PT20S'], - ['PT31S', 'PT1M'], + ['PT31S', 'PT31S'], + ['PT55S', 'PT1M'], ['PT1H', 'PT1H'], ['PT1H14M', 'PT1H'], ['PT1H29M', 'PT1H'], - ['PT1H31M', 'PT2H'], - ['PT1H45M', 'PT2H'], + ['PT1H31M', 'PT1H'], + ['PT1H55M', 'PT2H'], + ['PT20H', 'PT20H'], + ['PT21H', 'P1D'], + ['P4D', 'P4D'], ['P6D', 'P1W'], + ['P2W', 'P2W'], + ['P3W3D', 'P3W'], + ['P3W6D', 'P1M'], + ['P21D', 'P3W'], + ['P24D', 'P3W'], + ['P24DT25H', 'P1M'], + ['P25D', 'P1M'], + ['P8M', 'P8M'], + ['P9M', 'P9M'], ['P1M1D', 'P1M'], + ['P9M20DT25H', 'P9M'], + ['P9M24DT25H', 'P10M'], + ['P11M', 'P1Y'], ['P1Y4D', 'P1Y'], ['P1Y5M13D', 'P1Y'], - ['P1Y5M15D', 'P2Y'], - ['P1Y5M20D', 'P2Y'], - ['P1Y6M', 'P2Y'], + ['P1Y5M15D', 'P1Y'], + ['P1Y5M20D', 'P1Y'], + ['P1Y11M', 'P2Y'], ]) for (const [input, expected] of roundTests) { test(`roundToSingleUnit(${input}) === ${expected}`, () => { @@ -151,19 +167,35 @@ suite('duration', function () { suite('getRelativeTimeUnit', function () { const relativeTests = new Set([ ['PT20S', [20, 'second']], - ['PT31S', [1, 'minute']], + ['PT31S', [31, 'second']], + ['PT55S', [1, 'minute']], ['PT1H', [1, 'hour']], ['PT1H14M', [1, 'hour']], ['PT1H29M', [1, 'hour']], - ['PT1H31M', [2, 'hour']], - ['PT1H45M', [2, 'hour']], + ['PT1H31M', [1, 'hour']], + ['PT1H55M', [2, 'hour']], + ['PT20H', [20, 'hour']], + ['PT21H', [1, 'day']], + ['P4D', [4, 'day']], ['P6D', [1, 'week']], + ['P2W', [2, 'week']], + ['P3W3D', [3, 'week']], + ['P3W6D', [1, 'month']], + ['P21D', [3, 'week']], + ['P24D', [3, 'week']], + ['P24DT25H', [1, 'month']], + ['P25D', [1, 'month']], + ['P8M', [8, 'month']], + ['P9M', [9, 'month']], ['P1M1D', [1, 'month']], + ['P9M20DT25H', [9, 'month']], + ['P9M24DT25H', [10, 'month']], + ['P11M', [1, 'year']], ['P1Y4D', [1, 'year']], ['P1Y5M13D', [1, 'year']], - ['P1Y5M15D', [2, 'year']], - ['P1Y5M20D', [2, 'year']], - ['P1Y6M', [2, 'year']], + ['P1Y5M15D', [1, 'year']], + ['P1Y5M20D', [1, 'year']], + ['P1Y11M', [2, 'year']], ]) for (const [input, [val, unit]] of relativeTests) { test(`roundToSingleUnit(${input}) === [${val}, ${unit}]`, () => { diff --git a/test/relative-time.js b/test/relative-time.js index 849b8b2..ed37606 100644 --- a/test/relative-time.js +++ b/test/relative-time.js @@ -472,7 +472,7 @@ suite('relative-time', function () { timeElement.setAttribute('tense', 'past') timeElement.setAttribute('datetime', then) await Promise.resolve() - assert.equal(timeElement.shadowRoot.textContent, '2 years ago') + assert.equal(timeElement.shadowRoot.textContent, 'last year') }) test('micro formats years', async () => { @@ -762,9 +762,9 @@ suite('relative-time', function () { {datetime: '2022-10-24T14:46:08.000Z', format: 'duration', tense: 'past', expected: '0 seconds'}, // 50 seconds in the future - {datetime: '2022-10-24T14:46:50.000Z', tense: 'future', format: 'relative', expected: 'in 1 minute'}, + {datetime: '2022-10-24T14:46:50.000Z', tense: 'future', format: 'relative', expected: 'in 50 seconds'}, {datetime: '2022-10-24T14:46:50.000Z', tense: 'past', format: 'relative', expected: 'now'}, - {datetime: '2022-10-24T14:46:50.000Z', format: 'relative', formatStyle: 'narrow', expected: 'in 1 min.'}, + {datetime: '2022-10-24T14:46:50.000Z', format: 'relative', formatStyle: 'narrow', expected: 'in 50 sec.'}, {datetime: '2022-10-24T14:46:50.000Z', format: 'relative', precision: 'hour', expected: 'now'}, {datetime: '2022-10-24T14:46:50.000Z', format: 'relative', threshold: 'PT0S', expected: 'on Oct 24'}, {datetime: '2022-10-24T14:46:50.000Z', format: 'datetime', expected: 'Mon, Oct 24'}, @@ -775,9 +775,9 @@ suite('relative-time', function () { {datetime: '2022-10-24T14:46:50.000Z', format: 'duration', tense: 'past', expected: '0 seconds'}, // 90 seconds in the future - {datetime: '2022-10-24T14:47:30.000Z', tense: 'future', format: 'relative', expected: 'in 2 minutes'}, + {datetime: '2022-10-24T14:47:30.000Z', tense: 'future', format: 'relative', expected: 'in 1 minute'}, {datetime: '2022-10-24T14:47:30.000Z', tense: 'past', format: 'relative', expected: 'now'}, - {datetime: '2022-10-24T14:47:30.000Z', format: 'relative', formatStyle: 'narrow', expected: 'in 2 min.'}, + {datetime: '2022-10-24T14:47:30.000Z', format: 'relative', formatStyle: 'narrow', expected: 'in 1 min.'}, {datetime: '2022-10-24T14:47:30.000Z', format: 'relative', precision: 'hour', expected: 'now'}, {datetime: '2022-10-24T14:47:30.000Z', format: 'relative', threshold: 'PT0S', expected: 'on Oct 24'}, {datetime: '2022-10-24T14:47:30.000Z', format: 'datetime', expected: 'Mon, Oct 24'}, @@ -788,10 +788,10 @@ suite('relative-time', function () { {datetime: '2022-10-24T14:47:30.000Z', format: 'duration', tense: 'past', expected: '0 seconds'}, // 20 days in the future - {datetime: '2022-11-13T15:46:00.000Z', tense: 'future', format: 'relative', expected: 'next month'}, + {datetime: '2022-11-13T15:46:00.000Z', tense: 'future', format: 'relative', expected: 'in 3 weeks'}, {datetime: '2022-11-13T15:46:00.000Z', tense: 'past', format: 'relative', expected: 'now'}, - {datetime: '2022-11-13T15:46:00.000Z', format: 'relative', formatStyle: 'narrow', expected: 'next mo.'}, - {datetime: '2022-11-13T15:46:00.000Z', format: 'relative', precision: 'hour', expected: 'next month'}, + {datetime: '2022-11-13T15:46:00.000Z', format: 'relative', formatStyle: 'narrow', expected: 'in 3 wk.'}, + {datetime: '2022-11-13T15:46:00.000Z', format: 'relative', precision: 'hour', expected: 'in 3 weeks'}, {datetime: '2022-11-13T15:46:00.000Z', format: 'relative', threshold: 'PT0S', expected: 'on Nov 13'}, {datetime: '2022-11-13T15:46:00.000Z', format: 'datetime', expected: 'Sun, Nov 13'}, {datetime: '2022-11-13T15:46:00.000Z', format: 'duration', expected: '20 days, 1 hour'}, @@ -846,8 +846,8 @@ suite('relative-time', function () { // 50 seconds in the past {datetime: '2022-10-24T14:45:10.000Z', tense: 'future', format: 'relative', expected: 'now'}, - {datetime: '2022-10-24T14:45:10.000Z', tense: 'past', format: 'relative', expected: '1 minute ago'}, - {datetime: '2022-10-24T14:45:10.000Z', format: 'relative', formatStyle: 'narrow', expected: '1 min. ago'}, + {datetime: '2022-10-24T14:45:10.000Z', tense: 'past', format: 'relative', expected: 'now'}, + {datetime: '2022-10-24T14:45:10.000Z', format: 'relative', formatStyle: 'narrow', expected: 'now'}, {datetime: '2022-10-24T14:45:10.000Z', format: 'relative', precision: 'hour', expected: 'now'}, {datetime: '2022-10-24T14:45:10.000Z', format: 'relative', threshold: 'PT0S', expected: 'on Oct 24'}, {datetime: '2022-10-24T14:45:10.000Z', format: 'datetime', expected: 'Mon, Oct 24'}, @@ -859,8 +859,8 @@ suite('relative-time', function () { // 90 seconds in the past {datetime: '2022-10-24T14:44:30.000Z', tense: 'future', format: 'relative', expected: 'now'}, - {datetime: '2022-10-24T14:44:30.000Z', tense: 'past', format: 'relative', expected: '2 minutes ago'}, - {datetime: '2022-10-24T14:44:30.000Z', format: 'relative', formatStyle: 'narrow', expected: '2 min. ago'}, + {datetime: '2022-10-24T14:44:30.000Z', tense: 'past', format: 'relative', expected: '1 minute ago'}, + {datetime: '2022-10-24T14:44:30.000Z', format: 'relative', formatStyle: 'narrow', expected: '1 min. ago'}, {datetime: '2022-10-24T14:44:30.000Z', format: 'relative', precision: 'hour', expected: 'now'}, {datetime: '2022-10-24T14:44:30.000Z', format: 'relative', threshold: 'PT0S', expected: 'on Oct 24'}, {datetime: '2022-10-24T14:44:30.000Z', format: 'datetime', expected: 'Mon, Oct 24'}, @@ -872,9 +872,9 @@ suite('relative-time', function () { // 20 days in the past {datetime: '2022-10-04T14:46:00.000Z', tense: 'future', format: 'relative', expected: 'now'}, - {datetime: '2022-10-04T14:46:00.000Z', tense: 'past', format: 'relative', expected: 'last month'}, - {datetime: '2022-10-04T14:46:00.000Z', format: 'relative', formatStyle: 'narrow', expected: 'last mo.'}, - {datetime: '2022-10-04T14:46:00.000Z', format: 'relative', precision: 'hour', expected: 'last month'}, + {datetime: '2022-10-04T14:46:00.000Z', tense: 'past', format: 'relative', expected: '3 weeks ago'}, + {datetime: '2022-10-04T14:46:00.000Z', format: 'relative', formatStyle: 'narrow', expected: '3 wk. ago'}, + {datetime: '2022-10-04T14:46:00.000Z', format: 'relative', precision: 'hour', expected: '3 weeks ago'}, {datetime: '2022-10-04T14:46:00.000Z', format: 'relative', threshold: 'PT0S', expected: 'on Oct 4'}, {datetime: '2022-10-04T14:46:00.000Z', format: 'datetime', expected: 'Tue, Oct 4'}, {datetime: '2022-10-04T14:46:00.000Z', format: 'duration', expected: '20 days'}, @@ -958,13 +958,13 @@ suite('relative-time', function () { {datetime: '2022-10-24T15:46:00.000Z', tense: 'future', format: 'micro', expected: '1h'}, {datetime: '2022-10-24T16:00:00.000Z', tense: 'future', format: 'micro', expected: '1h'}, {datetime: '2022-10-24T16:15:00.000Z', tense: 'future', format: 'micro', expected: '1h'}, - {datetime: '2022-10-24T16:31:00.000Z', tense: 'future', format: 'micro', expected: '2h'}, + {datetime: '2022-10-24T16:31:00.000Z', tense: 'future', format: 'micro', expected: '1h'}, {datetime: '2022-10-30T14:46:00.000Z', tense: 'future', format: 'micro', expected: '1w'}, {datetime: '2022-11-24T14:46:00.000Z', tense: 'future', format: 'micro', expected: '1m'}, {datetime: '2023-10-23T14:46:00.000Z', tense: 'future', format: 'micro', expected: '1y'}, {datetime: '2023-10-24T14:46:00.000Z', tense: 'future', format: 'micro', expected: '1y'}, {datetime: '2024-03-31T14:46:00.000Z', tense: 'future', format: 'micro', expected: '1y'}, - {datetime: '2024-04-01T14:46:00.000Z', tense: 'future', format: 'micro', expected: '2y'}, + {datetime: '2024-04-01T14:46:00.000Z', tense: 'future', format: 'micro', expected: '1y'}, // Dates in the future {datetime: '2022-11-24T14:46:00.000Z', tense: 'past', format: 'micro', expected: '1m'}, @@ -975,13 +975,13 @@ suite('relative-time', function () { {datetime: '2022-10-24T13:46:00.000Z', tense: 'past', format: 'micro', expected: '1h'}, {datetime: '2022-10-24T13:30:00.000Z', tense: 'past', format: 'micro', expected: '1h'}, {datetime: '2022-10-24T13:17:00.000Z', tense: 'past', format: 'micro', expected: '1h'}, - {datetime: '2022-10-24T13:01:00.000Z', tense: 'past', format: 'micro', expected: '2h'}, + {datetime: '2022-10-24T13:01:00.000Z', tense: 'past', format: 'micro', expected: '1h'}, {datetime: '2022-10-18T14:46:00.000Z', tense: 'past', format: 'micro', expected: '1w'}, {datetime: '2022-09-23T14:46:00.000Z', tense: 'past', format: 'micro', expected: '1m'}, {datetime: '2021-10-25T14:46:00.000Z', tense: 'past', format: 'micro', expected: '1y'}, {datetime: '2021-10-24T14:46:00.000Z', tense: 'past', format: 'micro', expected: '1y'}, {datetime: '2021-05-18T14:46:00.000Z', tense: 'past', format: 'micro', expected: '1y'}, - {datetime: '2021-05-17T14:46:00.000Z', tense: 'past', format: 'micro', expected: '2y'}, + {datetime: '2021-05-17T14:46:00.000Z', tense: 'past', format: 'micro', expected: '1y'}, // Elapsed Times {datetime: '2022-10-24T14:46:10.000Z', format: 'elapsed', expected: '10s'}, @@ -1011,23 +1011,23 @@ suite('relative-time', function () { {datetime: '2022-10-24T15:46:00.000Z', tense: 'future', format: 'auto', expected: 'in 1 hour'}, {datetime: '2022-10-24T16:00:00.000Z', tense: 'future', format: 'auto', expected: 'in 1 hour'}, {datetime: '2022-10-24T16:15:00.000Z', tense: 'future', format: 'auto', expected: 'in 1 hour'}, - {datetime: '2022-10-24T16:31:00.000Z', tense: 'future', format: 'auto', expected: 'in 2 hours'}, + {datetime: '2022-10-24T16:31:00.000Z', tense: 'future', format: 'auto', expected: 'in 1 hour'}, {datetime: '2022-10-30T14:46:00.000Z', tense: 'future', format: 'auto', expected: 'next week'}, {datetime: '2022-11-24T14:46:00.000Z', tense: 'future', format: 'auto', expected: 'next month'}, {datetime: '2023-10-23T14:46:00.000Z', tense: 'future', format: 'auto', expected: 'next year'}, {datetime: '2023-10-24T14:46:00.000Z', tense: 'future', format: 'auto', expected: 'next year'}, {datetime: '2024-03-31T14:46:00.000Z', tense: 'future', format: 'auto', expected: 'next year'}, - {datetime: '2024-04-01T14:46:00.000Z', tense: 'future', format: 'auto', expected: 'in 2 years'}, + {datetime: '2024-04-01T14:46:00.000Z', tense: 'future', format: 'auto', expected: 'next year'}, {datetime: '2022-10-24T15:46:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'in 1 hr.'}, {datetime: '2022-10-24T16:00:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'in 1 hr.'}, {datetime: '2022-10-24T16:15:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'in 1 hr.'}, - {datetime: '2022-10-24T16:31:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'in 2 hr.'}, + {datetime: '2022-10-24T16:31:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'in 1 hr.'}, {datetime: '2022-10-30T14:46:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'next wk.'}, {datetime: '2022-11-24T14:46:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'next mo.'}, {datetime: '2023-10-23T14:46:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'next yr.'}, {datetime: '2023-10-24T14:46:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'next yr.'}, {datetime: '2024-03-31T14:46:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'next yr.'}, - {datetime: '2024-04-01T14:46:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'in 2 yr.'}, + {datetime: '2024-04-01T14:46:00.000Z', lang: 'en', tense: 'future', formatStyle: 'narrow', expected: 'next yr.'}, // Dates in the future {datetime: '2022-11-24T14:46:00.000Z', tense: 'past', format: 'auto', expected: 'now'}, @@ -1038,23 +1038,23 @@ suite('relative-time', function () { {datetime: '2022-10-24T13:46:00.000Z', tense: 'past', format: 'auto', expected: '1 hour ago'}, {datetime: '2022-10-24T13:30:00.000Z', tense: 'past', format: 'auto', expected: '1 hour ago'}, {datetime: '2022-10-24T13:17:00.000Z', tense: 'past', format: 'auto', expected: '1 hour ago'}, - {datetime: '2022-10-24T13:01:00.000Z', tense: 'past', format: 'auto', expected: '2 hours ago'}, + {datetime: '2022-10-24T13:01:00.000Z', tense: 'past', format: 'auto', expected: '1 hour ago'}, {datetime: '2022-10-18T14:46:00.000Z', tense: 'past', format: 'auto', expected: 'last week'}, {datetime: '2022-09-23T14:46:00.000Z', tense: 'past', format: 'auto', expected: 'last month'}, {datetime: '2021-10-25T14:46:00.000Z', tense: 'past', format: 'auto', expected: 'last year'}, {datetime: '2021-10-24T14:46:00.000Z', tense: 'past', format: 'auto', expected: 'last year'}, {datetime: '2021-05-18T14:46:00.000Z', tense: 'past', format: 'auto', expected: 'last year'}, - {datetime: '2021-05-17T14:46:00.000Z', tense: 'past', format: 'auto', expected: '2 years ago'}, + {datetime: '2021-05-17T14:46:00.000Z', tense: 'past', format: 'auto', expected: 'last year'}, {datetime: '2022-10-24T13:46:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: '1 hr. ago'}, {datetime: '2022-10-24T13:30:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: '1 hr. ago'}, {datetime: '2022-10-24T13:17:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: '1 hr. ago'}, - {datetime: '2022-10-24T13:01:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: '2 hr. ago'}, + {datetime: '2022-10-24T13:01:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: '1 hr. ago'}, {datetime: '2022-10-18T14:46:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: 'last wk.'}, {datetime: '2022-09-23T14:46:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: 'last mo.'}, {datetime: '2021-10-25T14:46:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: 'last yr.'}, {datetime: '2021-10-24T14:46:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: 'last yr.'}, {datetime: '2021-05-18T14:46:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: 'last yr.'}, - {datetime: '2021-05-17T14:46:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: '2 yr. ago'}, + {datetime: '2021-05-17T14:46:00.000Z', lang: 'en', tense: 'past', formatStyle: 'narrow', expected: 'last yr.'}, // Edge case dates {