dayjs icon indicating copy to clipboard operation
dayjs copied to clipboard

relativeTime outputs wrong amount of months

Open froks opened this issue 5 years ago • 3 comments

Describe the bug When you put in custom thresholds for relativeTime to output everything up to 9999 months as months, and enter a duration longer than 36 months, some months get lost.

Expected behavior Output of correct amount of month

Information

  • dayjs 1.9.3
  • Windows
  • Chrome
  • CEST

I created a fiddle here https://jsfiddle.net/sy50xg2e/1/

Details

const config = {
	thresholds: [
		{l: 's', r: 59, d: 'second'},
		{l: 'm', r: 59},
		{l: 'mm', r: 59, d: 'minute'},
		{l: 'h', r: 23},
		{l: 'hh', r: 23, d: 'hour'},
		{l: 'd', r: 29},
		{l: 'dd', r: 29, d: 'day'},
		{l: 'M', r: 1},
		{l: 'MM', r: 9999, d: 'month'}
//		{l: 'y', r: 1},
//		{l: 'yy', r: 9999, d: 'year'}
	]

};

dayjs.extend(dayjs_plugin_relativeTime, config)
dayjs.extend(dayjs_plugin_duration)

console.log(dayjs.duration(36, "month").humanize());
console.log(dayjs.duration(37, "month").humanize());
console.log(dayjs.duration(38, "month").humanize());
console.log(dayjs.duration(9999, "month").humanize());

The output is:

"36 months"
"36 months"
"37 months"
"9855 months"

I'd expect, 36, 37, 38, 9999.

froks avatar Oct 15 '20 09:10 froks

We might have to re-think about the implementation of the duration plugin.

It is not safe just to store duration in ms, cause not all days in a month is 30, and not all dayjs in a year is 365.

That's why this error happened.

iamkun avatar Oct 15 '20 11:10 iamkun

Below is a test case that shows that the results of add 1 month is different than adding P1M. That's not good - the behavior should be the same. Hence, using milliseconds in the duration plugin is not a feasible option.

test('duration P1M is equivalent one month', () => {
    const now = dayjs()
    const a = now.add(1, 'month')
    const b = now.add(dayjs.duration('P1M'))

    const diff = a.diff(b, 'day')
    expect(diff).toEqual(0) // <= will fail
})

thovden avatar Dec 15 '20 10:12 thovden

I just ran into a similar issue to this.

<Text>Today: {dayjs().toString()}</Text>
<Text>Duration: {dayjs.duration("P6W").humanize()}</Text>
<Text>
  Today + Duration: {dayjs().add(dayjs.duration("P6W")).toString()}
</Text>

image

davidchalifoux avatar Apr 23 '24 15:04 davidchalifoux