Menu ≡
kalendar.beda.cz

Algoritmy pro výpočet čísla juliánského dne

Princip výpočtu je vcelku jednoduchý, stačí spočítat počet dnů od určitého data, pro jednoduchost budu pracovat ze začátku pouze s juliánským kalendářem a s astronomickým číslováním letopočtu, tedy pracuje se s rokem 0 i se zápornými roky, viz stránka Existoval rok nula? Kdyby neexistovaly přestupné dny, stačilo by násobit počet let 365 a připočítat počet dnů v daném roce. Avšak v juliánském kalendáři je každý čtvrtý rok přestupný. Musíme tedy každý čtvrtý rok připočítat jeden den, naneštěstí se přestupný den přidává na konci února, takže pro lednová a únorová data v přestupném roce se nic nepřipočítává, na to je zapotřebí pamatovat. Větší problém je zjistit počet dnů v roce do daného kalendářního data, problém dělají nestejně dlouhé měsíce. Najít jednoduchou funkci, která vrací uplynulý počet dnů v roce pro daný měsíc je obtížné. Pomůžeme si tabulkou, která udává kolik dnů v roce uplynulo do konce předcházejícího měsíce.

měsícledenúnorbřezendubenkvětenčervenčervenecsrpenzáříříjenlistopadprosinec
dnů v roce0315990120151181212243273304334
měsícdnů v roce
leden0
únor31
březen59
duben90
květen120
červen151
červenec181
srpen212
září243
říjen273
listopad304
prosinec334

Použití je snadné, například nás zajímá kolikátý den v (nepřestupném) roce je datum 8. května. V tabulce pro květen nalezneme, že do konce předchozího měsíce uplynulo 120 dnů, připočteme počet dnů v květnu, tedy 8, a výsledek je 128. 8. květen je tedy 128. dnem v nepřestupném roce. V přestupném roce je pak nutno pro březnová a pozdější data připočítat jeden den (březen=60). Vzorec je jednoduchý:

den + dnů_v_roce

Pokud nás zajímá počet dnů od 1. ledna roku 0 (v chronologické vyjádření 1. leden roku 1 př. n. l.) do konce předchozího roku, výpočet je poměrně jednoduchý:

365 * rok + int(rok / 4)

Výraz int(rok / 4) připočítá jeden den každý čtvrtý rok, viz tabulka (v přestupných letech odečtěte 1):

rok123456789
dnů3657301095146118262191255629223287
rokdnů
1365
2730
31095
41461
51826
62191
72556
82922
93287

Nyní můžeme oba vzorce sloučit a dostaneme návod pro výpočet počtu dní od začátku roku 0. Pokud půjde o přestupný rok a současně datum bude z ledna či února, bude zapotřebí odečíst jeden den, protože jde o datum před přestupným dnem a člen int(rok / 4) již jeden den připočetl.

den + dnů_v_roce + 365 * rok + int(rok / 4)
je-li přestupný rok a současně měsíc <= 2 pak nutno odečíst 1

Například nás zajímá kolik dnů uplynulo od 1. ledna roku 0 do 29. listopadu 1378 (od začátku roku do konce října uplynulo 304 dnů):

29 + 304 + 365 * 1378 + int(1378 / 4) = 503647 dnů

Pro lednová a únorová data je výpočet stejný, jen na konci odečteme 1. Viz příklad výpočtu pro 5. únor 1236:

5 + 31 + 365 * 1236 + int(1236 / 4) = 451485 - 1 = 451484

Protože nás zajímá číslo juliánského dne, tedy počet dnů od 1. ledna roku -4712, musíme poupravit číslování roků, což lehce provedeme přičtením čísla 4712 k roku. Výsledkem celého výpočtu pak bude číslo juliánského dne. Viz výpočet pro předchozí datum:

5 + 31 + 365 * (1236 + 4712) + int((1236 + 4712) / 4) = 2172543 - 1 = 2172542

Pokud nechcete k roku nic připočítávat, lze připočíst konstantu 1721058 (365 * 4712 + 4712/4, číslo juliánského dne pro 1. leden roku 0) až ke konečnému výsledku. Výsledek bude pochopitelně stejný. Vzorec pro výpočet čísla juliánského dne z kalendářních dat juliánského kalendáře vypadá takto:

jdn = den + dnů_v_roce + 365 * rok + int(rok / 4) + 1721058
je-li přestupný rok a současně měsíc <= 2 pak jdn = jdn - 1

Následuje příklad výpočtu pro 29. listopad 1378:

29 + 304 + 365 * 1378 + int(1378 / 4) + 1721058 = 2224705

A příklad výpočtu pro 5. únor 1236:

5 + 31 + 365 * 1236 + int(1236 / 4) + 1721058 = 2172543 - 1 = 2172542

V gregoriánském kalendáři je princip samozřejmě stejný, jen je nutno pamatovat na komplikovanější pravidla pro přestupné roky. Ke konečnému výsledku je pak nutné připočítat konstantu 1721060, která je o dva dny větší než pro juliánský výpočet. V roce 0 byl totiž hypotetický rozdíl mezi oběma kalendáři dva dny. Tentokrát totiž není možné hned k roku přičíst konstantu 4712. Za prvé jde o proleptický gregoriánský kalendář (proleptické datování: pravidla určitého kalendáře se aplikují i na data před jeho zavedením) a rozdíl ve dnech od juliánského kalendáře je v roce -4712 již 38 dní. Je-li číslo juliánského dne rovno nule, tak proleptické gregoriánské datum je 24. listopadu -4713. A za druhé, by se nedala testovat přestupnost gregoriánských roků. Někdy se to řeší přičtením konstanty 4800, ale pak je stejně nutno na konci výpočtu odečíst další konstantu. Vše ostatní je stejné jako u juliánského kalendáře.

jdn = den + dnů_v_roce + 365 * rok + int(rok / 4) - int(rok / 100) + int(rok / 400) + 1721060
je-li přestupný rok a současně měsíc <= 2 pak jdn = jdn - 1

Níže je příklad výpočtu pro 28. října 1918:

28 + 273 + 365 * 1918 + int(1918 / 4) - int(1918 / 100) + int(1918 / 400) + 1721060 = 2421895

Jak vidno největší komplikovanost je určení počtu dní roku a přestupný den na konci února, tedy uvnitř roku. Tomu se lze vtipně vyhnout, pokud rok bude končit 28. únorem, případný přestupný den bude prvním dnem roku, jinak to bude 1. březen. Březen bude nultým měsícem a leden s únorem budou patřit do předcházejícího roku. Přečíslovaný měsíc je v níže uvedené tabulce označen písmenem m. Tabulka opět zobrazuje počet dnů v roce do konce předcházejícího přečíslovaného měsíce. Pracujeme-li s lednem a únorem je zapotřebí od čísla roku odečíst 1, přečíslovaný rok je označen y.

měsícledenúnorbřezendubenkvětenčervenčervenecsrpenzáříříjenlistopadprosinec
m10110123456789
dnů v roce3063370316192122153184214245275
měsícmdnů v roce
leden10306
únor11337
březen00
duben131
květen261
červen392
červenec4122
srpen5153
září6184
říjen7214
listopad8245
prosinec9275

Pro hodnoty přečíslovaných měsíců již lze najít jednoduchý vzorec pro výpočet počtu dní roku do konce předcházejícího přečíslovaného měsíce. A ten vypadá takto:

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

V juliánském kalendáři pak vzorec pro výpočet čísla juliánského dne může vypadat takto:

if mesic > 2
    y = rok
    m = mesic - 3
else
    y = rok - 1
    m = mesic + 9
    
jdn = den + int((153 * m + 2) / 5) + 365 * y + int(y / 4) + 1721117

Konstanta 1721117 se liší o 59 dnů (součet počtu dnů v lednu a únoru), neboť přečíslovaný rok začíná o dva měsíce později. Někdy panuje nechuť k podmínkám v algoritmu, přidává se proto další pomocná proměnná, která nabývá hodnot 0 (od března výše) a 1 (leden únor). Ve vzorcích níže je označena a.

a = int((14 - mesic) / 12)
y = rok - a
m = mesic + 12 * a - 3

