Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duration between dates seems to be incorrect #1433

Open
simeon9696 opened this issue Mar 28, 2021 · 11 comments
Open

Duration between dates seems to be incorrect #1433

simeon9696 opened this issue Mar 28, 2021 · 11 comments

Comments

@simeon9696
Copy link

simeon9696 commented Mar 28, 2021

Describe the bug
Duration seems to be incorrect. The difference between March 29th, 2020 and March 28th 2021 should be less than 12 months

Expected behavior
Calculating the difference between two days one year apart from each other should yield a difference of one year.

Information

  • Day.js Version: 1.10.3
  • OS: Windows 10 20H2
  • Browser Chrome 89
  • Time zone: GMT -4:00

I'm trying to get the difference between two dates:

  • A fixed date (March 29th, 2020)
  • Todays date (at the time of writing March 28th, 2021)

I do that with:

      const lockdown = dayjs("3/29/2020", "M/DD/YYYYY"); //29th March 2020
      const currentDate = dayjs();
 
      // get the difference between the moments
      const diff = currentDate.diff(lockdown);
    
      //express as a duration
      const diffDuration = dayjs.duration(diff);

   
      // display
      const timeInLockDown = {
        months: diffDuration.months(),
        days: diffDuration.days(),
        hours: diffDuration.hours(),
        minutes: diffDuration.minutes(),
        seconds: diffDuration.seconds()
      };

This yields diffDuration as:

days: 4
hours: 1
milliseconds: 709
minutes: 4
months: 12
seconds: 5
years: 0

Which doesn't make sense to me? It shouldn't 12 months and 4 days. Also, I think that if it is 12 months and 4 days, then years should be 1 but in this instance it's 0.

Is this expected behaviour?

@bornova
Copy link

bornova commented Mar 29, 2021

Just to add to @simeon9696 's issue, using the CustomParseFormat plugin along with Duration plugin returns NaN for diff in above example.

https://runkit.com/6052c5915dac89001a8e3602/606151bf64ef4e00192ea162

@avand
Copy link

avand commented May 27, 2021

I just noticed a bug and it seems related to this issue:

// dayjs version 1.10.5
import dayjs from 'dayjs';
import dayjsDurationPlugin from 'dayjs/plugin/duration';

const a = dayjs('3/19/2018');
const b = dayjs('3/17/2021');
const diff = b.diff(a, 'day'); // => 1094 correct
dayjs.duration(diff, 'days'); // => { years: 2, months: 12, days: 4 } incorrect

I would expect the output to be { years: 3, days: 4 }.

@caterpaula
Copy link

is there any movement on this? just stumbled across it myself

@Oliver-Saer
Copy link

Is there any further on this, please? I too have encountered this issue.

@xmsz
Copy link

xmsz commented Jun 16, 2022

any update?

@guypursey
Copy link

guypursey commented Aug 28, 2022

I encountered this issue today too.

Example

startDate = dayjs("2021-09-21")
endDate = dayjs("2050-09-21")

dayjs(startDate).add(29, "y").toDate() // returns "2050-09-21", same as endDate as expected -- 29 years' difference

dayjs.duration(endDate.diff(startDate)) // returns an object containing 29 years and 7 days instead

Thoughts

As the code @avand pasted above actually also shows, the issue is the interaction between diff and duration.

The method diff by itself, if you don't specify a unit of time argument, basically returns the difference between the two dates in milliseconds. This difference is accurate but has no context.

If you then pass this milliseconds result to duration it seems to simply work out how long that should be in terms of fixed month lengths, etc. The milliseconds have no context with them as to the dates they originally sat between. Hence you get these weird rounding errors.

That's my theory anyway.

Workaround?

Until this is fixed, a workaround might be to use diff more specifically.

So say for me, for now, I want my interface to recognise that from 2021-09-21 to 2050-09-21 is 29 years but that 2021-09-21 to 2050-09-20 (just a day less) is still 28 years.

I can do this with:

dayjs("2050-09-21").diff(dayjs("2021-09-21"), "years")

If I then pass this onto duration, the result I get back is accurate.

Summary of problem

In short I think both the way diff gets rid of the context of its calculations and the fact that duration doesn't expect any context is the problem here.

@guypursey
Copy link

Further evidence for the above observed in comment on a related issue.

Brief thread on more accurate duration requirements also adds to this.

@ablarer
Copy link

ablarer commented Feb 6, 2023

Same problem here:
const monthDifference = dayjs("2023.03.04").diff(dayjs("2023.02.06"), "month");
Result: 0
Though, this does works:
const monthDifference = dayjs("2023.03.04").get("month") - (dayjs("2023.02.06").get("month"));
Result: 1

@vendramini
Copy link

vendramini commented May 5, 2023

Here too:

const diffMonth = to.diff(from, 'month');
console.log({fromParam, toParam, diffMonth, diffMonth2: to.get('month') - from.get('month')});

{fromParam: '2023-05-29', toParam: '2023-07-02', diffMonth: 1, diffMonth2: 2}

"dayjs": "^1.11.7"

@umnyash
Copy link

umnyash commented Jan 18, 2024

"dayjs": "1.11.10"

In my experience, you can't rely on the duration method when calculating duration in months or years. This is due to the fact that months do not contain the same number of days, and the calculations use one fixed value: ~30.41666 (30 days 10 hours).

Example:

const dateFrom = "2024-02-02T00:00:00"; // February 2, 2024
let dateTo = "2024-03-03T00:00:00"; // March 3, 2024
const duration1 = dayjs.duration(dayjs(dateTo).diff(dayjs(dateFrom))); // 0 months, 30 days, 0 hours

dateTo = "2024-03-04T00:00:00"; // March 4, 2024urs
const duration2 = dayjs.duration(dayjs(dateTo).diff(dayjs(dateFrom))); // 1 month. 0 days, 14 hours

@herbievine
Copy link

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests