Wieczny kalendarz
Z Wikipedii
| Ten artykuł wymaga dopracowania zgodnie z zaleceniami edycyjnymi. Należy w nim poprawić: zła definicja, kongruencja Zellera (zob. interwiki), niepotrzebne implementacje, imć Mariusz Meller. Dokładniejsze informacje o tym, co należy poprawić, być może znajdują się na stronie dyskusji tego artykułu w sekcji Dopracować Po wyeliminowaniu wskazanych powyżej niedoskonałości prosimy usunąć szablon {{Dopracować}} z kodu tego artykułu. |
Kalendarz wieczny – tabela lub wzór pozwalająca w prosty sposób odnaleźć określony dzień tygodnia w kalendarzu gregoriańskim dla każdej daty w postaci dzień miesiąca, miesiąc, rok. Przy pomocy wiecznego kalendarza nie ma możliwości obliczenia np: roku na podstawie daty w postaci: dzień tygodnia, dzień miesiąca - gdyż dni tygodnia dla danego dnia miesiąca powtarzają się acyklicznie w kalendarzu gregoriańskim.
Spis treści |
[edytuj] Uniwersalny wzór Zellera dla lat 1 - 9999 n.e.
Kalendarz stuletni daje sprowadzić się do dość prostego algorytmu, który w pierwotnej wersji został zaproponowany przez Christiana Zellera, w kolejnych publikacjach, które ukazywały się w latach 1882-1886 (m.in. w Acta Mathematica, vol.9 (1886-1887), pp.131-6).
Algorytm Zellera został uproszczony przez matematyka, Mikea Keitha do postaci:
- dzień tygodnia = ([23m/9] + d + 4 + y + [z/4] - [z/100] + [z/400] - 2 (if m >= 3) ) mod 7
- gdzie
- [ ] oznacza dzielenie bez reszty z zaokrągleniem w dół
- mod - funkcja modulo
- m - numer miesiÄ…ca (od stycznia = 1 do grudnia = 12)
- d - numer dnia miesiÄ…ca
- z = y - 1 jeśli m < 3,
- z = y w pozostałych przypadkach
Zaletą wzoru Mike'a Keitha jest możliwość zapisania go w języku programowania C w jednej linii liczącej raptem 45 znaków:
- (d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7
która to linia kodu generuje wartość kodującą dzień tygodnia od niedzieli (0) do soboty (6)
Aby ten wzór był poprawny dla lat od 1 do 1582 trzeba uwzględnić różnicę pomiędzy stylem juliańskim a gregoriańskim która wynosi C - C div 4 - 2 (po przesunięciu początku roku do 1 marca)
Wzór ten został opublikowany w Journal of Recreational Mathematics, Vol. 22, No. 4, 1990, p. 280.
[edytuj] Implementacja w Pascalu
Zapis w języku Pascal algorytmu obliczania dnia tygodnia w kalendarzu gregoriańskim (bez ww. poprawki dla kalendarza juliańskiego):
function dzien_tygodnia(Year,Month,Day:word):string; var M,C,D,N:integer; const week:array[0..6]of string[12]=('Niedziela','Poniedziałek','Wtorek','Środa','Czwartek','Piątek','Sobota'); begin M := 1 + (Month + 9) mod 12 ; if M>10 then Dec(Year) ; C := Year div 100 ; D := Year mod 100 ; N := ((13*M-1) div 5 + D + D div 4 + C div 4 + 5*C + Day) mod 7 ; dzien_tygodnia:=week[N]; end;
-
- gdzie Month, Day = numer miesiÄ…ca i dnia miesiÄ…ca, Year = czterocyfrowy zapis roku, N = kod dnia tygodnia poczynajÄ…c od niedzieli (0) do soboty (6),
- mod = funkcja modulo, div = funkcja dzielenia liczb całkowitych bez reszty z zaokrągleniem w dół, if ... then - funkcja warunkowa
- gdzie Month, Day = numer miesiÄ…ca i dnia miesiÄ…ca, Year = czterocyfrowy zapis roku, N = kod dnia tygodnia poczynajÄ…c od niedzieli (0) do soboty (6),
Często wzór Zellera jest podawany w formie, w której występuje wartość 2*C zamiast 5*C, która to forma prowadzi jednak przy niektórych latach do wartości N - ujemnych oraz nie sprawdza się dla niektórych dat.
[edytuj] Implementacja w C
Oto funkcja napisana na podstawie algorytmu Zellera
char* week[7]={"Niedziela","Poniedzialek","Wtorek","Sroda","Czwartek","Piatek","Sobota"}; int zeller(int d,int m,int y,int s){ int Y,C,M,N,D; M=1+(9+m)%12; Y=y-(M>10); C=Y/100; D=Y%100; if (s!=0) N=((13*M-1)/5+D+D/4+C/4+5*C+d)%7; else N=((13*M-1)/5+D+D/4+6*C+d+5)%7; return (7+N)%7; }
Oto funkcja napisana na podstawie analizy tablic zamieszczonych w Małej Encyklopedii Powszechnej PWN z 1959 r.
char* week[7]={"Niedziela","Poniedzialek","Wtorek","Sroda","Czwartek","Piatek","Sobota"}; int dow(int m, int d, int y, int s) { int mon[12]={0,1,1,2,5,6,2,3,4,0,1,4}; int leap; int a,b,c; leap=(s==0&&y%4==0||s!=0&&(y%4==0&&y%100!=0||y%400==0)); a=(y%100)%28; b=(s==0)*(4+(y%700)/100+2*(a/4)+6*((!leap)*(1+(a%4))+(leap)*((9+m)/12)))%7+ (s!=0)*(2*(1+(y%400)/100+(a/4))+6*((!leap)*(1+(a%4))+(leap)*((9+m)/12)))%7; c=(3*mon[m-1]+d)%7; return (c+6*b)%7; }
Funkcja zwraca indeks do tablicy "week". Parametr s oznacza styl
- s==0 dla stylu juliańskiego
- s!=0 dla stylu gregoriańskiego
[edytuj] Implementacja w Ocamlu
Oto funkcja napisana na podstawie wzoru Mikea Keitha:
type date = {day : int; month : int; year : int;} ;; (* funkcja zwraca dzień tygodnia na podstawie podanej daty, przy czym: 0 - niedziela, 1 - poniedziałek, ..., 6 - sobota *) let weekday (time : date) = let z = if time.month < 3 then time.year - 1 else time.year in let x = ((23 * time.month) / 9) + time.day + 4 + time.year + (z / 4) - (z / 100) + (z / 400) in if time.month < 3 then x mod 7 else (x - 2) mod 7 ;;
[edytuj] Kalendarze stuletnie
Na podstawie wzoru Zellera można w prosty sposób utworzyć tabele, które bywają nazywane kalendarzami stuletnimi choć mogą one praktycznie obejmować dowolny okres. Przykładowy "kalendarz stuletni" (a właściwie stuczterdziestoletni) dla lat 1901-2040:
| Opis | Przykład dla: 31 VIII 1984 | |
| 1. W tabeli Lata znajdź liczbę na przecięciu roku i miesiąca wybranej daty | 1984/VIII → 2 | |
| 2. Do odszukanej liczby dodaj dzień miesiąca | 2+31=33 | |
| 3. W tabeli Kod dnia tygodnia znajdź odpowiadający wynikowi dzień tygodnia | 33 → piątek |
| Lata 1901-2040 | MiesiÄ…ce | ||||||||||||||||
| I | II | III | IV | V | VI | VII | VIII | IX | X | XI | XII | ||||||
| 1901 | 1929 | 1957 | 1985 | 2013 | 1 | 4 | 4 | 0 | 2 | 5 | 0 | 3 | 6 | 1 | 4 | 6 | |
| 1902 | 1930 | 1958 | 1986 | 2014 | 2 | 5 | 5 | 1 | 3 | 6 | 1 | 4 | 0 | 2 | 5 | 0 | |
| 1903 | 1931 | 1959 | 1987 | 2015 | 3 | 6 | 6 | 2 | 4 | 0 | 2 | 5 | 1 | 3 | 6 | 1 | |
| 1904 | 1932 | 1960 | 1988 | 2016 | 4 | 0 | 1 | 4 | 6 | 2 | 4 | 0 | 3 | 5 | 1 | 3 | |
| 1905 | 1933 | 1961 | 1989 | 2017 | 6 | 2 | 2 | 5 | 0 | 3 | 5 | 1 | 4 | 6 | 2 | 4 | |
| 1906 | 1934 | 1962 | 1990 | 2018 | 0 | 3 | 3 | 6 | 1 | 4 | 6 | 2 | 5 | 0 | 3 | 5 | |
| 1907 | 1935 | 1963 | 1991 | 2019 | 1 | 4 | 4 | 0 | 2 | 5 | 0 | 3 | 6 | 1 | 4 | 6 | |
| 1908 | 1936 | 1964 | 1992 | 2020 | 2 | 5 | 6 | 2 | 4 | 0 | 2 | 5 | 1 | 3 | 6 | 1 | |
| 1909 | 1937 | 1965 | 1993 | 2021 | 4 | 0 | 0 | 3 | 5 | 1 | 3 | 6 | 2 | 4 | 0 | 2 | |
| 1910 | 1938 | 1966 | 1994 | 2022 | 5 | 1 | 1 | 4 | 6 | 2 | 4 | 0 | 3 | 5 | 1 | 3 | |
| 1911 | 1939 | 1967 | 1995 | 2023 | 6 | 2 | 2 | 5 | 0 | 3 | 5 | 1 | 4 | 6 | 2 | 4 | |
| 1912 | 1940 | 1968 | 1996 | 2024 | 0 | 3 | 4 | 0 | 2 | 5 | 0 | 3 | 6 | 1 | 4 | 6 | |
| 1913 | 1941 | 1969 | 1997 | 2025 | 2 | 5 | 5 | 1 | 3 | 6 | 1 | 4 | 0 | 2 | 5 | 0 | |
| 1914 | 1942 | 1970 | 1998 | 2026 | 3 | 6 | 6 | 2 | 4 | 0 | 2 | 5 | 1 | 3 | 6 | 1 | |
| 1915 | 1943 | 1971 | 1999 | 2027 | 4 | 0 | 0 | 3 | 5 | 1 | 3 | 6 | 2 | 4 | 0 | 2 | |
| 1916 | 1944 | 1972 | 2000 | 2028 | 5 | 1 | 2 | 5 | 0 | 3 | 5 | 1 | 4 | 6 | 2 | 4 | |
| 1917 | 1945 | 1973 | 2001 | 2029 | 0 | 3 | 3 | 6 | 1 | 4 | 6 | 2 | 5 | 0 | 3 | 5 | |
| 1918 | 1946 | 1974 | 2002 | 2030 | 1 | 4 | 4 | 0 | 2 | 5 | 0 | 3 | 6 | 1 | 4 | 6 | |
| 1919 | 1947 | 1975 | 2003 | 2031 | 2 | 5 | 5 | 1 | 3 | 6 | 1 | 4 | 0 | 2 | 5 | 0 | |
| 1920 | 1948 | 1976 | 2004 | 2032 | 3 | 6 | 0 | 3 | 5 | 1 | 3 | 6 | 2 | 4 | 0 | 2 | |
| 1921 | 1949 | 1977 | 2005 | 2033 | 5 | 1 | 1 | 4 | 6 | 2 | 4 | 0 | 3 | 5 | 1 | 3 | |
| 1922 | 1950 | 1978 | 2006 | 2034 | 6 | 2 | 2 | 5 | 0 | 3 | 5 | 1 | 4 | 6 | 2 | 4 | |
| 1923 | 1951 | 1979 | 2007 | 2035 | 0 | 3 | 3 | 6 | 1 | 4 | 6 | 2 | 5 | 0 | 3 | 5 | |
| 1924 | 1952 | 1980 | 2008 | 2036 | 1 | 4 | 5 | 1 | 3 | 6 | 1 | 4 | 0 | 2 | 5 | 0 | |
| 1925 | 1953 | 1981 | 2009 | 2037 | 3 | 6 | 6 | 2 | 4 | 0 | 2 | 5 | 1 | 3 | 6 | 1 | |
| 1926 | 1954 | 1982 | 2010 | 2038 | 4 | 0 | 0 | 3 | 5 | 1 | 3 | 6 | 2 | 4 | 0 | 2 | |
| 1927 | 1955 | 1983 | 2011 | 2039 | 5 | 1 | 1 | 4 | 6 | 2 | 4 | 0 | 3 | 5 | 1 | 3 | |
| 1928 | 1956 | 1984 | 2012 | 2040 | 6 | 2 | 3 | 6 | 1 | 4 | 6 | 2 | 5 | 0 | 3 | 5 | |
| Pochyłą czcionką oznaczono lata przestępne | I | II | III | IV | V | VI | VII | VIII | IX | X | XI | XII | |||||
| Kod dnia tygodnia | ||||||
| Poniedziałek | 1 | 8 | 15 | 22 | 29 | 36 |
| Wtorek | 2 | 9 | 16 | 23 | 30 | 37 |
| Åšroda | 3 | 10 | 17 | 24 | 31 | |
| Czwartek | 4 | 11 | 18 | 25 | 32 | |
| PiÄ…tek | 5 | 12 | 19 | 26 | 33 | |
| Sobota | 6 | 13 | 20 | 27 | 34 | |
| Niedziela | 7 | 14 | 21 | 28 | 35 | |
[edytuj] Bibliografia
- Omówienie wzoru Zellera na stronie Dr J R Stockton.
- Algorytm Mike'a Kitha - omówiony na jego stronie osobistej
|
||||||||
Warning: curl_setopt() [function.curl-setopt]: CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set in /www/motocykle_www/spam/abc/richFeeds.php on line 59
| Świetlana przyszłość wideo online |
|
Amerykańscy internauci obejrzeli w listopadzie 2008 roku 12,7 mln materiałów wideo online, co oznacza 34 procentowy wzrost w porównaniu z tym samym okresem w roku ubiegłym.
|
| Koniec zabezpieczeń DRM |
|
Apple uznało, że najwyższy czas rozstać się z zabezpieczeniami DRM. Materiały audio i wideo dostępne w sklepie iTunes zostana pozbawione kłopotliwych zabezpieczeń.
|
| Microsoft bagatelizuje zagrożenie |
|
Microsoft zlekceważył zgłoszenie o luce zidentyfikowanej we wszystkich wersjach odtwarzacza Microsoft Windows Media Player.
|
| Aktualizacja programu pocztowego Mozilli |
|
Mozilla zaktualizowała swojego klienta poczty do wersji Thunderbird 2.0.0.19, łatając w ten sposób siedem luk, z których część została poprawiona również w zaktualizowanej przeglądarce Firefox 3.0.5.
|
| Policja będzie mogła włamywać się do komputerów |
|
Brytyjskie MSW zyskało nowe narzędzie. Policja i MI5 może włamywać się do komputerów osobistych bez konieczności posiadania nakazu.
|