ВНИМАНИЕ! На форуме начался конкурс - астрофотография месяца НОЯБРЬ!
0 Пользователей и 1 Гость просматривают эту тему.
А какой смысл григорианского календаря в столь отдалённом прошлом?
Может сразу работать в системе непрерывного счёта времени и не заморачиваться?
В общем, надеюсь на вашу помощь в данном вопросе. Если у кого-то есть методика для вычисления юлианской даты на большом отрезке времени, то буду очень благодарен за предоставленную помощь.
//------------------------------------------------------------------------------//// Ddd: Conversion of angular degrees, minutes and seconds of arc to decimal// representation of an angle //// Input://// D Angular degrees// M Minutes of arc// S Seconds of arc//// <return>: Angle in decimal representation////------------------------------------------------------------------------------double Ddd(int D, int M, double S){ // // Variables // double sign; if ( (D<0) || (M<0) || (S<0) ) sign = -1.0; else sign = 1.0; return sign * ( fabs((double)D)+fabs((double)M)/60.0+fabs(S)/3600.0 );}
//------------------------------------------------------------------------------//// Mjd: Modified Julian Date from calendar date and time//// Input://// Year Calendar date components// Month// Day// Hour Time components (optional)// Min// Sec//// <return>: Modified Julian Date////------------------------------------------------------------------------------double Mjd ( int Year, int Month, int Day, int Hour, int Min, double Sec ){ // // Variables // long MjdMidnight; double FracOfDay; int b; if (Month<=2) { Month+=12; --Year;} if ( (10000L*Year+100L*Month+Day) <= 15821004L ) b = -2 + ((Year+4716)/4) - 1179; // Julian calendar else b = (Year/400)-(Year/100)+(Year/4); // Gregorian calendar MjdMidnight = 365L*Year - 679004L + b + int(30.6001*(Month+1)) + Day; FracOfDay = Ddd(Hour,Min,Sec) / 24.0; return MjdMidnight + FracOfDay;}
// DE-0431LE-0431 -13200-AUG-15 00:00 JD -3100015.50 to 17191-MAR-15 00:00 JD 8000016.50cout << Mjd ( -13200, 8, 15, 0, 0, 0 ) + 2400000.5 << endl; // Ответ: -3100015.5cout << Mjd ( 17191, 3, 15, 0, 0, 0 ) + 2400000.5 << endl; // Ответ: 8000016.5
void Time::calcJD(bool cal) // https://web.archive.org/web/https://articles.adsabs.harvard.edu/pdf/1985QJRAS..26..151H{ // For Gregorian calendar int Ji = 1721426; int y = 4716; int j = 1401; int m = 3; int n = 12; int i = 1; int q = 0; int r = 4; int p = 1461; int v = 3; int u = 5; int s = 153; int t = 2; int w = 2; int Ys = year + y - (int)((n+m-i-month)/n); int g = (int)((int)((Ys+184)/100)*3/4)-38; int Ms = (month-m) % n; int Ds = day-i; jdn = (int)((p*Ys+q)/r) + (int)((s*Ms+t)/u) + Ds-j-g-0.5;}
if ((10000L*year+100L*month+day) > 15821004L) jdn -= g; // Gregorian calendar
void Time::calcJD(bool cal) // https://web.archive.org/web/https://articles.adsabs.harvard.edu/pdf/1985QJRAS..26..151H{ // For Gregorian calendar int Ji = 1721426; int y = 4716; int j = 1401; int m = 3; int n = 12; int i = 1; int q = 0; int r = 4; int p = 1461; int v = 3; int u = 5; int s = 153; int t = 2; int w = 2; int Ys = year + y - (int)((n+m-i-month)/n); int g = (int)((int)((Ys+184)/100)*3/4)-38; int Ms = (month-m) % n; int Ds = day-i; jdn = (int)((p*Ys+q)/r) + (int)((s*Ms+t)/u) + Ds-j-0.5; if ((10000L*year+100L*month+day) > 15821004L) jdn -= g; // Gregorian calendar}
Вот старая статья Hatcher, D. A. Generalized Equations for Julian Day Numbers and Calendar DatesТакже PDF прикреплён к сообщению.В ней приводится расширенный вариант расчёта Юлианской даты для разных календарей. О статье узнал из Трудов ИПА РАН, выпуск 10, 2004.Код: [Выделить]void Time::calcJD(bool cal) // https://web.archive.org/web/https://articles.adsabs.harvard.edu/pdf/1985QJRAS..26..151H{ // For Gregorian calendar int Ji = 1721426; int y = 4716; int j = 1401; int m = 3; int n = 12; int i = 1; int q = 0; int r = 4; int p = 1461; int v = 3; int u = 5; int s = 153; int t = 2; int w = 2; int Ys = year + y - (int)((n+m-i-month)/n); int g = (int)((int)((Ys+184)/100)*3/4)-38; int Ms = (month-m) % n; int Ds = day-i; jdn = (int)((p*Ys+q)/r) + (int)((s*Ms+t)/u) + Ds-j-g-0.5;}Из файла header.441JPL Planetary Ephemeris DE441/LE441Start Epoch: JED= -3100015.5-13200-AUG-15 00:00:00Final Epoch: JED= 8000016.5 17191-MAR-15 00:00:00На практике выходит-13200-8-15 0:0:0.0, Gregorian JD: -3099915.5 17191-3-15 0:0:0.0, Gregorian JD: 8000016.5То есть в + работает нормально, а в - ошибка ровно в 100 дней. Хз)P.S. Сейчас на некоторые зарубежные сайты вход закрыт. Один вариантов обхода это использование https://web.archive.org/web/. После web/ добавляем свою ссылку. Как раз верхняя ссылка так и сформирована. Да, ссылка будет устаревшей, но для доступа к архивам старых статей самое то.P.P.S. Разница 100 дней, это разница между Юлианским и Григорианским календарями на тот момент. Если добавить условие,Код: [Выделить]if ((10000L*year+100L*month+day) > 15821004L) jdn -= g; // Gregorian calendarто всё встаёт на свои места.Итоговый вариант:Код: [Выделить]void Time::calcJD(bool cal) // https://web.archive.org/web/https://articles.adsabs.harvard.edu/pdf/1985QJRAS..26..151H{ // For Gregorian calendar int Ji = 1721426; int y = 4716; int j = 1401; int m = 3; int n = 12; int i = 1; int q = 0; int r = 4; int p = 1461; int v = 3; int u = 5; int s = 153; int t = 2; int w = 2; int Ys = year + y - (int)((n+m-i-month)/n); int g = (int)((int)((Ys+184)/100)*3/4)-38; int Ms = (month-m) % n; int Ds = day-i; jdn = (int)((p*Ys+q)/r) + (int)((s*Ms+t)/u) + Ds-j-0.5; if ((10000L*year+100L*month+day) > 15821004L) jdn -= g; // Gregorian calendar}P.P.S. Условие для григорианского календаря я взял из Монтенбрука. Он ссылается на Sky & Telescope, April 1981. Там в статье сказано, что формулы взяты из Jean Meeus Astronomical formulae for calculators
/Astronomy/Ephemeris/GashaSoft/libMeneldil/JD/Tantzen$ ./a.out Julian->Gregorian: 2022-12-25 -> 2023-1-7 Diff = 13Gregorian->Julian: 2023-1-7 -> 2022-12-25 Diff = -13Julian->JD -13200-8-15 -> -3100015.500000JD->Julian -3100015.500000 -> -13200-8-15Gregorian->JD 17191-3-15 -> 8000016.500000JD->Gregorian 8000016.500000 -> 17191-3-15
void divmod(int a, int b, int& q, int& r){ /* * [url]https://skysmart.ru/articles/mathematic/delenie-chisel-s-ostatkom[/url] * Теорема * a = b · q + r, где * a — делимое, * b — делитель, * q — неполное частное, * r — остаток. 0 ⩽ r < |b| */ if (a%b==0) // Если делится без остатка { q = a/b; // Частное // quotient r = 0; // Остаток // remainder } else { if (a>0 && b>0) { q = static_cast<int>(a/b); r = a-b*q; if (r<0 && r>=abs(b)) std::cerr << " Error with rule r>=0 && r<abs(b)\n"; if (a!=(b*q+r)) std::cerr << " Error with a>0 && b>0\n"; } else if (a<0 && b>0) { q = -1*static_cast<int>(abs(a)/abs(b))-1; r = a-b*q; if (r<0 && r>=abs(b)) std::cerr << " Error with rule r>=0 && r<abs(b)\n"; if (a!=(b*q+r)) std::cerr << " Error with a<0 && b>0"; } else if (a>0 && b<0) { q = -1*static_cast<int>(abs(a)/abs(b)); r = a-b*q; if (r<0 && r>=abs(b)) std::cerr << " Error with rule r>=0 && r<abs(b)\n"; if (a!=(b*q+r)) std::cerr << " Error with a>0 && b<0"; } else if (a<0 && b<0) { q = -1*static_cast<int>(abs(a)/abs(b))+1; r = a-b*q; if (r<0 && r>=abs(b)) std::cerr << " Error with rule r>=0 && r<abs(b)\n"; if (a!=(b*q+r)) std::cerr << " Error with a<0 && b<0"; } }}
// From Gregorian Date to CJDN int a,m,a1,m1,c1,a2,d,J; a = -1000000; m = 1; d = 1; divmod((m-3), 12, a1, m1); divmod((a+a1), 100, c1, a2); J = floor(146097*c1/4.0); J += floor(36525*a2/100); J += floor((153*m1+2)/5.0); J += d+1721119; std::cout << std::fixed << " J= " << J << "\n"; // From CJDN to Gregorian Date int e1, e2, e3, m2; divmod((4*J-6884477), 146097, c1, e1); divmod((100*floor(e1/4)+99), 36525, a1, e2); divmod((5*floor(e2/100)+2), 153, m1, e3); divmod((m1+2), 12, a2, m2); a = 100*c1+a1+a2; m=m2+1; d = floor(e3/5.0)+1; std::cout << a << "-" << m << "-" << d << "\n"; // From Julian Date to CJDN divmod((m-3), 12, a1, m1); J = floor(1461*(a+a1)/4.0); J += floor((153*m1+2)/5.0); J += d + 1721117; std::cout << std::fixed << " J= " << J << "\n"; // From CJDN to Julian Date int m0, alpha1; divmod((4*J-6884469), 1461, a1, e1); divmod((5*floor(e1/4.0)+2), 153, m1, e2); divmod((m1+2), 12, alpha1, m0); a = a1+alpha1; m = m0+1; d = floor(e2/5.0)+1; std::cout << a << "-" << m << "-" << d << "\n";
Проверка сайта [url]https://www.aa.quae.nl/en/reken/juliaansedag.html[/url] J= -363521440-1000000-1-1 J= -363528942-1000000-1-1