Skip to content
Advertisement

PHP Julian date converter algorithms

Algorithms for the following:

JD 1099114.5

PHP: 3 Mar -1704 12:00:00 (PHP Internal convertor)

echo jdtogregorian($int_jd);

FLN: 0 Mar -1703 12:00:00 (Fliegel-Van Flandern)

function jd_to_gd_fln ($J) {
   $p = $J + 68569;
   $q = floor(4*$p/146097);
   $r = floor($p - (146097*$q + 3)/4);
   $s = floor(4000*($r+1)/1461001);
   $t = floor($r - (1461*$s/4) + 31);
   $u = floor(80*$t/2447);
   $v = floor($u/11);

     $Y = floor(100*($q-49)+$s+$v);
     $M = floor($u + 2 - 12*$v);
     $D = floor($t - 2447*$u/80);

return "$M/$D/$Y";

}

MEU: 18 Mar -1703 12:00:00 (Jean Meeus “Astronomical Algorithms, 2nd ed., corrected)

function jd_to_greg_meeus($julian) { 
    $Z = intval($J+0.5); 
 $F = ($J+0.5)-$Z;



  if ($Z < 2299161) {$A = $Z;}
   if ($Z >= 2299161) {
        $alpha = floor(($Z-1867216.25)/36524.25);
         $A = $Z + 1 + $alpha - floor($alpha/4);
         }


         $B = $A + 1524;
         $C = floor( ($B-122.1)/365.25);
         $D = floor( 365.25*$C );
         $E = floor( ($B-$D)/30.6001 );


     $day = floor($B - $D - floor(30.6001*$E)); 

if ($E < 13.5) {   $month = $E - 1;}
if ($E > 13.5) {   $month = $E - 13;}
if ($month > 2.5) {  $year = $C - 4716; }
if ($month < 2.5) {  $year = $C - 4715; }



    return "$month/$day/$year";
} 

RICH: 4 Mar -1703 12:00:00 (Richards in Explanatory Supplement 3rd Ed.)

function jd_to_gd_rchrds ($J) {
$y=4716;    
$v=3;
$j=1401;    
$u=5;
$m=2;   
$s=153;
$n=12;  
$w=2;
$r=4;   
$B=274277;
$p=1461;    
$C=-38;

$f = $J + $j + (((4 * $J + $B) / 146097) * 3) / 4 + $C;


$e = $r * $f + $v;
$g = ($e % $p) / $r;
$h = $u * $g + $w;
$D = floor((($h%$s)) / $u + 1);
$M = floor((($h / $s + $m) % $n) + 1);
$Y = floor(($e / $p) - $y + ($n + $m - $M) / $n);

return "$M/$D/$Y"; 
}

Each Algorithm has its issues.

What am I doing wrong with the code?

For reference test data should include:

  • JD: 2399301.5

  • JD: 1721420

  • JD: 1721425

  • JD: 1721426

  • JD: 2422444

  • JD: 2222444

Meeus assumes that there is a Gregorian year 0, even if this is astronomically correct, it makes little sense from a calendrical perspective. Technically then all the results to convert into Gregorian dates are just wrong? Calendrically speaking if there is no 0 but astronomically speaking there is a 0 how does that translate into the same date?

Advertisement

Answer

I did not look at the Fliegel-Van Flandern algorithm. I tested the remaining algorithm for the test cases Danny F requested, and added the last noon the Julian calendar was observed in Rome (JD 2299160) and the first noon of the Gregorian calendar in Rome (JD 2299161). For non-integer Julian days, I only used the Meeus algorithm since that’s the only one that says it supports non-integers.

The internal algorithm was correct, when you allow for considering year 0 to not exist, and it always converts to Gregorian. The Meeus algorithm is correct, when you allow for it assuming the existence of year 0, and converting to Julian for October 4, 1582 and earlier, and to Gregorian for dates after that.

The Richards algorithm required corrections. Rather than using the floor function at certain points, I used the intdiv function in place of every “/” operator, which more closely follows Richard’s description of the algorithm. After these corrections, the test cases were successful. (Richards considers the year 0 to exist and always converts to Gregorian.)

function jd_to_gd_rchrds ($J) {
$y=4716;    
$v=3;
$j=1401;    
$u=5;
$m=2;   
$s=153;
$n=12;  
$w=2;
$r=4;   
$B=274277;
$p=1461;    
$C=-38;

$f = $J + $j + intdiv(intdiv(4 * $J + $B,146097) * 3,4) + $C;

$e = $r * $f + $v;
$g = intdiv(($e % $p) , $r);

$h = $u * $g + $w;
$D = intdiv((($h%$s)) , $u) + 1;
$M = ((intdiv($h , $s) + $m) % $n) + 1;
$Y = intdiv($e , $p) - $y + intdiv($n + $m - $M,$n);

return "$M/$D/$Y"; 
}

Testcase results:

Julian day PHP internal Meeus      Richards
0          0/0/0        1/1/-4712  11/24/-4713
1          11/25/-4714  1/2/-4712  11/25/-4713
1507231.5  bad input    7/30/-586  bad input
1721420    12/26/-1     12/28/0    12/26/0
1721425    12/31/-1     1/2/1      12/31/0
1741426    10/5/55      10/7/55    10/5/55
2222444    9/28/1372    9/20/1372  9/28/1372
2299160    10/14/1582   10/4/1582  10/14/1582
2299161    10/15/1582   10/15/1582 10/15/1582
2399301.5  bad input    12/18/1856 bad input
2422444    4/29/1920    4/29/1920  4/29/1920
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement