HEJMO EO | FR | EN

TAGNUMERILO

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:

Kial numeri tagojn?

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.

Kalendaraj faktoj

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).

Senabaka entjer-aritmetika algoritmo

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:
monato (m): 3 4 5 6 7 8 9101112 1314
nombro da tagoj: 313031303131303130313128
periodo: 153 153
(((m+1)*153)/5)-122 0316192122153184214245275306337

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: 0123456
Julia (B=0): lunmarmerjaŭvensabdim
Gregoria: merjaŭvensabdimlunmar

Ekzemple: 2005-09-03, J=2005 M=9 T=3, j=5 m=9, NJ=NG=2012=7*287+3=sabato.

Inversa algoritmo

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.

Uzoj de la Julia algoritmo

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).

Kodfontoj

En JavaScript:
vidu en la HTML-a fontkodo de ĉi tiu paĝo.
En C lingvaĵo:
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;
}
En Forth :
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