iamkun / dayjs

⏰ Day.js 2kB immutable date-time library alternative to Moment.js with the same modern API
https://day.js.org
MIT License
46.71k stars 2.28k forks source link

dayjs('2020-10-01').add(dayjs.duration(1, 'months')) not returns dayjs('2020-11-01') #1515

Open chimerast opened 3 years ago

chimerast commented 3 years ago

Describe the bug dayjs.duration(1, 'months') is converted to dayjs.duration(30, 'days') internally by duration plugin. so dayjs('2020-10-01').add(dayjs.duration(1, 'months')) returns dayjs('2020-10-31')

Expected behavior dayjs('2020-10-01').add(dayjs.duration(1, 'months')) should returns dayjs('2020-11-01')

Information

chimerast commented 3 years ago

To reproduce

diff --git a/test/plugin/duration.test.js b/test/plugin/duration.test.js
index cca1a82..57456af 100644
--- a/test/plugin/duration.test.js
+++ b/test/plugin/duration.test.js
@@ -174,8 +174,8 @@ describe('Add', () => {

 test('Add duration', () => {
   const a = dayjs('2020-10-01')
-  const days = dayjs.duration(2, 'days')
-  expect(a.add(days).format('YYYY-MM-DD')).toBe('2020-10-03')
+  const days = dayjs.duration(1, 'months')
+  expect(a.add(days).format('YYYY-MM-DD')).toBe('2020-11-01')
 })

 describe('Subtract', () => {

Results

  ● Add duration

    expect(received).toBe(expected) // Object.is equality

    Expected value to be:
      "2020-11-01"
    Received:
      "2020-10-31"

      176 |   const a = dayjs('2020-10-01')
      177 |   const days = dayjs.duration(1, 'months')
    > 178 |   expect(a.add(days).format('YYYY-MM-DD')).toBe('2020-11-01')
      179 | })
      180 |
      181 | describe('Subtract', () => {

      at Object.<anonymous> (test/plugin/duration.test.js:178:44)
toiletpatrol commented 3 years ago

That's because:

"Durations do not have a defined beginning and end date. They are contextless.

A duration is conceptually more similar to '2 hours' than to 'between 2 and 4 pm today'. As such, they are not a good solution to converting between units that depend on context."

The idea of Duration is simple. What's a month? 30 days. What's a year? 365 days. That's it. You probably want a more precise library/plugin.

Magnuti commented 3 months ago

I don't think this issue is relevant any longer. Both of these two tests succeeds on my machine.

dayjs.tz.setDefault("Asia/Tokyo");
assert.equal(dayjs("2020-10-01").add(1, "month").isSame(dayjs("2020-11-01"), "day"), true);
assert.equal(dayjs("2020-10-01").add(dayjs.duration(1, "months")).isSame(dayjs("2020-11-01"), "day"), true);