Menu ≡
kalendar.beda.cz

Výpočet kalendářního data z čísla juliánského dne

Výpočet juliánského kalendářního data z čísla juliánského dne

Pokud potřebujeme z čísla juliánského dne vypočítat kalendářní datum, vyplatí se zavést pomocný kalendář, který pak výpočet podstatně zjednoduší. Po skončení výpočtu potom provedeme triviální konverzi z pomocného na juliánský či gregoriánský kalendář. V následujících výpočtech budeme pro číslování roků používat astronomickou notaci, která pracuje s rokem 0, více na zdejší stránce Existoval rok nula?. Nejprve budeme pracovat s juliánským kalendářem, ten je jednodušší. Rok pomocného kalendáře bude začínat 1. března a končit posledního února, někdy to může být přestupný den. Nyní nás zajímá počet dnů v pomocném roce před libovolným měsícem. Pokud k tomuto číslu připočteme den daného měsíce, zjistíme počet dnů od začátku pomocného roku. Využijeme toho, že počty dnů měsíce se opakují v sérii 31+30+31+30+31 a můžeme sestavit tuto tabulku, kde v první řádce jsou délky měsíců a následujících řádcích je za zkratkou měsíce počet dnů od začátku roku do konce předchozího měsíce:

3130313031
bře:0dub:31kvě:61čer:92čec:122
srp:153zář:184říj:214lis:245pro:275
led:306úno:337

Pravidelnost je porušena až únorem, to je ale poslední měsíc pomocného kalendáře a protože nás zajímá počet dnů od začátku roku do konce předchozího měsíce, nemusíme se v tomto případě nestandardní délkou února vůbec zabývat.

Číslo měsíce pomocného kalendáře označíme m a jeho číslování měsíců bude začínat od 0. Tedy březen bude 0 a únor 11. Tímto vzorcem zjistíme počet dnů od začátku roku do konce předchozího měsíce, pro březen (m=0) dává vzorec výsledek 0.

dnů_v_roce = int((153 * m + 2) / 5)

Existuje 'inverzní' vzorec pro výpočet čísla měsíce z počtu dní, ten později využijeme:

m = int((5 * dnů_v_roce + 2) / 153)

Protože juliánský kalendář má epochu 1. ledna -4712, tak se nám do pomocného kalendáře, který začíná březnem nehodí. Zavedeme tedy jinou epochu, která bude začínat v březnu a hlavně před tímto datem, díky tomu budou všechny výpočty s nezápornými čísly, což programový kód zjednoduší. Byl zvolen 1. březen -4800, v tento den bude pomocné číslo juliánského dne rovno 0.

juliánský kal. -4800
1 2 3 4 5 6 7 8 9 10 11 12
pomocný kal. 10 11 0 1 2 3 4 5 6 7 8 9
-4801 -4800

Primitivním výpočtem provedeme konverzi z čísla juliánského dne (jdn) na pomocný juliánský den (jdnx), kde konstanta 32082 je počet dnů mezi 1. březnem -4800 a 1. lednem -4712 (88 × 365.25 - (31 + 29)):

jdnx = jdn + 32082

V pomocném kalendáři jinak platí stejná pravidla jako v juliánském, každý čtvrtý rok je přestupný. Data se tedy opakují v cyklu čtyř let, který má 1461 dní (365+365+365+366). Následujícím výpočtem zjistíme číslo roku pro libovolný den. Konstanta 3 značí pořadové číslo přestupného roku v cyklu pomocného kalendáře (začínáme od roku -4800, který začíná 1. března a neobsahuje přestupný den):

y = int((4 * jdnx + 3) / 1461)

Ze znalosti čísla roku vypočteme pořadové číslo prvního dne roku. Pak jeho odečtením od jdnx zjistíme pořadové číslo dne v rámci roku (začínáme od 0):

dy = jdnx - int(1461 * y / 4)

Vzorec pro výpočet čísla měsíce (0: březen, 11: únor) z pořadového čísla dne roku už známe :

m = int((5 * dy + 2) / 153)

Když od pořadového čísla roku odečteme počet dnů v předchozích měsících dostaneme číslo dne v měsíci. Musíme připočítat 1 neboť doposud jsme počítali od 0:

day = dy - int((153 * m + 2) / 5) + 1

A nyní stačí jen provést triviální konverzi čísla měsíce a roku pomocného kalendáře na měsíc a rok juliánského kalendáře.

if (m < 10) {
    month = m + 3
    year = y - 4800
}
else {
    month = m - 9
    year = y - 4800 + 1
}

V praxi pochopitelně výraz y - 4800 + 1 zjednodušíme na y - 4799, ale pak tolik nevynikne konstanta. Lze to i zapsat bez použití podmínek, pak si musíme pomoci proměnnou, která nabývá hodnoty 0 pro měsíce menší jak 10 a 1 pro větší nebo rovné 10.

a = int(m / 10)
month = m + 3 - 12 * a
year = y - 4800 + a

Celý postup zapsaný v pseudokódu pak vypadá takto:

jdnx = jdn + 32082
y = int((4 * jdnx + 3) / 1461)
dy = jdnx - int(1461 * y / 4)
m = int((5 * dy + 2) / 153)
day = dy - int((153 * m + 2) / 5) + 1
a = int(m / 10)
month = m + 3 - 12 * a
year = y - 4800 + a

Algoritmus přepsaný do programovacího jazyka Python:

jdnx = jdn + 32082
y = (4 * jdnx + 3) // 1461
dy = jdnx - 1461 * y // 4
m = (5 * dy + 2) // 153
a = m // 10
year = y - 4800 + a
month = m + 3 - 12 * a
day = dy - (153 * m + 2) // 5 + 1

Toto je jeden z nejoblíbenějších, nejčitelnějších a nejkratších postupů zjištění kalendářního data juliánského kalendáře z čísla juliánského dne. Nic nám však nebrání zvolit jinou epochu pomocného kalendáře, pak se pochopitelně změní jen několik konstant. Například epocha pomocného kalendáře bude 1. březen -4714. Konstanta 671 je pak počet dní k 1.lednu -4712 a přestupný rok je pak první v pořadí. Konstanta 2 ve výrazu int((1461 * y + 2) / 4) značí počet let od přestupného roku do konce cyklu. V předchozím algoritmu byla 0. Výsledek potom vypadá takto:

jdnx = jdn + 671
y = int((4 * jdnx + 1) / 1461)
dy = jdnx - int((1461 * y + 2) / 4)
m = int((5 * dy + 2) / 153)
day = dy - int((153 * m + 2) / 5) + 1
a = int(m / 10)
month = m + 3 - 12 * a
year = y - 4714 + a

Jiné algoritmy pro výpočet juliánského kalendářního data z čísla juliánského dne

Poněkud nepřehledný postup od Henry Fliegela z roku 1990 zveřejněný v 'Explanatory Supplement to the Astronomical Almanac'.

J = jdn + 1402
K = int((J - 1) / 1461)
L = J - 1461 * K
N = int((L - 1) / 365) - int(L / 1461)
I = L - 365 * N + 30
J = int((80 * I) / 2447)
day = I - int((2447 * J) / 80)
I = int(J / 11)
month = J + 2 - 12 * I
year = 4 * K + N + I - 4716

I umělá inteligence GPT přispěla svým algoritmem:

n = jdn - 1721058

# Čtyřleté cykly
q = int((n - (n % 1461)) / 1461)
r = n % 1461
s = int(4 * r / 1461)

year = 4 * q + s
doy = r - 365 * s - int((s + 3) / 4)

# Přestupný rok: 1 jinak 0
leap = int(year % 4 == 0)

# Převod přes březnový počátek
e = (doy + 306) % (365 + leap)
m = int((5 * e + 2) / 153)

month = (m + 2) % 12 + 1
day = e - int((153 * m + 2) / 5) + 1

V programovacím jazyce Python to vypadá ještě lépe:

n = jdn - 1721058
q, r = divmod(n, 1461)
s = 4 * r // 1461
year = 4 * q + s
doy = r - 365 * s - (s + 3) // 4
leap = int(year % 4 == 0)
e = (doy + 306) % (365 + leap)
m = (5 * e + 2) // 153
month = (m + 2) % 12 + 1
day = e - (153 * m + 2) // 5 + 1

Výpočet gregoriánského kalendářního data z čísla juliánského dne

Gregoriánský kalendář je komplikovanější, má navíc cyklus 400 let, kdy první tři centenární roky (končící 00) nejsou přestupné. Přestupný je až centenární rok dělitelný 400 beze zbytku. Tento velký cyklus 400 let má 146 097 dní (365 × 303 + 366 × 97). Použijeme stejný fígl jako v juliánském kalendáři, pomocný kalendář bude začínat 1. března -4800, ale gregoriánského kalendáře. Prvním krokem bude zjistit pozici v 400letém cyklu a pak už postupujeme podobně jako v juliánském kalendáři.

Nejprve provedeme konverzi z čísla juliánského dne (jdn) na pomocný juliánský den (jdnx), kde konstanta 32044 je počet dnů mezi 1. březnem -4800 a 1. lednem -4712 (rozdíl mezi extrapolovanými kalendáři je v tu dobu 38 dní (32082 - 38)):

jdnx = jdn + 32044

Takto nalezneme počet století od pomocné epochy:

c = int((4 * jdnx + 3) / 146097)

Nyní hledáme čítač dní ve velkém, 400letém cyklu:

dc4 = jdnx - int(146097 * c / 4)

Najdeme kolik uplynulo roků ve století:

yc1 = int((4 * dc4 + 3) / 1461)

A určíme pořadí dne uvnitř pomocného roku:

dy = dc4 - int(1461 * yc1 / 4);

Zjištění pomocného měsíce a převod data na gregoriánské kalendářní datum je stejný, až na výpočet gregoriánského roku, tam připočítáváme navíc století. Výsledek pak vypadá takto:

