I conducted a quick test with the Cocoa Touch to see how NSHebrewCalendar works. I’m particularly interested in the month numbers. I used a date picker to easily change dates, and I passed it in to a method which logs the hebrew date, the hebrew month number, the hebrew year, and if the year is leap year. That looks like this:
BOOL isHebrewLeapYear = [self.calendar isHebrewLeapYear:[calendar hebrewYearForDate:[self.calendar workingDate]]];
NSLog(@"Hebrew Date:%@, Month Number: %i, %i is Leap Year: %i", [self.calendar stringFromHebrewDate:[self.calendar workingDate]], [self.calendar hebrewMonthNumberFromDate:[self.calendar workingDate]], [calendar hebrewYearForDate:[self.calendar workingDate]], isHebrewLeapYear);
The self.calendar object is a custom class. The workingDate property is an NSDate instance. Here are the relevant method declarations.
// Check if a given year is a leap year
- (BOOL) isHebrewLeapYear:(NSInteger)year{
return ((7 * year + 1) % 19) < 7;
}
//Get the hebrew year for a given date
- (NSInteger) hebrewYearForDate:(NSDate *)date{
NSCalendar *hebrewCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSHebrewCalendar] autorelease];
return [[hebrewCalendar components:NSYearCalendarUnit fromDate:date] year];
}
- (NSInteger) hebrewMonthNumberFromDate:(NSDate *)date{
NSCalendar *hebrewCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSHebrewCalendar] autorelease];
return [[hebrewCalendar components:NSMonthCalendarUnit fromDate:date] month];
}
Apparently hebrew leap years are handled as follows:
- Month numbering starts at 1, with that month being “Tishri”.
- In a nonleap year, Adar is month number 7, not 6.
- In a leap year, Adar I is number 6 and Adar II is 7.
- “Nisan” is always 8 and so on until “Elul”, which is always 13.
Does it sound like my experiment is producing accurate results? Is this behavior documented anywhere?
Correct.
Technically incorrect. (More on this below)
Correct.
Correct.
So what’s up with Adar in non-leap years? I ran this code to find out:
In a leap year, this will log what you would expect:
For each incrementation of the “month” date component, we get a different date. But when we run this in a non-leap year, we get this:
Here we see that have a month of 6 and 7 will both evaluate to Adar. Thus, Adar is both the 6th and the 7th month in non-leap years.
Also, since we know that the year 5790 is a leap year, we can deduce a simpler implementation of the-isHebrewLeapYear:method: