Skip to content

Commit

Permalink
Merge pull request #249 from github/tweak-rounding-rules-for-months
Browse files Browse the repository at this point in the history
tweak rounding rules for months
  • Loading branch information
keithamus committed Feb 7, 2023
2 parents cce3194 + d39c73e commit 244af66
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 41 deletions.
25 changes: 17 additions & 8 deletions src/duration.ts
Expand Up @@ -150,20 +150,29 @@ export function roundToSingleUnit(duration: Duration, {relativeTo = Date.now()}:
if (hours >= 21) days += Math.round(hours / 24)
if (days || weeks || months || years) hours = 0

const currentYear = relativeTo.getFullYear()
let currentMonth = relativeTo.getMonth()
const currentDate = relativeTo.getDate()
if (days >= 27 || (years + months && days)) {
relativeTo.setDate(currentDate + days * sign)
days = 0
months += Math.abs(
relativeTo.getFullYear() >= currentYear
? relativeTo.getMonth() - currentMonth
: relativeTo.getMonth() - currentMonth - 12,
)
currentMonth = relativeTo.getMonth()
}

if (days >= 6) weeks += Math.round(days / 7)
if (weeks || months || years) days = 0

if (weeks >= 4) months += Math.round(weeks / 4)
if (months || years) weeks = 0

const currentMonth = relativeTo.getMonth()
const delta = sign < 0 ? currentMonth : 12 - currentMonth
if (months && months >= delta) {
years += 1
relativeTo.setFullYear(relativeTo.getFullYear() + sign)
relativeTo.setMonth(0)
months -= delta
years += Math.floor(months / 12)
if (months >= 11 || (years && months)) {
relativeTo.setMonth(relativeTo.getMonth() + months * sign)
years += Math.abs(currentYear - relativeTo.getFullYear())
}
if (years) months = 0

Expand Down
102 changes: 73 additions & 29 deletions test/duration.ts
Expand Up @@ -235,41 +235,72 @@ suite('duration', function () {
['PT1H55M', 'PT2H'],
['PT20H', 'PT20H'],
['PT21H', 'P1D'],
['P4D', 'P4D'],
['P6D', 'P1W'],
['P2W', 'P2W'],
['P3W3D', 'P3W'],
['P3W6D', 'P1M'],
['P21D', 'P3W'],
['P24D', 'P3W'],
['P24DT25H', 'P1M'],
['P25D', 'P1M'],
['P1M1D', 'P1M'],
['P4D', 'P4D', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P4D', '-P4D', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P6D', 'P1W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P6D', '-P1W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P2W', 'P2W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P2W', '-P2W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P3W3D', 'P3W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P3W3D', '-P3W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P3W6D', 'P1M', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P3W6D', '-P1M', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P21D', 'P3W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P21D', '-P3W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P24D', 'P3W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P24D', '-P3W', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P24DT25H', 'P1M', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P24DT25H', '-P1M', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P25D', 'P1M', {relativeTo: new Date('2023-07-01T00:00:00')}],
['-P25D', '-P1M', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P1M1D', 'P1M', {relativeTo: new Date('2023-07-02T00:00:00')}],
['-P1M1D', '-P1M', {relativeTo: new Date('2023-07-02T00:00:00')}],
['P1M1D', 'P2M', {relativeTo: new Date('2023-07-31T00:00:00')}],
['-P1M1D', '-P2M', {relativeTo: new Date('2023-07-01T00:00:00')}],
['P1D', 'P1D', {relativeTo: new Date('2022-01-01T00:00:00Z')}],
['-P1D', '-P1D', {relativeTo: new Date('2022-01-01T00:00:00Z')}],
['P8M', 'P8M', {relativeTo: new Date('2022-01-01T00:00:00Z')}],
['-P8M', '-P8M', {relativeTo: new Date('2022-10-01T00:00:00Z')}],
['P9M', 'P9M', {relativeTo: new Date('2022-01-01T00:00:00Z')}],
['-P9M', '-P9M', {relativeTo: new Date('2022-11-01T00:00:00Z')}],
['-P1M', '-P1Y', {relativeTo: new Date('2023-01-01T00:00:00Z')}],
['P1M', 'P1Y', {relativeTo: new Date('2023-12-01T00:00:00Z')}],
['P1M', 'P1M', {relativeTo: new Date('2023-12-01T00:00:00Z')}],
['-P1M', '-P1M', {relativeTo: new Date('2023-01-01T00:00:00Z')}],
['P1M15D', 'P1M', {relativeTo: new Date('2023-12-01T00:00:00Z')}],
['-P1M15D', '-P2M', {relativeTo: new Date('2023-01-01T00:00:00Z')}],
['P1M15D', 'P2M', {relativeTo: new Date('2023-01-18T00:00:00Z')}],
['-P1M15D', '-P2M', {relativeTo: new Date('2023-01-01T00:00:00Z')}],
['P1M15D', 'P2M', {relativeTo: new Date('2023-01-18T00:00:00Z')}],
['-P18M', '-P2Y', {relativeTo: new Date('2023-01-01T00:00:00Z')}],
['P18M', 'P2Y', {relativeTo: new Date('2023-12-01T00:00:00Z')}],
['-P18M', '-P2Y', {relativeTo: new Date('2023-07-01T00:00:00Z')}],
['-P18M', '-P1Y', {relativeTo: new Date('2023-07-01T00:00:00Z')}],
['P18M', 'P2Y', {relativeTo: new Date('2023-07-01T00:00:00Z')}],
['-P18M', '-P1Y', {relativeTo: new Date('2023-08-01T00:00:00Z')}],
['P18M', 'P1Y', {relativeTo: new Date('2023-03-01T00:00:00Z')}],
['-P9M20DT25H', '-P9M', {relativeTo: new Date('2023-11-12T00:00:00Z')}],
['P9M20DT25H', 'P9M', {relativeTo: new Date('2023-01-12T00:00:00Z')}],
[
'-P9M20DT25H',
'-P10M',
{
relativeTo: new Date('2023-11-12T00:00:00Z'),
},
],
['P9M20DT25H', 'P10M', {relativeTo: new Date('2023-01-12T00:00:00Z')}],
['P11M', 'P1Y', {relativeTo: new Date('2022-11-01T00:00:00Z')}],
['-P11M', '-P1Y', {relativeTo: new Date('2022-11-01T00:00:00Z')}],
['P1Y4D', 'P1Y', {relativeTo: new Date('2022-11-01T00:00:00Z')}],
['P1Y5M13D', 'P1Y', {relativeTo: new Date('2023-01-01T00:00:00Z')}],
['P1Y5M15D', 'P1Y', {relativeTo: new Date('2023-01-01T00:00:00Z')}],
['P1Y5M20D', 'P1Y', {relativeTo: new Date('2023-01-01T00:00:00Z')}],
['P1Y10M', 'P2Y', {relativeTo: new Date('2022-11-01T00:00:00Z')}],
['-P1Y10M', '-P2Y', {relativeTo: new Date('2022-11-01T00:00:00Z')}],
['-P1Y10M', '-P1Y', {relativeTo: new Date('2022-11-01T00:00:00Z')}],
['P1Y10M', 'P1Y', {relativeTo: new Date('2022-01-01T00:00:00Z')}],
['-P1Y10M', '-P1Y', {relativeTo: new Date('2022-12-01T00:00:00Z')}],
[
'-P1Y5M20D',
'-P2Y',
{
relativeTo: new Date('2022-01-01T00:00:00Z'),
},
],
])
for (const [input, expected, opts] of roundTests) {
test(`roundToSingleUnit(${input}) === ${expected}`, () => {
Expand Down Expand Up @@ -299,16 +330,29 @@ suite('duration', function () {
['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']],
['PT21H', [1, 'day'], {relativeTo: '2023-01-15T00:00:00Z'}],
['-PT21H', [-1, 'day'], {relativeTo: '2023-01-15T00:00:00Z'}],
['P4D', [4, 'day'], {relativeTo: '2023-01-15T00:00:00Z'}],
['-P4D', [-4, 'day'], {relativeTo: '2023-01-15T00:00:00Z'}],
['P6D', [1, 'week'], {relativeTo: '2023-01-15T00:00:00Z'}],
['-P6D', [-1, 'week'], {relativeTo: '2023-01-15T00:00:00Z'}],
['P2W', [2, 'week'], {relativeTo: '2023-01-15T00:00:00Z'}],
['-P2W', [-2, 'week'], {relativeTo: '2023-01-15T00:00:00Z'}],
['P3W3D', [3, 'week'], {relativeTo: '2023-01-15T00:00:00Z'}],
['-P3W3D', [-3, 'week'], {relativeTo: '2023-01-15T00:00:00Z'}],
['P3W6D', [1, 'month'], {relativeTo: '2023-01-15T00:00:00Z'}],
['-P3W6D', [-1, 'month'], {relativeTo: '2023-01-15T00:00:00Z'}],
['P21D', [3, 'week'], {relativeTo: '2023-01-01T00:00:00Z'}],
['-P21D', [-3, 'week'], {relativeTo: '2023-01-01T00:00:00Z'}],
['P24D', [3, 'week'], {relativeTo: '2023-01-01T00:00:00Z'}],
['-P24D', [-3, 'week'], {relativeTo: '2023-01-01T00:00:00Z'}],
['P24DT25H', [1, 'month'], {relativeTo: '2023-01-15T00:00:00Z'}],
['P25D', [1, 'month'], {relativeTo: '2023-01-15T00:00:00Z'}],
['-P35D', [-1, 'month'], {relativeTo: '2023-02-07T22:22:57Z'}],
['-P45D', [-1, 'month'], {relativeTo: '2023-02-17T22:22:57Z'}],
['-P55D', [-1, 'month'], {relativeTo: '2023-02-27T22:22:57Z'}],
['-P65D', [-3, 'month'], {relativeTo: '2023-02-28T22:22:57Z'}],
['-P75D', [-3, 'month'], {relativeTo: '2023-03-09T22:22:57Z'}],
[
'P8M',
[8, 'month'],
Expand Down Expand Up @@ -337,7 +381,7 @@ suite('duration', function () {
relativeTo: new Date('2022-12-01T00:00:00Z'),
},
],
['P1M1D', [1, 'month']],
['P1M1D', [1, 'month'], {relativeTo: new Date('2022-12-01T00:00:00Z')}],
[
'P9M20DT25H',
[9, 'month'],
Expand All @@ -347,14 +391,14 @@ suite('duration', function () {
],
[
'-P9M20DT25H',
[-9, 'month'],
[-10, 'month'],
{
relativeTo: new Date('2022-12-01T00:00:00Z'),
},
],
[
'P9M24DT25H',
[10, 'month'],
[9, 'month'],
{
relativeTo: new Date('2022-01-01T00:00:00Z'),
},
Expand Down
8 changes: 4 additions & 4 deletions test/relative-time.js
Expand Up @@ -471,7 +471,7 @@ suite('relative-time', function () {
time.setAttribute('tense', 'past')
time.setAttribute('datetime', '2023-06-01T00:00:00Z')
await Promise.resolve()
assert.equal(time.shadowRoot.textContent, '3 months ago')
assert.equal(time.shadowRoot.textContent, '4 months ago')
})

test('micro formats years', async () => {
Expand Down Expand Up @@ -1174,7 +1174,7 @@ suite('relative-time', function () {
datetime: '2022-12-03T15:46:00.000Z',
tense: 'future',
format: 'relative',
expected: 'next month',
expected: 'in 2 months',
},
{
datetime: '2022-12-03T15:46:00.000Z',
Expand Down Expand Up @@ -2408,14 +2408,14 @@ suite('relative-time', function () {
datetime: '2024-03-01T12:00:00.000Z',
tense: 'future',
format: 'auto',
expected: 'in 2 years',
expected: 'in 3 years',
},
{
reference: '2022-12-31T12:00:00.000Z',
datetime: '2024-03-01T12:00:00.000Z',
tense: 'future',
format: 'micro',
expected: '2y',
expected: '3y',
},
{
reference: '2021-04-24T12:00:00.000Z',
Expand Down

0 comments on commit 244af66

Please sign in to comment.