Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSCalendar getting day difference wrong

I'm trying to use [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:date] on two different dates to see if they fall on the same day. However, if my time zone is different (say, somewhere in Germany), even though the dates are obviously the same, the days returned are different. If I use NSYearCalendarUnit instead of NSEraCalendarUnit on the same dates, the returned values are the same.

The only problem with using NSYearCalendarUnit is it returns the same value for the same day of different years, and it's not simple to determine the number of days between two dates if they fall on different years.

Any ideas what's wrong or how to more easily determine if two dates are on the same day, or to determine the number of days between them?

Example:

[NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Berlin"]];
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDate *date1 = [NSDate dateWithTimeIntervalSinceReferenceDate:300751200];
NSDate *date2 = [NSDate dateWithTimeIntervalSinceReferenceDate:300836062.388569];

NSLog(@"\nDate 1: %@\nDate 2: %@",date1,date2);
/*Output:
Date 1: 2010-07-14 00:00:00 +0200
Date 2: 2010-07-14 23:34:22 +0200
*/

int day1 = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit
                         forDate:date1];
int day2 = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit
                         forDate:date2];

NSLog(@"\nDay 1: %i\nDay 2: %i",day1,day2);
/*Output:
  Day 1: 733966
  Day 2: 733967
*/

day1 = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit
                     forDate:date1];
day2 = [cal ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit
                     forDate:date2];

NSLog(@"\nDay 1:%i\nDay 2: %i",day1,day2);
/*Output:
  Day 1: 195
  Day 2: 195
*/
like image 294
Ed Marty Avatar asked Jul 14 '10 22:07

Ed Marty


2 Answers

Filed a bug, but then I checked Date and Time Programming Guide again. If you use the code from listing 13 (similar to yours), it behaves wrong. But if you use listing 14, it works as expected.

EDIT: Conceptually, Apple is right. Jesus Christ (as everybody else) was born in absolute time, independent of timezones. So the new era started at the same point of time, regardless of timezones. New Year is at a different point of time in each timezone. This could explain differences between NSYearCalendarUnit and NSEraCalendarUnit. The problem is, that they did not explicitly state this in the docs.

like image 91
Vilém Kurz Avatar answered Oct 27 '22 08:10

Vilém Kurz


See http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/Reference/NSCalendar.html: “Discussion

The ordinality is in most cases not the same as the decomposed value of the unit. Typically return values are 1 and greater. For example, the time 00:45 is in the first hour of the day, and for units Hour and Day respectively, the result would be 1. An exception is the week-in-month calculation, which returns 0 for days before the first week in the month containing the date.”

In other words: 23:34:22 belongs to the last hour of day, coming up to 240. Time running over the zero is equivalent to: next day.

Maybe this could be treated as a bug: hours in a day running from the first over the twentytird to the zeroth? I suggest: fill in a bug report.

like image 36
Objective Interested Person Avatar answered Oct 27 '22 06:10

Objective Interested Person