Преобразование gregorian строки даты в исламскую дату дает правильные и неправильные результаты

У меня есть следующие две строки даты: (1) 24/04/2013 и (2) 19/03/2013 Я пытаюсь преобразовать эти даты в исламские (Um Al Qura) даты, я использую этот блок кода для этого:

    NSDateFormatter *df = [[NSDateFormatter alloc] init];
    df.dateFormat = @"dd/MM/yyyy";
    df.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDate *dateInGrogrian = [df dateFromString:@"24/04/2013"];

    NSDateFormatter *df2 = [[NSDateFormatter alloc] init];
    NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSIslamicCalendar];
    [df2 setCalendar:cal];
    [df2 setDateFormat:@"dd/MM/yyyy"];
    NSLog(@"Converted date to Islamic = %@",[df2 stringFromDate:dateInGrogrian]); 

если строка ввода была 24/04/2013, отображается NSLog:

Converted date to Islamic = 14/06/1434, который является правильным (согласно официальному исламскому календарю, который используется во всех исламских странах). Но если входная строка была 19/03/2013, отображается NSLog:

Converted date to Islamic = 08/05/1434, который является неправильным (согласно исламскому календарю, правильная дата должна быть 07/05/1434, которая на 1 день позади).

- Примечания для рассмотрения, прежде чем вы предлагаете ответ:

(1) Я попытался использовать идентификатор календаря NSIslamicCivilCalendar вместо NSIslamicCalendar, но безрезультатно: одна из преобразованных дат была правильной, а другая была неправильной (1 день сзади).

(2) Я попытался использовать часовой пояс GMT следующим образом: [df2 setTimeZone : [NSTimeZone timeZoneWithName:@"GMT"]];, это привело к правильной конвертированной дате для дня (2), но неверно для дня (1) (1 день позади).

(3) Я пробовал комбинации решений: NSIslamicCivilCalendar с/без часовой пояс GMT, NSIslamicCalendar с/без часовой пояс, но также безрезультатно...

может ли кто-нибудь предоставить блок кода, который удовлетворяет обеим датам? поэтому я гарантирую, что любая предоставленная gregorian строка даты правильно преобразована в исламскую строку даты.

Большое вам спасибо.

Ответы

Ответ 1

После распечатки всех дат за последние 4 года кажется, что Apple использует несколько принятую формулу для математического расчета Исламского календаря, поскольку, как указал Мокси, фактический календарь не основан на научных днях, а вместо этого лунное приближение,

Эта формула состоит в том, что все нечетные месяцы имеют 30 дней, а все четные месяцы - 29 дней, причем дополнительный день добавляется к последнему месяцу в течение любого года, в течение которого год 30-го года является одним из следующих: 2, 5, 7, 10, 13, 16, 18, 21, 24, 26 или 29.

В результате получается средняя длина месяца 29.53056 дней, что довольно близко к лунному месяцу 29.53059 дней.

Эта формула используется в других местах на компьютерах, так как это единственный метод для расчета даты без использования таблицы поиска для каждого года в истории. Таким образом, если вы сами не напишите справочную таблицу, это будет так же точно, как вы можете получить для всех дат, идущих назад и вперед.

Ответ 2

// Create a Gregorian Calendar
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

// Set up components of a Gregorian date
NSDateComponents *gregorianComponents = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:[NSDate date]];

NSLog(@"[In Gregorian calendar ->] Day: %ld, Month: %ld, Year:%ld",
      (long)[gregorianComponents day],
      (long)[gregorianComponents month],
      (long)[gregorianComponents year]);


gregorianComponents.day = [gregorianComponents day];
gregorianComponents.month = [gregorianComponents month];
gregorianComponents.year = [gregorianComponents year];

// Create the date
NSDate *date = [gregorianCalendar dateFromComponents:gregorianComponents];



// Then create an Islamic calendar
NSCalendar *hijriCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSIslamicCivilCalendar];

// And grab those date components for the same date
NSDateComponents *hijriComponents = [hijriCalendar components:(NSDayCalendarUnit |
                                                               NSMonthCalendarUnit |
                                                               NSYearCalendarUnit)
                                                     fromDate:date];


NSLog(@"[In Hijri calendar ->] Day: %ld, Month: %ld, Year:%ld",
      (long)[hijriComponents day],
      (long)[hijriComponents month],
      (long)[hijriComponents year]);