algorytm.org

Wyznaczanie dnia tygodnia



Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Wyznaczanie dnia tygodnia
Ocena użytkowników:***** / 53
SłabyŚwietny 
Wpisany przez Tomasz Lubiński, 02 marca 2008 20:12

Przedstawiony tutaj algorytm pozwala na szybkie obliczenie dnia tygodnia dla podanej daty dzień-miesiąc-rok. Wszystkie przedstawione operacje dzielenia są operacjami dzielenia całkowitego - tzn. odrzucającymi resztę. Czyli 5/2 = 2.
Na początku obliczymy dzień tygodnia dla pierwszego stycznia podanego roku. 0 oznacza poniedziałek, 1 wtorek, ... 6 niedzielę.
  • YY = (rok-1) mod 100
  • C = (rok-1) - YY
  • G = YY + YY/4
  • dzień tygodnia dla 1 stycznia = (((((C / 100) mod 4) * 5) + G) mod 7)


Teraz zdefiniujemy pomocniczą tabelę określającą ile dni roku minęło dla podanego miesiąca. Tabela zdefiniowana jest dla roku nieprzestępnego:

Miesiącliczba dni
styczeń0
luty31
marzec59
kwiecień90
maj120
czerwiec151
lipiec181
sierpień212
wrzesień243
październik273
listopad304
grudzień334


Następnie wyznaczymy dzień roku:
  • dzień roku = liczba dni, które minęły dla podanego miesiąca odczytane z tabeli powyżej + dzień miesiąca
  • Teraz jeszcze należy sprawdzić czy należy dodać jeden dzień w związku z latami przestępnymi. A więc dzień roku należy zwiększyć o 1 jeżeli podany miesiąc jest po lutym oraz podany rok jest przestępny


Mamy już teraz wszystkie niezbędne dane do wyznaczenia dnia tygodnia. Do obliczonego dnia tygodnia dla 1 stycznia dodajemy wyznaczony dzień roku pomniejszony o 1 i dzielimy całość modulo 7. Wynik to dzień tygodnia dla podanej daty, 0 oznacza poniedziałek, 1 wtorek, ... 6 niedzielę.

dzień tygodnia = (dzień tygodnia dla 1 stycznia + dzień roku - 1) mod 7


Przykład:

Wyznaczymy dzień tygodnia dla: 15-2-2008.
A więc najpierw obliczymy dzień tygodnia dla 1 stycznia.
YY = (rok-1) mod 100 = (2008-1) mod 100 = 2007 mod 100 = 7.
C = (rok-1) - YY = (2008-1) - 7 = 2007 - 7 = 2000.
G = YY + YY/4 = 7 + 7/4 = 7 + 1 = 8.
dzień tygodnia dla 1 stycznia = (((((C / 100) mod 4) * 5) + G) mod 7) = (((((2000 / 100) mod 4) * 5) + 8) mod 7) = ((((20 mod 4) * 5) + 8) mod 7) = (((0 * 5) + 8) mod 7) = ((0 + 8) mod 7) = 8 mod 7 = 1.
Zatem 1 stycznia 2008 roku to wtorek.
Teraz obliczymy, którym dniem roku 2008 jest dzień 15-2.
dzień roku = 31 + 15 = 46.
Podany rok jest rokiem przestępnym, ale podany miesiąc nie jest późniejszy niż luty a więc nie dodajmy 1 do dnia roku.
A więc ostatecznie:
dzień tygodnia = (dzień tygodnia dla 1 stycznia + dzień roku - 1) mod 7 = (1 + 46 - 1) mod 7 = 46 mod 7 = 4.
A więc 15-2-2008 to piątek.

Implementacje
AutorJęzyk
programowania
KomentarzOtwórzPobierzOcena
Tomasz LubińskiC#MS Visual Studio .net
.cs
.cs
***** / 2
Tomasz LubińskiC/C++
.cpp
.cpp
***** / 12
Michał BurchardtC/C++C++
.cpp
.cpp
***** / 18
Tomasz LubińskiDelphi/Pascal
.pas
.pas
***** / 4
Tomasz LubińskiJava
.java
.java
***** / 4
Nikodem SolarzRubyMetoda obliczająca
.rb
.rb
***** / 0
Nikodem SolarzRubyGotowy program obliczający
.rb
.rb
***** / 0
 
Dodaj własną implementację tego algorytmu
  • Zaloguj się na stronie
Plik:
Język
programowania:
Komentarz:
  By móc dodać implementacje zaloguj się na stronie

Poprawiony: 30 lipca 2012 18:15
Komentarze
photo
+1 # ciekawy 2011-09-10 15:52
chciałem zapytać czy ten algorytm jest jakoś nazwany, czy to algorytm wymyślony przez autora artykułu?
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
+4 # Tomasz Lubiński 2015-08-25 08:22
Nie wydaje mi się, żeby miał on jakąś nazwę. Bazuje on po prostu na wyliczeniu:
Dzień 1 stycznia roku 1 + liczba lat od roku 1 * liczba dni w roku + liczba lat przestępnych od roku 1 do roku poprzedzający zadany rok + liczba dni w roku bieżącym i to wszystko modulo 7. Tak więc jakaś wyższa matematyka to to nie jest
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
-2 # Jurgen 2014-11-12 21:08
Niestety ten algorytm nie działa zbyt dobrze - np. 12.11.2014
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
+4 # Tomasz Lubiński 2015-08-25 08:32
Wszystko jest OK:

A więc najpierw obliczymy dzień tygodnia dla 1 stycznia 2014 roku.
YY = (rok-1) mod 100 = (2014-1) mod 100 = 2013 mod 100 = 13.
C = (rok-1) - YY = (2014-1) - 13 = 2013 - 13 = 2000.
G = YY + YY/4 = 13 + 13/4 = 13 + 3 = 16.
dzień tygodnia dla 1 stycznia = (((((C / 100) mod 4) * 5) + G) mod 7) = (((((2000 / 100) mod 4) * 5) + 16) mod 7) = ((((20 mod 4) * 5) + 16) mod 7) = (((0 * 5) + 16) mod 7) = ((0 + 16) mod 7) = 16 mod 7 = 2.
Zatem 1 stycznia 2014 roku to środa.
Teraz obliczymy, którym dniem roku 2014 jest dzień 12 listopada.
dzień roku = 304 + 12 = 316.
Podany miesiąc jest późniejszy niż luty ale podany rok nie jest rokiem przestępnym więc nie dodajmy 1 do dnia roku.
A więc ostatecznie:
dzień tygodnia = (dzień tygodnia dla 1 stycznia + dzień roku - 1) mod 7 = (2 + 316 - 1) mod 7 = 317 mod 7 = 2.
A więc 12-11-2014 to środa - wszystko się zgadza.
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
+1 # Bartas100 2015-05-22 13:08
Co oznacza YY C i G w tym algorytmie?
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
+1 # Tomasz Lubiński 2015-08-25 08:33
Nie, to po prostu nazwy zmiennych żeby uprościć wzór na obliczanie dnia dla pierwszego dnia roku.
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
+1 # Cypis 2018-09-19 17:12
yy=rok
c=miesiąc
g=dzień
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
+2 # Marcinnn 2016-06-20 09:09
ktos moglby zrobic dla vba ?
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
+1 # pcu 2017-07-12 09:40
[*][*]Algorytm Zellera został uproszczony przez matematyka, Mike'a Keitha do postaci:
dzień tygodnia = ([23m/9] + d + 4 + y + [z/4] + [z/100] + [z/400] - c) mod 7gdzie [ ] oznacza część całkowitą liczby
mod – funkcja modulo (reszta z dzielenia)
m – numer miesiąca (ang. month) (od stycznia = 1 do grudnia = 12)
d – numer dnia (ang. day) miesiąca
y – rok (ang. year)
z – rok z poprawką: z = y - 1 jeżeli m < 3; z = y, jeżeli m >= 3
c – korekta (ang. correction): c = 0, jeżeli m < 3; c = 2, jeżeli m >= 3
dni tygodnia ze zbioru {0, 1, 2, 3, 4, 5, 6}, gdzie: 0 – wtorek, 1 – środa, 2 – czwartek, 3 – piątek, 4 – sobota, 5 – niedziela, 6 – poniedziałek

Zaletą wzoru Mike'a Keitha jest możliwość zapisania go w języku programowania C w jednej linii liczącej raptem 45 znaków.
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
0 # Jan moczarski 2017-08-31 22:49
A co oznacza mod
Odpowiedz | Odpowiedz z cytatem | Cytować
photo
0 # Tomasz Lubiński 2019-11-13 08:31
Dzielenie modulo, czyli inaczej mówiąc reszta z dzielenia.
Odpowiedz | Odpowiedz z cytatem | Cytować
Dodaj komentarz