iPhone - get number of days between two dates

自古美人都是妖i 提交于 2019-11-29 07:38:27

From the docs for components:fromDate:toDate:options::

The result is lossy if there is not a small enough unit requested to hold the full precision of the difference.

Since the difference is less than a full day, it correctly returns a result of 0 days.

If all you care about is tomorrow or yesterday vs. a specific date, then you can save yourself a lot of work and just test whether the dates are only one calendar day apart.

To do that, compare the dates to find which is earlier and which is later (and if they compare equal, bail out with that result), then test whether 1 day after the earlier date produces a date with the same year, month, and day-of-month as the later date.


If you really do want to know exactly how many calendar days there are from one date to the other:

  1. Send the calendar a components:fromDate: message to get the year, month, and day-of-the-month of the first date.
  2. Same as #1, but for the second date.
  3. If the two dates are in the same year and month, subtract one day-of-month from the other and pass to abs (see abs(3)) to take the absolute value.
  4. If they are not in the same year and month, test whether they are in adjacent months (e.g., December 2010 to January 2011, or June 2010 to July 2010). If they are, add the number of days in the earlier date's month (which you can obtain by sending the calendar a rangeOfUnit:inUnit:forDate: message, passing NSDayCalendarUnit and NSMonthCalendarUnit, respectively) to the day-of-month of the later date, then compare that result to the earlier date's day-of-month.

    For example, when comparing 2010-12-31 to 2011-01-01, you would first determine that these are in adjacent months, then add 31 (number of days in 2010-12) to 1 (day-of-month of 2011-01-01), then subtract 31 (day-of-month of 2010-12-31) from that sum. Since the difference is 1, the earlier date is one day before the later date.

    When comparing 2010-12-30 to 2011-01-02, you would determine that they are in adjacent months, then add 31 (days in 2010-12) to 2 (day-of-month of 2011-01-02), then subtract 30 (day-of-month of 2010-12-30) from that sum. 33 minus 30 is 3, so these dates are three calendar days apart.


Either way, I strongly suggest writing unit tests at least for this code. I've found that date-handling code is among the most likely to have subtle bugs that only manifest, say, twice a year.

One thing you might try is using rangeOfUnit: to zero out hours, minutes and seconds from the start and end dates.

NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit range = NSDayCalendarUnit;
NSDateComponents *comps = [[NSDateComponents alloc] init];
NSDate *start = [NSDate date];
NSDate *end;

[comps setDay:1];
[calendar rangeOfUnit:range startDate:&start interval:nil forDate:start];

end = [calendar dateByAddingComponents:comps toDate:start options:0];

In this example start will be 2010-06-19 00:00:00 -0400, end will be 2010-06-20 00:00:00 -0400. I'd imagine this would work better with NSCalendar's comparison methods, although I haven't tested it myself.

Rog

You can easily work it out using the very nice answer to this related question

I am using this piece of code, it is working very well:

- (NSInteger)daysToDate:(NSDate*)date
{
    if(date == nil) {
        return NSNotFound;
    }
    NSUInteger otherDay = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay   inUnit:NSCalendarUnitEra forDate:date];
    NSUInteger currentDay = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:self];
    return (otherDay-currentDay);
}

Here is the function I've used in the past its defined in a category on NSDate

- (int) daysToDate:(NSDate*) endDate
{
    //dates needed to be reset to represent only yyyy-mm-dd to get correct number of days between two days.
    NSDateFormatter *temp = [[NSDateFormatter alloc] init];
    [temp setDateFormat:@"yyyy-MM-dd"];
    NSDate *stDt = [temp dateFromString:[temp stringFromDate:self]];
    NSDate *endDt =  [temp dateFromString:[temp stringFromDate:endDate]];
    [temp release]; 
    unsigned int unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;
    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *comps = [gregorian components:unitFlags fromDate:stDt  toDate:endDt  options:0];
    int days = [comps day];
    [gregorian release];
    return days;
}
 -(NSInteger)daysBetweenTwoDates:(NSDate*)fromDateTime andDate:(NSDate*)toDateTime

{

NSDate *fromDate;
NSDate *toDate;

NSCalendar *calendar = [NSCalendar currentCalendar];

[calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate
             interval:NULL forDate:fromDateTime];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate
             interval:NULL forDate:toDateTime];

NSDateComponents *difference = [calendar components:NSDayCalendarUnit
                                           fromDate:fromDate toDate:toDate options:0];

return [difference day];

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!