Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,27 @@ export function elapsedTime(date: Date, precision: Unit = 'second', now = Date.n
const delta = date.getTime() - now
if (delta === 0) return new Duration()
const sign = Math.sign(delta)
const ms = Math.abs(delta)
// Months below are approximated as 30 days, so a year is 360 days long. Over many years that drift adds up to
// whole extra years, so count the whole calendar years first and only approximate what is left over.
const earlier = new Date(sign < 0 ? date : now)
const later = new Date(sign < 0 ? now : date)
let calendarYears = later.getUTCFullYear() - earlier.getUTCFullYear()
while (calendarYears > 0 && applyDuration(earlier, new Duration(calendarYears)) > later) calendarYears -= 1
const ms =
calendarYears > 0
? later.getTime() - applyDuration(earlier, new Duration(calendarYears)).getTime()
: Math.abs(delta)
const sec = Math.floor(ms / 1000)
const min = Math.floor(sec / 60)
const hr = Math.floor(min / 60)
const day = Math.floor(hr / 24)
const month = Math.floor(day / 30)
const year = Math.floor(month / 12)
const extraYears = Math.floor(month / 12)
const year = Math.max(calendarYears, 0) + extraYears
Comment on lines +167 to +168
const i = unitNames.indexOf(precision)
return new Duration(
i >= 0 ? year * sign : 0,
i >= 1 ? (month - year * 12) * sign : 0,
i >= 1 ? (month - extraYears * 12) * sign : 0,
0,
i >= 3 ? (day - month * 30) * sign : 0,
i >= 4 ? (hr - day * 24) * sign : 0,
Expand Down
15 changes: 15 additions & 0 deletions test/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,21 @@ suite('duration', function () {
input: '2023-03-21T16:03:00.000Z',
expected: '-P1DT20H',
},
{
now: '2025-02-06T12:00:00.000Z',
input: '2015-02-14T05:13:48.000Z',
expected: '-P9Y11M28DT6H46M12S',
},
{
now: '2025-01-01T00:00:00.000Z',
input: '2020-01-01T00:00:00.000Z',
expected: '-P5Y',
},
{
now: '2025-02-06T00:00:00.000Z',
input: '2035-02-14T00:00:00.000Z',
expected: 'P10Y8D',
},
{
now: '2022-10-24T14:46:00.000Z',
input: '2024-10-24T14:46:00.000Z',
Expand Down
40 changes: 27 additions & 13 deletions test/relative-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ suite('relative-time', function () {
time.setAttribute('tense', 'past')
time.setAttribute('datetime', '2023-01-01T00:00:00Z')
await Promise.resolve()
assert.equal(time.shadowRoot.textContent, '11 years ago')
assert.equal(time.shadowRoot.textContent, '10 years ago')
})

test('rewrites from now past datetime to minutes ago', async () => {
Expand Down Expand Up @@ -842,9 +842,25 @@ suite('relative-time', function () {
assert.equal(time.shadowRoot.textContent, '3 months ago')
})

test('does not count an extra year for dates many years in the past', async () => {
freezeTime(new Date('2025-02-06T12:00:00Z'))
const time = document.createElement('relative-time')
time.setAttribute('tense', 'past')
time.setAttribute('datetime', '2015-02-14T15:13:48+05:00')
await Promise.resolve()
assert.equal(time.shadowRoot.textContent, '10 years ago')
})

test('does not count an extra year for exact multiples of five years', async () => {
freezeTime(new Date('2025-01-01T00:00:00Z'))
const time = document.createElement('relative-time')
time.setAttribute('tense', 'past')
time.setAttribute('datetime', '2020-01-01T00:00:00Z')
await Promise.resolve()
assert.equal(time.shadowRoot.textContent, '5 years ago')
})

test('micro formats years', async () => {
// FIXME: there is still a bug, if the duration is long enough (say, 10 or 100 years)
// then the `month = Math.floor(day / 30)` in elapsedTime causes errors, then "10 years" would output "11y"
const now = new Date(Date.now() - 2 * 365 * 24 * 60 * 60 * 1000).toISOString()
const time = document.createElement('relative-time')
time.setAttribute('tense', 'past')
Expand Down Expand Up @@ -946,8 +962,6 @@ suite('relative-time', function () {
})

test('micro formats years', async () => {
// FIXME: there is still a bug, if the duration is long enough (say, 10 or 100 years)
// then the `month = Math.floor(day / 30)` in elapsedTime causes errors, then "10 years" would output "11y"
const now = new Date(Date.now() + 2 * 365 * 24 * 60 * 60 * 1000).toISOString()
const time = document.createElement('relative-time')
time.setAttribute('tense', 'future')
Expand Down Expand Up @@ -1684,7 +1698,7 @@ suite('relative-time', function () {
{
datetime: '2024-10-24T14:46:00.000Z',
format: 'duration',
expected: '2 years, 11 days',
expected: '2 years',
},
{
datetime: '2024-10-24T14:46:00.000Z',
Expand All @@ -1696,19 +1710,19 @@ suite('relative-time', function () {
datetime: '2024-10-24T14:46:00.000Z',
format: 'duration',
precision: 'minute',
expected: '2 years, 11 days',
expected: '2 years',
},
{
datetime: '2024-10-24T14:46:00.000Z',
format: 'duration',
precision: 'day',
expected: '2 years, 11 days',
expected: '2 years',
},
{
datetime: '2024-10-24T14:46:00.000Z',
format: 'duration',
tense: 'future',
expected: '2 years, 11 days',
expected: '2 years',
},
{
datetime: '2024-10-24T14:46:00.000Z',
Expand Down Expand Up @@ -2140,19 +2154,19 @@ suite('relative-time', function () {
{
datetime: '2020-10-24T14:46:00.000Z',
format: 'duration',
expected: '2 years, 10 days',
expected: '2 years',
},
{
datetime: '2020-10-24T14:46:00.000Z',
format: 'duration',
precision: 'minute',
expected: '2 years, 10 days',
expected: '2 years',
},
{
datetime: '2020-10-24T14:46:00.000Z',
format: 'duration',
precision: 'day',
expected: '2 years, 10 days',
expected: '2 years',
},
{
datetime: '2020-10-24T14:46:00.000Z',
Expand All @@ -2164,7 +2178,7 @@ suite('relative-time', function () {
datetime: '2020-10-24T14:46:00.000Z',
format: 'duration',
tense: 'past',
expected: '2 years, 10 days',
expected: '2 years',
},
{
reference: '2023-03-23T12:03:00.000Z',
Expand Down