Алгоритмы следующие:
JD 1099114.5
PHP: 3 марта -1704 12:00:00 (внутренний конвертор PHP)
echo jdtogregorian($int_jd);
FLN: 0 марта -1703 12:00:00 (Флигель-Ван Фландерн)
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 марта -1703 12:00:00 (Жан Миус «Астрономические алгоритмы, 2-е изд., Исправлено)
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 марта -1703 12:00:00 (Ричардс в пояснительном дополнении 3-е изд.)
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";
}
У каждого алгоритма есть свои проблемы.
Что я делаю не так с кодом?
Для справки данные испытаний должны включать:
JD: 2399301,5
JD: 1721420
JD: 1721425
JD: 1721426
JD: 2422444
JD: 2222444
Меус предполагает, что существует григорианский год 0, даже если это астрономически правильно, он не имеет большого смысла с точки зрения календаря. Технически тогда все результаты по конвертации в григорианские даты просто неверны? Если говорить по календарю, если нет 0, но астрономически есть 0, как это переводится в ту же дату?
Я не смотрел на алгоритм Флигеля-Ван Фландерна. Я протестировал оставшийся алгоритм для тестовых случаев, запрошенных Дэнни Ф., и добавил последний полдень, в котором юлианский календарь наблюдался в Риме (JD 2299160), и первый полдень григорианского календаря в Риме (JD 2299161). Для нецелых юлианских дней я использовал только алгоритм Мееуса, так как он единственный, который говорит, что поддерживает нецелые числа.
Внутренний алгоритм был верным, если учесть, что год 0 не существует, и он всегда конвертируется в григорианский. Алгоритм Мееуса верен, когда вы допускаете, что он предполагает существование года 0 и преобразовывает его в юлианский для 4 октября 1582 года и ранее и в григорианский для дат после этого.
Алгоритм Ричардса потребовал исправлений. Вместо того, чтобы использовать функцию floor в определенных точках, я использовал функцию intdiv вместо каждого оператора «/», что более точно следует описанию алгоритма Ричардом. После этих исправлений тестовые случаи были успешными. (Ричардс считает, что год 0 существует и всегда преобразуется в григорианский.)
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";
}
Результаты теста:
Юлианский день PHP внутренний Мееус Ричардс 0 0/0/0 1/1 / -4712 11/24 / -4713 1 11/25 / -4714 1/2 / -4712 11/25 / -4713 1507231,5 Плохой ввод 7/30 / -586 Плохой ввод 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 28.09.1372 20.09.1372 28.09.1372 2299160 14.10.1582 10.04.1582 14.10.1582 2299161 15.10.1582 15.10.1582 15.10.1582 2399301.5 плохой ввод 18.12.1856 плохой ввод 2422444 29.04.1920 29.04.1920 29.04.1920
Нет, не существует такого понятия, как григорианский год 0, потому что григорианский календарь не начинался до 1582 года. Астрономические алгоритмы используют юлианский календарь до реформы григорианского календаря. Да астрономические алгоритмы возвращают ноль года. Миус абсолютно прав. Годы не совпадают с годами до нашей эры. Поищи это. Любой алгоритм, который использует BC-AD, использует полностью вымышленный пролептический григорианский календарь, который не используется астрономами. Поищи это.
void JDToDateMeeus(double jDNum, int *month, double *day, int *year) //converts a Julian day to a calendar Date
{
int alpha, A, B, C, D, E, Z;
double F;
jDNum += 0.5;
Z = jDNum; //Z == int so I = int part
F = jDNum - Z; //F = fractional part
if(Z < 2299161) //Julian?
A = Z;
else{ //Gregorian
alpha = (int)floor((Z - 1867216.25) / 36524.25);
A = Z + 1 + alpha - (int)floor(alpha / 4.0);
}
B = A + 1524;
C = (int)floor((B - 122.1) /365.25);
D = (int)floor(365.25 * C);
E = (int)floor((B - D) /30.6001);
*day = B - D - (int)floor(30.6001 * E) + F;
if( E < 14)
*month = E - 1;
else
*month = E - 13;
if(*month > 2)
*year = C - 4716;
else
*year = C - 4715;
}
double DateToJulianDayNumber(int month, double day, int year) //after Meeus
{
int M, Y, A, B;
double JD;
if(month > 2){
Y = year;
M = month;
}
else{
Y = year - 1;
M = month + 12;
}
if((year > 1582) || ((year == 1582) && ((month == 10 && day >= 5.0) || (month > 10)))){ //Gregorian
A = (int)floor(Y / 100.0);
B = 2 - A + (int)floor(A / 4.0);
}
else
B = 0;
JD = (int)floor(365.25 * (Y + 4716)) + (int)floor(30.6001 * (M + 1)) + day + B - 1524.5;
return JD;
}
Эти функции не используют вымышленный пролептический григорианский календарь. После 15 октября 1582 года, согласно календарной реформе папы Григория. Использует григорианские високосные годы после 1582 года. Существует год 0 и годы до того, которые записаны со знаком минус.