9

Following code shows the problem: Advancing a full year from the first day of the year 1435 does not result in the first day of 1436.

Any ideas what i'm missing?

NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:1];
[components setMonth:1];
[components setYear:1435];


NSCalendar *islamic = [[NSCalendar alloc] initWithCalendarIdentifier:NSIslamicCalendar];
NSDate *date = [islamic dateFromComponents:components];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setCalendar:islamic];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];

NSLog(@"%@", [dateFormatter stringFromDate:date]);  // -> 01.01.1435

NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setYear:1];

NSDate *dateWithOffset = [islamic dateByAddingComponents:offsetComponents toDate:date options:0];

NSLog(@"%@", [dateFormatter stringFromDate:dateWithOffset]); 
// -> 30.12.1435 ... WHY NOT 01.01.1436 ????
Frank Martin
  • 2,584
  • 2
  • 22
  • 25
  • Not a solution but could help narrow down the problem: Have you tried making your initial calendar using a different type, such as Gregorian? Try that and see if the issue still occurs to rule out or narrow the Islamic component possibly having some quirk that causes this. – Dima Jun 05 '12 at 18:04
  • With other calendars (gregorian, hebrew, buddhist) the algorithm seems to work fine - at least for the time intervals i looked at. Even for the majority of islamic years it works, but some don't. – Frank Martin Jun 05 '12 at 18:41
  • I created a new project and copied your code into it. Under iOS 4.3, 5.0, and 5.1 I got the expected result. `Muh. 1, 1435` and `Muh. 1, 1436` – Thomas Hajcak Jun 06 '12 at 18:07
  • @Thomas Just created also a new project and executed the code. My output is the following: 2012-06-06 22:16:48.522 IslamicCalendarTest[16738:f803] 01.01.1435 2012-06-06 22:16:48.523 IslamicCalendarTest[16738:f803] 30.12.1435 Does your system differ from mine? Mac OS X 10.7.4, Xcode 4.3.2, iOS SDK 5.1 – Frank Martin Jun 06 '12 at 20:30
  • @FrankMartin Same system and Xcode version. Maybe this has to do with user settings. Have you tried explicitly setting the calendar in the `NSDateComponents`? Is that even an option? – Thomas Hajcak Jun 12 '12 at 18:40
  • @Thomas: The timeZone of my system defaults to Central European Summer Time (CEST) - i suspect this being the reason for the different results. Thanks for testing! – Frank Martin Jun 13 '12 at 13:37

1 Answers1

3

My suspicion is because of summertime/wintertime (daylight savings time) difference. Muh. 1, 1435 falls on November 5, 2013, while Muh. 1, 1436 falls on October 25, 2014. The first date is during wintertime, the second during summertime.

The first NSDate you created is exactly November 5, 2013 00:00 (at midnight). "dateByAddingComponents:" works by converting the components to seconds, and adding that to the first date. In this case, the result is October 24, 2014 23:00, because of the summertime.

This would also mean that the results could be different for different people around the world because of daylight saving time differences between timezones.

You can prevent the problem by setting the first date to mid-day, instead of midnight (which is in general a good idea when working with pure dates):

NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:1];
[components setMonth:1];
[components setYear:1435];
[components setHour:12];

Now, whether this is correct behaviour of "dateByAddingComponents" is another question.

fishinear
  • 6,101
  • 3
  • 36
  • 84
  • Good argument :-) I want to investigate the timezone aspect in detail and provide feedback about it. Just now i'm in a hurry - so i have to beg for a little patience. – Frank Martin Jun 11 '12 at 15:20
  • Your suspicion was right: Explicitly setting the timeZone (to a non daylight saving time value) for calendar, dateFormatter and NSDateComponents results in the expected values :-) – Frank Martin Jun 13 '12 at 13:48