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