HEJMO
EO
| FR
| EN
| |
Tradukoj: traduction française (FR) | english translation (EN)
Se via TTT-legilo ne permesas JavaScript-on, vi ne povas nek vidi nek uzi la ĉisuban JavaScript-itan tagnumerilon:
Kiom da tagoj apartigas du kalendarajn datojn?
Kiu dato apartiĝas iom da tagojn de iu dato?
Tiaj simplaj demandoj ŝajnas malsimple respondeblaj, pro la tempokalkulaj sistemoj, t.e. kalendaroj, aspektas malmulte regulaj, esceptoplenaj. Tial kutimaj kalendaraj algoritmoj uzas abakojn por komputi de ĉiu dato la tagnumeron, laŭ vicaj tagnumeroj, de kie la problemo reduktiĝas al simpla aritmetika diferenco inter du tagnumeroj.
Tiu artikolo prezentas senabakan
tagnumeran algoritmon,
kaj ties inverson (de tagnumero al dato), por la nuna
okcidenta Gregoria kalendaro,
aŭ ties pli simpla Julia antaŭanto
ankoraŭ uzebla hodiaŭ se nur tra du jarcentoj.
Ĉar ambaŭ algoritmoj necesas nur simplan
entjeran aritmetikon,
kun nur entjeraj (senkomaj) nombroj kaj eŭklidaj dividoj
(t.e. kun entjeraj kvociento kaj resto), ili estas
aparte taŭgaj por simplaj komputrimedoj,
kiaj permana komputado
aŭ la plej malmultekostaj (kaj plej multnombraj) procesoretoj.
La terglobo rivoluas ĉirkaŭ sia polusa akso
po unu tago relative
al la suno, kaj ĉirkaŭ la suno
po unu jaro relative al foraj steloj.
La senŝanĝa angulo inter la du rivoluaj aksoj kaŭzas la sezonojn,
kun kiuj provas samfazi la tielnomataj "sunaj" kalendaroj,
kiaj la Gregoria kaj Julia.
Nuntempa astronomia mezuro de
unu jaro egalas proksimume 365,2422 tagoj.
La Julian kalendaron enkondukis
la romiana imperiestro Julio Cezaro
en 45 a.K. konsilite de egiptaj astronomiistoj.
Ĝia jaro entenas 365 tagoj, dispartigitaj en la nunaj 12 monatoj,
plus unu "supertago",
aldonita la 29an de februaro
ĉiu "superjaro" obla de kvar.
Tiu alproksimiĝo de la jardaŭro,
meznombre 365,25 tagoj,
bonega relative al tiamaj astronomiaj iloj,
tamen malfruigas la Julian kalendaron proksimume po 3 tagoj en ĉiu
kvarcentjara periodo.
Post kvar tiaj periodoj, pro tro evidenta malfruo,
la Gregorian kalendaron enkondukis
katolika papo Gregorio la 13a en 1582.
Li unue plibonigis l' alproksimiĝon de la jardaŭro,
meznombre 365,2425 tagoj,
per salto de la supertago de ĉiu jaro obla de cent sed ne de kvarcent,
t.e. de tri supertagoj en ĉiu kvarcentjara periodo,
kaj due refazigis la kalendaron per salto de 10 tagoj:
la morgaŭo de jaŭdo 1582-10-04
estis vendredo 1582-10-15.
La ŝanĝon, de la Julia kalendaro al la Gregoria, ne tuj akceptis ĉiuj
landoj: unuaj estis la katolikaj (ekz. Francio ekde lundo 1582-12-20),
pli poste la protestantaj (ekz. Anglio ekde jaŭdo 1752-08-14), kaj
eĉ pli poste la ortodoksaj (ekz. Rusio ekde jaŭdo 1918-02-14).
Unue ni elektu la 1an de Marto kiel komenco de la jara periodo
(kaj do numeru januaro=13 kaj februaro=14):
al ties fino tiel foriras la okazebla supertago.
Plie, aperas kvinmonata periodo
de 31+30+31+30+31 = 153 tagoj:
Kalendaraj faktoj
Senabaka entjer-aritmetika algoritmo
monato (m): | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
nombro da tagoj: | 31 | 30 | 31 | 30 | 31 | 31 | 30 | 31 | 30 | 31 | 31 | 28 |
periodo: | 153 | 153 | ||||||||||
(((m+1)*153)/5)-122 | 0 | 31 | 61 | 92 | 122 | 153 | 184 | 214 | 245 | 275 | 306 | 337 |
Iom da atento, al la vicaj obloj de 153/5 kaj al ĝiaj diferencoj, facile aperigas la formulon de la kvara tabulolinio, kiu egalas la sumon de la nombroj da tagoj de la monatoj inter la 1a de marto kaj la 1a de monato "m"; aldonu la monatan tagnumeron de la dato por obteni la nombron de tagoj inter la 1a de marto kaj tiu dato.
Inter la 1a de marto de iu baza superjaro (obla de 400 por la Gregoria kalendaro, aŭ de 4 por la Julia), kaj la 1a de marto de la "j"a posta jaro, la nombro da tagoj estas (j*365)+(j/4)-(j/100)+(j/400) por la Gregoria kalendaro (aŭ pli simple (j*365)+(j/4) por la Julia).
Do jen estas la tagnumera algoritmo, kun J=jaro M=monato T=tago, kaj NG aŭ NJ = tagnumero laŭ la Gregoria aŭ Julia kalendaro:
Por malkovri la datan semajnotagon,
dividu N en semajnaj periodoj po 7 tagoj
(rimarkinde la Gregoria kvarcentjara periodo de 146097 tagoj estas oblo de 7);
la resto de la eŭklida divido egalas:
resto: | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
Julia (B=0): | lun | mar | mer | jaŭ | ven | sab | dim |
Gregoria: | mer | jaŭ | ven | sab | dim | lun | mar |
Ekzemple: 2005-09-03, J=2005 M=9 T=3, j=5 m=9, NJ=NG=2012=7*287+3=sabato.
La tagnumeron NG unue dividu en kvarcentjaraj periodoj
po 146097 tagoj:
NG=146097*K+R
(t.e. K kaj R estas la kvociento kaj resto de la eŭklida divido NG/146097).
Se R=146096, la dato estas la lasta supertago
de la kvarcentjara periodo,
la 29a de februaro de la jaro J=B+K*400+400.
Alie due dividu R en centjaraj periodoj
po 36524 tagoj: R=36524*C+c.
La antaŭaj du unuaj paŝoj necesas nur por la Gregoria kalendaro;
por la Julia, startu ĉi tie kun
c=NJ.
Trie dividu c en kvarjaraj periodoj
po 1461 tagoj: c=1461*k+r.
Se r=1460, la dato estas supertago,
la 29a de februaro de la jaro J=B+K*400+C*100+k*4+4.
Alie kvare dividu r en jaraj periodoj
po 365 tagoj: r=365*i+t,
kaj kalkulu j=B+K*400+C*100+k*4+i, kaj m=(((t+31)*5)/153)+2,
kaj T=t-(((m+1)*153)/5)+123.
Fine, se m>12, kalkulu J=j+1 kaj M=m-12, alie J=j kaj M=m.
La dato estas J=jaro M=monato T=tago.
Ekzemple: NJ=2012, k=1 r=551, i=1 t=186, j=2005 m=9 T=3, J=2005 M=9,
2005-09-03.
Unue, 16 ĝis 19 jarcentoj de historio estis datitaj laŭ la Julia kalendaro.
Ekzemple, dum la vivo de Zamenhof, rusoj ankoraŭ uzis
la Julian kalendaron
(ĝis ĝia merkredo la 31a de januaro 1918, kiu estis la Gregoria 13a de
februaro), tiam 13 tagojn pli malfrua ol la Gregoria, uzata de okcidentanoj
jam de tri jarcentoj.
Due, procesoretoj malpli koste kalkulas per 16 bitaj nombroj,
inter 0 kaj 65535, t.e. la nombro da tagoj de proksimume 180 jaroj.
Ĉar inter 1900-03-01 kaj 2100-02-28
la Gregoriaj kaj Juliaj superjaroj egalas,
la pli simplan Julian algoritmon oni povas uzi kun ekzemple 1900
kiel baza jaro (1900-03-01 = tagnumero 0, ĝis
tagnumero 65535 = 2079-05-05).
Inversa algoritmo
Uzoj de la Julia algoritmo
Kodfontoj
static int gregoria = 1; // 1:Gregoria 0:Julia
typedef struct{int tago, monato, jaro;} dato; // 1..31, 1..12, ..2005..
int tagnumero(dato d) { // konvertu daton en tagnumeron
if(monato<3){ d.jaro-=1; d.monato+=12; } // jarkomencu 1an de marto
return d.jaro*365 + d.jaro/4 + (gregoria ? -d.jaro/100 + d.jaro/400 : 0)
+ (d.monato+1)*153/5-123 + d.tago;
}
int semajntago(int n) { // konvertu tagnumeron en:
return (gregoria ? n+2 : n) % 7; // 0=lundo .. 6=dimancho
}
void tagdato(int n, dato *d) { // konvertu tagnumeron en daton
int m, j=0;
if(gregoria) {
m = n/146097; j += m*400; n -= m*146097; // 400-jaraj periodoj
if(n==146096) { d->jaro=j+400; d->monato=2; d->tago=29; return; }
m = n/36524; j += m*100; n -= m*36524; // 100-jaraj periodoj
}
m = n/1461; j += m*4; n -= m*1461; // 4-jaraj periodoj
if(n==1460) { d->jaro=a+4; d->monato=2; d->tago=29; return; }
m = n/365; j += m; n -= m*365; // 1-jara periodoj
m = (n+31)*5/153+2; n -= (m+1)*153/5-123;
if(m>12) { j+=1; m-=12; } // jarkomencu 1an de januaro
d->jaro=j; d->monato=m; d->tago=n; return;
}
1 value gregoria \ 1:Gregoria 0:Julia
: dato> \ t m j -- n ; konvertu daton t/m/j en tagnumeron n
>r dup 3 < IF 12 + r> 1- >r THEN \ jarkomencu 1an de marto
1+ 153 * 5 / 123 - + \ -- n | j ; n tagoj de 1/3/j al t/m/j
r@ 4 / + gregoria IF r@ 100 / - r@ 400 / + THEN r> 365 * +
;
: >semajntago \ n -- s ; konvertu tagnumeron en:
gregoria IF 2 + THEN 7 mod \ 0:lundo .. 6:dimancho
;
: >dato \ n -- t m j ; konvertu tagnumeron n en daton t/m/j
0 >r gregoria IF
146097 /mod 400 * r> + >r \ 400-jaraj periodoj
146096 over = IF drop 29 2 r> 400 + exit THEN
36524 /mod 100 * r> + >r \ 100-jaraj periodoj
THEN \ -- n | j
1461 /mod 4 * r> + >r \ 4-jaraj periodoj
1460 over = IF drop 29 2 r> 4 + exit THEN
365 /mod r> + >r \ 1-jara periodoj
dup 31 + 5 * 153 / 2 + tuck 1+ 153 * 5 / 123 - - swap \ -- t m | j
dup 12 > IF 12 - r> 1+ >r THEN r> \ -- t m j
;
Ligoj
CL20080702