0
votes

I'm trying to perform date calculations for a scheduling app but am running into issues with daylight savings time. I'm trying to determine the number of days between two dates with:

NSDateComponents *activityComponents = [[NSDateComponents alloc]init];
activityComponents = [self.calendar components:NSDayCalendarUnit
                                      fromDate:self.viewBeginDate
                                        toDate:item.ES
                                       options:0];
NSLog(@"Days: %d and hours: %d", [activityComponents day], [activityComponents hour]);

where self.viewBeginDate and item.ES are both NSDate objects and self.calendar is a gregorian calendar.

  • When calculating between Nov 1, 2013 and Nov 1, 2013, it provides 0.
  • When calculating between Nov 1, 2013 and Nov 2, 2013, it provides 1.
  • When calculating between Nov 1, 2013 and Nov 3, 2013, it provides 2.
  • When calculating between Nov 1, 2013 and Nov 4, 2013, it provides 2 again!

Here is my output:

    Days: 0 and hours: 0
    Days: 1 and hours: 0
    Days: 2 and hours: 0
    Days: 2 and hours: 24
    Days: 3 and hours: 23

I'd like to be able to determine the number of days between 2 NSDate objects without impact by Daylight Savings Time, as my app doesn't care what local or timezone the user is in. I just want it to tell me that there are 3 days between Nov 1, 2013 and Nov 4, 2013. Any thoughts?

My NSDate objects are created from strings in the format of: 2013-11-01 00:00:00 +0000. Each date has the time set to 00:00:00 with the GMT offset of +0000.

I've thought of two possible options:

  • Use isDaylightSavingTime to check each date and create a new (modified) date offset by 1 hour if it the date is Daylight Savings Time. I'm worried about the added calculation time as my app calculates the date between a given begin date and an array of other dates. This array may have up to 2,000 dates in it. I'm not sure if that's a legit concern or not...
  • create a custom timezone that is not affected by DST. Is this even possible?
1
Just set your NSCalendar to UTC.Hot Licks
I've changed my calendar to UTC with no difference in the results. Did I do this right? [self.calendar setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];dfro
I've listed out the timezones with NSLog(@"%@", [NSTimeZone knownTimeZoneNames]); and got a long list in the likes of "America/such-and-such" and "Europe/such-and-such" and even GMT, but I didn't see UTC. Is it not always available?dfro
Use GMT, it is the old name for UTC. I am amazed that Apple does not add UTC.zaph
Or just use [NSTimeZone timeZoneForSecondsFromGMT:0]Hot Licks

1 Answers

2
votes

I can confirm your observations using dates around the 27 October (when British Summer Time started) and setting the time zone to Europe/London. The "n days 24 hours" seems to be a quirk (kind word for a bug, somebody forgot to carry).

Solution 1: Use an NSCalendar set to UTC. UTC has no daylight savings.

Solution 2: As all your times are at midnight and the maximum daylight savings shift is 1 hours then a "day" is between 23 and 25 hours. To allow for this, and handle the quirk at the same time simply:

daysBetween = [activityComponents day] + ([activityComponents hour] >= 23 ? 1 : 0);

Note that this only works because time is the same in the two dates!