1
votes

We know that NSDate is UTC/GMT. In order words, no time zone info is associated with it.

There are high level classes such as NSCalendar and NSTimeZone and NSDateComponents which do take timezone into account.

Based on that, I am using the following code to calculate the difference in days between 2 dates. However the result I am getting seems as the calculation is done ignoring the time altogether. I am wondering if I am doing something wrong or if this is by design for some reason.

Here is the code and data:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comp = [calendar components:NSDayCalendarUnit fromDate:startDate toDate:stopDate options:0];
NSInteger day = [comp day];

Debug output:

(gdb) po startDate
2011-04-01 03:52:13 +0000
(gdb) po stopDate
2011-04-03 15:52:13 +0000
(gdb) p (int) day
$1 = 2

The timezone is Pacific Standard Time and the dates above converted to PST are:

startDate = 2011-03-31 8:52:13 -7
stopDate  = 2011-04-03 8:52:13 -7

Therefore I would expect 4 days between them, not 2. (31st, 1st, 2nd, and 3rd)

The reason I think the hours are ignored is because if hours are added to the calculations we get 2 days and 12 hours.

Am I doing something wrong or is this how this is designed to work?

Thank you, Vance

1

1 Answers

0
votes

Not quite. When you format the dates in the Pacific time zone, you get:

Calendars[38041:707] start: 2011-03-31 20:52:13 -0700
Calendars[38041:707] stop : 2011-04-03 08:52:13 -0700

This is a bit different from what you posted. Yours seems to indicate 8 AM, not 8 PM.

Also, the components:fromDate:toDate:options: is going to count whole units. Thus, if you're asking for the number of days, it's going to say there are 2 whole days in between them, which there are.

Perhaps a better way to do what you're looking for is this:

NSUInteger startOrdinal = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:startDate];
NSUInteger stopOrdinal = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:stopDate];

Then the number of days between them will be (stopOrdinal - startOrdinal). In the case of your dates, this yields 3 (April 1 GMT - April 3 GMT). If you really really want to ignore the time portion, you're going to have to figure out how to chop off the time portion of the dates within the target timezone. This will involve converting the dates into NSDateComponent objects, then setting the -hour, -minute, and -second portions to 0. Once you've done that, you can change them back into NSDates, and then go on with your difference calculations.