3
votes

I am trying to use NSDateComponents in order to test if a dynamic date occurs "today". I use it to extract the year/month/day and then compare those values for two NSDates. In theory this should work. I am on east coast, so EST, -5 from UTC.

Actual current time: 12:40:53, EST

Here are the correct NSDates, in UTC. The times are correct UTC:

  • Current [NSDate date]: 2016-01-19 17:40:53 +0000
  • Activity NSDate: 2016-01-19 00:00:00 +0000

Here is my log, showing each date. It is converting the dates to local timezone 2016-01-19 07:00:00. Since the current date is in the middle of the day, the -5 hour offset isn't causing it to shift days. The midnight one however shifts to one day back. How can I get it to respect UTC?

NSLog:

2016-1-19 12:40:53 (America/New_York (EST) offset -18000), 
2016-1-18 19:0:0 (America/New_York (EST) offset -18000)

Code:

NSDateComponents *current = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond |NSCalendarUnitTimeZone fromDate:_date];
NSDateComponents *activity = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond |NSCalendarUnitTimeZone fromDate:activityModel.date];

// attempt to set timezones to UTC manually, doesn't change anything   
activity.calendar = [NSCalendar currentCalendar];
activity.calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];

current.calendar = [NSCalendar currentCalendar];
current.calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];


NSLog(@"%ld-%ld-%ld %ld:%ld:%ld (%@), %ld-%ld-%ld %ld:%ld:%ld (%@)", (long)[current year],(long)[current month], (long)[current day], (long)[current hour], (long)[current minute], (long)[current second], [current timeZone].description, (long)[activity year], (long)[activity month], (long)[activity day],(long)[activity hour], (long)[activity minute], (long)[activity second],[current timeZone].description);

if([current day] == [activity day] &&
           [current month] == [activity month] &&
           [current year] == [activity year] &&
           [current era] == [activity era]) {

           // do something if activity on current day
}
1
You could just ask NSCalendar that question. Probably easier than debugging date code. See -[NSCalendar isDateInToday].Avi
Tried this: if([[NSCalendar currentCalendar] isDateInToday:activityModel.date]){ It is still failing the same way as my original comparison. But indeed, much simpler.Miro

1 Answers

4
votes

You are changing the timezone of the NSDateComponents. But you want to change the timezone of the calendar before you call components (or call the NSCalendar day checking routines), e.g.:

NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];

if ([calendar isDate:_date inSameDayAsDate:activityModel.date]) {
    NSLog(@"same");
} else {
    NSLog(@"diff");
}

But what if the local time was 2016-01-19 21:00:00 -0500 (i.e. the 20th, UTC). Do you want it to say that it was also the same day as the activity date in your example? If so, then you're really saying that you want to use local calendar for _date, and UTC for the activityModel.date, e.g.:

NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];

NSDateComponents *current = [calendar components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond |NSCalendarUnitTimeZone fromDate:_date];

calendar.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];

NSDateComponents *activity = [calendar components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond |NSCalendarUnitTimeZone fromDate:activityModel.date];

if ([current day] == [activity day] && [current month] == [activity month] && [current year] == [activity year] && [current era] == [activity era]) {
    NSLog(@"same");
} else {
    NSLog(@"diff");
}