NSCalendar returns same date component difference for two different dates

I'm calculating the difference in months and days between two dates using


- NSCalendar components:fromDateComponents:toDateComponents:options:


Interestingly I get the same result for two different days:

  • 2014-07-30
    -
    2015-07-20
    : 11 months 20 days
  • 2014-07-31
    -
    2015-07-20
    : 11 months 20 days

The relevant parts:

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
NSCalendarUnit flags = NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents *rslt = nil;

// between 7/30/2014 and 7/20/2015: 11 months 21 days
NSDateComponents *later = [NSDateComponents new];
later.year = 2015;
later.month = 7;
later.day = 20;
NSDateComponents *earlier = [NSDateComponents new];
earlier.year = 2014;
earlier.month = 7;
earlier.day = 30;
rslt = [calendar components:flags fromDateComponents:earlier toDateComponents:later options:0];
// rslt.month is 11, rslt.day is 20

// between 7/31/2014 and 7/20/2015: 11 months 20 days
earlier.day = 31;
rslt = [calendar components:flags fromDateComponents:earlier toDateComponents:later options:0];
// rslt.month is 11, rslt.day is 20


Can anyone explain what's going on and what the problem might be?

Answered by rod in 29860022

Months and days is not a precise notion, because months do not all have the same length.


In this case, 11 months from 2014-07-30 is 2015-06-30, and 11 months from 2014-07-31 is also 2015-06-30. (after all, you wouldn't want it to be 2015-07-01).

20 days after this date is 2015-07-20.


So the time from both 2014-07-30 and 2015-07-31 to 2015-07-20 is 11 months and 20 days.


If you want to have precise differences, you need to calculate in units that have a constant length. eg. hours, days, weeks.


The same problem happens with years.


1 year from 2004-02-28 is 2005-02-28. 1 year from 2004-02-29 is also 2005-02-28.


Rod

Accepted Answer

Months and days is not a precise notion, because months do not all have the same length.


In this case, 11 months from 2014-07-30 is 2015-06-30, and 11 months from 2014-07-31 is also 2015-06-30. (after all, you wouldn't want it to be 2015-07-01).

20 days after this date is 2015-07-20.


So the time from both 2014-07-30 and 2015-07-31 to 2015-07-20 is 11 months and 20 days.


If you want to have precise differences, you need to calculate in units that have a constant length. eg. hours, days, weeks.


The same problem happens with years.


1 year from 2004-02-28 is 2005-02-28. 1 year from 2004-02-29 is also 2005-02-28.


Rod

Ha, d'oh, of course that's right! The February 29 example was clear, but I didn't think that the same principle of course also applies to the 30/31 days a month issue.


Thanks a lot! 🙂

NSCalendar returns same date component difference for two different dates
 
 
Q