dayjs icon indicating copy to clipboard operation
dayjs copied to clipboard

Calculation of diff in years is wrong for leap-years (since v1.8.32)

Open amjmhs opened this issue 5 years ago • 5 comments

We use diff() to calculate the current age of people according to their date of birth. For someone who is born on February 29th at a leap-year, this calculation seems to be broken since version 1.8.32

Taken a person born on 2016-02-29, with version 1.8.31 on February 28th 2017 this person is still 0 years old. On March 1st, this person turns 1. With version 1.8.32, this person is already 1 year old on February 28th 2017, which is - at least here in Germany - not correct.

If the calculation is carried out in a leap year (e.g. 2020), it is correct in both versions.

Fiddle for version 1.8.31: https://jsfiddle.net/enqbx39r/1 Fiddle for version 1.8.32: https://jsfiddle.net/49yfb7wt/1

amjmhs avatar Aug 12 '20 19:08 amjmhs

Yes, we made an update https://github.com/iamkun/dayjs/commit/19e8a7f2f7582b717f49d446822e39603694433c, to keep the diff result the same with the current version of moment.js (2.27.0).

And this is also a bug on moment side.

We will try to find some workaround to fix this issue.

iamkun avatar Aug 13 '20 02:08 iamkun

This is an interesting issue.

I just met the same problem, and someone told me that

seems whether their birthday legally falls on Feb 28th or Mar 1st is dependent on the location https://en.wikipedia.org/wiki/February_29#Legal_status I'm not sure the question "Is one year after Feb 29th Mar 1st or Feb 28th?" has an absolutely correct answer.

zazzaz avatar Aug 23 '20 05:08 zazzaz

I had the same problem

image

programmer-yang avatar Aug 16 '21 09:08 programmer-yang

const d  = require("dayjs");
const duration = require('dayjs/plugin/duration');
const isBetween = require('dayjs/plugin/isBetween');
const isLeapYear = require('dayjs/plugin/isLeapYear');

d.extend(duration);
d.extend(isBetween);
d.extend(isLeapYear); 

const dateDiff = (startStr, endStr = new Date()) => {
  let startDate = d(startStr);
  let endDate = d(endStr);
  let diff = endDate.diff(startDate, 'days');
  for (let year = startDate.year(); year <= endDate.year(); year++) {
    const date = d(year + '-02-29');
    if (date.isBetween(startDate,endDate) && date.isLeapYear()) {
        diff -= 1;
    }
  }
  return diff;
}

const durationValue = d.duration(dateDiff('1990-08-16'), "days");

console.log(`${durationValue.years()} - ${durationValue.months()} - ${durationValue.days()}`)


Here is what I did

programmer-yang avatar Aug 16 '21 09:08 programmer-yang

Hi! Any news as to when will this be fixed? having the same issue.

ciprian-pratia-db avatar Dec 20 '23 13:12 ciprian-pratia-db