objective-ciphonensdategregorian-calendarjulian-date

Converting a Gregorian date to Julian Day Count in Objective C


I need Objective C method for converting Gregorian date to Julian days same as this PHP method (GregorianToJD).


Solution

  • According to http://en.wikipedia.org/wiki/Julian_day, the Julian day number for January 1, 2000, was 2,451,545. So you can compute the number of days between your date and this reference date. For example (Jan 1, 2014):

    NSUInteger julianDayFor01012000 = 2451545;
    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [cal setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    NSDateComponents *comp = [[NSDateComponents alloc] init];
    comp.year = 2014;
    comp.month = 1;
    comp.day = 1;
    NSDate *date = [cal dateFromComponents:comp];
    comp.year = 2000;
    comp.month = 1;
    comp.day = 1;
    NSDate *ref = [cal dateFromComponents:comp];
    
    NSDateComponents *diff = [cal components:NSDayCalendarUnit fromDate:ref toDate:date options:0];
    NSInteger julianDays = diff.day + julianDayFor01012000;
    NSLog(@"%ld", (long)julianDays);
    // Output: 2456659
    

    This gives the same result as http://www.php.net/manual/en/function.gregoriantojd.php:

    <?php
    $jd = GregorianToJD(1, 1, 2014);
    echo "$jd\n";
    ?>
    

    Inverse direction (Julian days to Gregorian year/month/day):

    NSInteger julianDays = 2456659; // From above example
    NSUInteger julianDayFor01012000 = 2451545;
    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [cal setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    NSDateComponents *comp = [[NSDateComponents alloc] init];
    comp.year = 2000;
    comp.month = 1;
    comp.day = 1;
    NSDate *ref = [cal dateFromComponents:comp];
    NSDateComponents *diff = [[NSDateComponents alloc] init];
    diff.day = julianDays - julianDayFor01012000;
    
    NSDate *date = [cal dateByAddingComponents:diff toDate:ref options:0];
    comp = [cal components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:date];
    NSLog(@"%04ld-%02ld-%02ld", (long)comp.year, (long)comp.month, (long)comp.day);
    // Output: 2014-01-01
    

    UPDATE: As Hot Licks correctly stated in a comment, it is easier to use a date formatter with the "g" format:

    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *comp = [[NSDateComponents alloc] init];
    comp.year = 2014;
    comp.month = 1;
    comp.day = 1;
    NSDate *date = [cal dateFromComponents:comp];
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    [fmt setDateFormat:@"g"];
    NSInteger julianDays = [[fmt stringFromDate:date] integerValue];
    NSLog(@"%ld", (long)julianDays);
    // Output: 2456659
    

    And for the inverse direction:

    NSInteger julianDays = 2456659;
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    [fmt setDateFormat:@"g"];
    NSDate *date = [fmt dateFromString:[@(julianDays) stringValue]];
    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *comp = [cal components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:date];
    NSLog(@"%04ld-%02ld-%02ld", (long)comp.year, (long)comp.month, (long)comp.day);
    // Output: 2014-01-01