Vlastní výpočet čísla juliánského dne je již stejný. Takže algoritmus pro výpočet čísla juliánského dne pro kalendářní data juliánského kalendáře vypadá takto:

a = int((14 - mesic) / 12)
y = rok - a
m = mesic + 12 * a - 3
jdn = den + int((153 * m + 2) / 5) + 365 * y + int(y / 4) + 1721117

A algoritmus pro výpočet čísla juliánského dne pro kalendářní data gregoriánského kalendáře vypadá podobně:

a = int((14 - mesic) / 12)
y = rok - a
m = mesic + 12 * a - 3
jdn = den + int((153 * m + 2) / 5) + 365 * y + int(y / 4) - int(y / 100) + int(y / 400) + 1721119

Jiné algoritmy pro výpočet čísla juliánského dne

Výše uvedené algoritmy nejsou samozřejmě jediné, existuje více možností jak vypočítat číslo juliánského dne. Níže je zobrazeno několik nejoblíbenějších algoritmů. Pokud je budete převádět do nějakého programovacího jazyka, nezapomeňte na rozdílné výsledky funkce integer pro záporná čísla. Například Python vrací pro výraz (-1 // 9) hodnotu -1, naproti tomu PHP (int)(-1 / 9) a Javascript parseInt(-1 / 9) vrací hodnotu 0. Zde uvedené algoritmy předpokládají, že výraz int(-1 / 9) vrací 0.

Kompaktní jednořádkový vzorec (autor Henry Fliegel 1970) pro juliánský kalendář:

jdn = 367 * rok - int((7 * (rok + 5001 + int((mesic - 9) / 7))) / 4) + int((275 * mesic) / 9) + den + 1729777

Sice jednořádkový, ale předlouhý vzorec (autoři Henry Fliegel a Van Flandern 1968) pro gregoriánský kalendář:

jdn = int((1461 * (rok + 4800 + int((mesic - 14) / 12))) / 4) + int((367 * (mesic - 2 - 12 * int((mesic - 14) / 12))) / 12) - int((3 * ((rok + 4900 + int((mesic - 14) / 12)) / 100)) / 4) + den - 32075

Mezi astronomy je oblíbený algoritmus od Jeana Meeuse pro juliánský kalendář:

if mesic > 2
    y = rok
    m = mesic
else
    y = rok - 1
    m = mesic + 12
    
jdn = int(365.25 * (y + 4716)) + int(30.6001 * (m + 1)) + den - 1524

A pro gregoriánský kalendář:

if mesic > 2
    y = rok
    m = mesic
else
    y = rok - 1
    m = mesic + 12

a = int(y / 100)
b = 2 - a + int(a / 4)

jdn = int(365.25 * (y + 4716)) + int(30.6001 * (m + 1)) + den + b - 1524

Liší se jen použitím proměnné b, která udává rozdíl mezi oběma kalendáři pro dané století ve dnech. Zbývá ještě objasnit použití zvláštní konstanty 30.6001. Ve skutečnosti by postačovala hodnota 30.6, ale díky binárnímu uložení této hodnoty v paměti počítače dochází k jisté malé nepřesnosti (více v článku Proč počítačům dělají problémy desetinná čísla). Výsledkem výrazu int(30.6 * 5) je pak někdy 152 a ne správných 153. Proto se tato konstanta v praktickém výpočtu pro jistotu malinko zvětší a uvedený výraz pak vrací správnou hodnotu.

Vzorec pro výpočet počtu dní roku do konce předcházejícího měsíce

Doktor A. Fuortes z Itálie našel vzorec pro výpočet počtu dní v roce do konce předcházejícího měsíce. Pro praktické použití je nevhodný, neboť používá cyklometrickou funkci, uvádím jej zde pouze jako zajímavost. Funkce arkus tangens (atan) pracuje v radiánech. Výpočtem pak dostaneme přesně stejné hodnoty, jaké jsou v první tabulce na této stránce.

dnů_v_roce = int(30.6001 * (měsíc - 1) - (0.4 + 0.9 * atan(3 * (měsíc - 2.5))))

Další informace:

Nahoru