Я правильно понимаю NSHebrewCalendar? - PullRequest
4 голосов
/ 20 ноября 2011

Я провел быстрый тест с Cocoa Touch, чтобы увидеть, как работает NSHebrewCalendar. Меня особенно интересуют цифры месяца. Я использовал средство выбора даты, чтобы легко изменить даты, и передал его методу, который записывает дату иврита, номер месяца иврита, год иврита и, если год является високосным. Это выглядит так:

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);    

Объект self.calendar является пользовательским классом. Свойство workingDate является экземпляром NSDate. Вот соответствующие объявления методов.

//  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];
}

Видимо, еврейские високосные годы обрабатываются следующим образом:

  • Нумерация месяцев начинается с 1, причем месяцем является «тишри».
  • В не високосный год Адар - это месяц № 7, а не 6.
  • В високосный год Адар I - номер 6, а Адар II - 7.
  • «Нисан» всегда равен 8 и т. Д. До «Элула», который всегда равен 13.

Похоже, мой эксперимент дает точные результаты? Задокументировано ли это поведение где-нибудь?

Ответы [ 2 ]

3 голосов
/ 20 ноября 2011

Нумерация месяцев начинается с 1, в этом месяце "Тишри".

Correct.

В не високосный год Адар - номер 7, а не 6.

Технически неверно. (Подробнее об этом ниже)

В високосный год Адар I - номер 6, а Адар II - 7.

Correct.

«Нисан» всегда равен 8 и т. Д. До «Элула», который всегда равен 13.

Correct.

Так что же случилось с Адаром в не високосные годы? Я запустил этот код, чтобы узнать:

@autoreleasepool {

    NSDate *today = [NSDate date];
    NSCalendar *hebrew = [[NSCalendar alloc] initWithCalendarIdentifier:NSHebrewCalendar];
    NSDateComponents *diff = [[NSDateComponents alloc] init];
    NSDateFormatter *f = [[NSDateFormatter alloc] init];
    [f setDateFormat:@"d MMMM y"];
    [f setCalendar:hebrew];

    for (NSInteger i = 0; i < 19; ++i) {
        NSDateComponents *comp = [[NSDateComponents alloc] init];
        [comp setYear:5772 + i];
        [comp setDay:1];

        NSLog(@"============= %d ============", [comp year]);

        for (NSInteger i = 1; i <= 13; ++i) {
            [comp setMonth:i];

            NSDate *d = [hebrew dateFromComponents:comp];
            NSLog(@"%d: %@ (%@)", i, [f stringFromDate:d], d);
        }
    }

}

В високосный год будет записано, что вы ожидаете:

============= 5790 ============
1: 1 Tishri 5790 (2029-09-10 07:00:00 +0000)
2: 1 Heshvan 5790 (2029-10-10 07:00:00 +0000)
3: 1 Kislev 5790 (2029-11-08 08:00:00 +0000)
4: 1 Tevet 5790 (2029-12-07 08:00:00 +0000)
5: 1 Shevat 5790 (2030-01-05 08:00:00 +0000)
6: 1 Adar I 5790 (2030-02-04 08:00:00 +0000)
7: 1 Adar II 5790 (2030-03-06 08:00:00 +0000)
8: 1 Nisan 5790 (2030-04-04 07:00:00 +0000)
9: 1 Iyar 5790 (2030-05-04 07:00:00 +0000)
10: 1 Sivan 5790 (2030-06-02 07:00:00 +0000)
11: 1 Tamuz 5790 (2030-07-02 07:00:00 +0000)
12: 1 Av 5790 (2030-07-31 07:00:00 +0000)
13: 1 Elul 5790 (2030-08-30 07:00:00 +0000)

Для каждого приращения компонента даты «месяц» мы получаем разные даты. Но когда мы запускаем это в не високосный год, мы получаем это:

============= 5789 ============
1: 1 Tishri 5789 (2028-09-21 07:00:00 +0000)
2: 1 Heshvan 5789 (2028-10-21 07:00:00 +0000)
3: 1 Kislev 5789 (2028-11-19 08:00:00 +0000)
4: 1 Tevet 5789 (2028-12-19 08:00:00 +0000)
5: 1 Shevat 5789 (2029-01-17 08:00:00 +0000)
6: 1 Adar 5789 (2029-02-16 08:00:00 +0000)
7: 1 Adar 5789 (2029-02-16 08:00:00 +0000)
8: 1 Nisan 5789 (2029-03-17 07:00:00 +0000)
9: 1 Iyar 5789 (2029-04-16 07:00:00 +0000)
10: 1 Sivan 5789 (2029-05-15 07:00:00 +0000)
11: 1 Tamuz 5789 (2029-06-14 07:00:00 +0000)
12: 1 Av 5789 (2029-07-13 07:00:00 +0000)
13: 1 Elul 5789 (2029-08-12 07:00:00 +0000)

Здесь мы видим, что месяц с 6 и 7 оба оценят по Адару. Таким образом, Адар является 6-м и 7-м месяцем в не високосные годы.


Кроме того, поскольку мы знаем, что 5790 год является високосным, мы можем вывести более простую реализацию метода -isHebrewLeapYear::

- (BOOL) isHebrewLeapYear:(NSInteger)year{
    return year % 19 == 14;
}

0 голосов
/ 02 января 2014

Чтобы не делать моих собственных расчетов, когда високосный год, вот код, который я использовал для его проверки (основываясь на предыдущем выводе, что месяц 6 и 7 - это Адар I в обычном году:

- (BOOL)isRegularYear:(NSDate *)date {
    NSCalendar *hebrew = [[NSCalendar alloc] initWithCalendarIdentifier:NSHebrewCalendar];

    NSDateComponents *comp = [hebrew components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];

    [comp setMonth:6];
    NSDate *adar_i = [hebrew dateFromComponents:comp];
    [comp setMonth:7];
    NSDate *adar_ii = [hebrew dateFromComponents:comp];

    return [adar_i isEqualToDate:adar_ii];
}
...