jdnx = jdn + 32044
c = int((4 * jdnx + 3) / 146097)
dc4 = jdnx - int(146097 * c / 4)
yc1 = int((4 * dc4 + 3) / 1461)
dy = dc4 - int(1461 * yc1 / 4)
m = int((5 * dy + 2) / 153)
day = dy - int((153 * m + 2) / 5) + 1
a = int(m / 10)
month = m + 3 - 12 * a
year = 100 * c + yc1 - 4800 + a

Algoritmus přepsaný do programovacího jazyka Python:

jdnx = jdn + 32044
c = (4 * jdnx + 3) // 146097
dc4 = jdnx - 146097 * c // 4
yc1 = (4 * dc4 + 3) // 1461
dy = dc4 - 1461 * yc1 // 4
m = (5 * dy + 2) // 153
a = m // 10
year = 100 * c + yc1 - 4800 + a
month = m + 3 - 12 * a
day = dy - (153 * m + 2) // 5 + 1

Jiné algoritmy pro výpočet gregoriánského kalendářního data z čísla juliánského dne

Algoritmus od Fliegela a Van Flanderna z roku 1968 zveřejněný v 'Explanatory Supplement to the Astronomical Almanac'.

L = jdn + 68569
N = int((4 * L) / 146097)
L = L - int((146097 * N + 3) / 4)
I = int((4000 * (L + 1)) / 1461001)
L = L - int((1461 * I) / 4) + 31
J = int((80 * L) / 2447)
day = L - int((2447 * J) / 80)
L = int(J / 11)
month = J + 2 - 12 * L
year = 100 * (N - 49) + I + L

Komplikovaný algoritmus z OpenJDK (Open Java Development Kit):

zeroDay = jdn - 1721120
adjust = 0
if (zeroDay < 0) {
    adjustCycles = int((zeroDay + 1) / 146097) - 1
    adjust = adjustCycles * 400
    zeroDay += -adjustCycles * 146097
}
yearEst = int((400 * zeroDay + 591) / 146097)
doyEst = zeroDay - (365 * yearEst + int(yearEst / 4) - int(yearEst / 100) + int(yearEst / 400))
if (doyEst < 0) {
    yearEst -= 1
    doyEst = zeroDay - (365 * yearEst + int(yearEst / 4) - int(yearEst / 100) + int(yearEst / 400))
}
yearEst += adjust
marchDoy0 = doyEst
marchMonth0 = int((marchDoy0 * 5 + 2) / 153)
month = (marchMonth0 + 2) % 12 + 1
day = marchDoy0 - int((marchMonth0 * 306 + 5) / 10) + 1
year = yearEst + int(marchMonth0 / 10)

Mezi astronomy je oblíbený univerzální algoritmus od Jeana Meeuse z nedostižné knihy 'Astronomical Algorithms' (1991). Konstanta 2299161 udává juliánské číslo dne od kterého platí gregoriánský kalendář (zde 15.říjen 1582) a algoritmus pak vrací kalendářní data v tomto kalendáři. Před tímto dnem vrací kalendářní data juliánského kalendáře. Tuto konstantu můžete změnit dle kalendářního data reformy ve vybrané lokalitě. Potřebná data najdete na zdejší stránce Data přijetí gregoriánského kalendáře v různých zemích.

if (jdn < 2299161) {
    A = jdn
}
else {
    alpha = int((jdn - 1867216.25) / 36524.25)
    A = jdn + 1 + alpha - int(alpha / 4)
}
B = A + 1524
C = int((B - 122.1) / 365.25)
D = int(365.25 * C)
E = int((B - D) / 30.6001)

day = B - D - int(30.6001 * E)

if (E < 14) {
    month = E - 1
}
else {
    month = E - 13
}
if (month > 2) {
    year = C - 4716
}
else {
    year = C - 4715
}

Originální algoritmus počítá s juliánským dnem, který obsahuje i desetinnou část a navíc se mění v poledne. Převod na číslo juliánského dne je však triviální:

jdn = int(jd + 0.5)

Pozor při převodu tohoto algoritmu do programovacího jazyka. Například v Pythonu, používejte výrazy int(a / b) a nikoli a // b. Pro záporná čísla dávají totiž tyto výrazy rozdílné výsledky, viz int(-7 / 4) = -1 a -7 // 4 = -2.

Všechny algoritmy na této stránce byly testovány jen pro nezáporná čísla juliánského dne.

Další informace:

Kalendáře Helma - nástěnný, stolní i pracovní kalendář Diáře Helma - diář a zápisník
Válka na Ukrajině: 1695.den
QR kód

Pokud se na tento web rádi vracíte pro praktické informace nebo si díky němu rozšiřujete své znalosti o kalendáři, můžete autorovi vyjádřit svou podporu malým finančním příspěvkem. Stačí oskenovat přiložený QR kód (kliknutím lze zvětšit) a snadno přispět přes QR platbu.

Děkuji za vaši štědrost a podporu!


Nahoru