Programowanie w języku Delphi » Gotowce

Jak z podanej daty odliczyć dzień tygodnia

Jak z podanej daty odliczyć dzień tygodnia


Jest to mój pierwszy gotowiec, a ja jestem początkujący więc proszę byście mnie nie zasztyletowali
Wiec tak przedstawię kodzik który może przydać się początkującym.
Jak w tytule zaznaczyłem napisze procedurę obliczającą z podanej daty dzień.
Ale zanim zacznę przydało by się słowo objaśnienia:

Jak to obliczyć


No wiec załóżmy że obliczymy dzień tygodnia daty 21.12.2012 (Ma być niby Koniec świata :-P)
1.Wiec tak musimy najpierw obliczyć liczbę lat przestępnych od początku naszej ery do roku 2012.
   Robimy to w następujący sposób nasz podany rok dzielimy przez 4:
   2012 : 4 = 503
2.W kalendarzu gregoriańskim musimy odjąć 13 dni:
   503 - 13 = 490
3.Następnie musimy obliczyć ile upłynie dni od 1 Stycznia do 21 Grudnia:
   Styczeń(31) + Luty(28) + Marzec(31) + Kwiecień(30) + Maj(31) + Czerwiec(30) + Lipiec(31) +
   Sierpień   (31) + Wrzesień(30) + Październik(31) + Listopad(30) + Grudzień(20) = 354

   Uwaga!
   W drugim miesiącu (Luty) musi być 28 dni bo obliczyliśmy już rok przestępne

4.Teraz musimy sumować nasze wyniki:
   2012 + 490 + 354 = 2856
5.I na koniec musimy podzielić nasz wynik przez 7 by uzyskać resztę tego wyniku:
   2856 : 7 = 408.0

   Uwaga!
   Akurat w tym wyniku nie ma reszty lecz dobrze się składa bo wytłumaczę ważną rzecz:
   Gdy niema reszty (0) to uznajemy, że jest to 7 więc 21.12.2012 wypadnie w Piątek
        1          2              3              4        5          6         7
   Sobota Niedziela Poniedziałek Wtorek Środa Czwartek Piątek

A teras kodzik! :-)


Na formę wrzucamy 4 komponenty 3 edit i 1 button.
Klikany 2 razy na formę i wpisujemy taki kodzik:
procedure TForm1.FormCreate(Sender: TObject);
var
 data: string;
 dmr: TStringList;
begin
 data:=datetostr(date); //Pobieramy date
 dmr:=TStringList.Create;
 dmr.Delimiter:='-';
 dmr.DelimitedText := data; //Dzielimy ją na dzień miesiąc i rok
 edit1.Text:=dmr.Strings[2]; //Dzień
 edit2.Text:=dmr.Strings[1]; //Miesiąc
 edit3.Text:=dmr.Strings[0]; //Rok
 dmr.Free;
end;

Teraz klikamy 2 razy na Button i wpisujemy taki kodzik:
procedure TForm1.Button1Click(Sender: TObject);
const
 dni_miesiecy : array[1..12] of integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
 dni_tygodnia : array[1..7] of string = (('Sobota'), ('Niedziela'), ('Poniedziałek'), ('Wtorek'), ('Środa'), ('Czwartek'), ('Piątek'));
var
 rok, dni, i, suma: integer;
begin
 dni:= 0;
 rok:= strtoint(edit3.Text) div 4 - 13; //Obliczamy liczbę lat przestępnych i odejmujemy 13 (Punkt 1 i 2)
 if (strtoint(edit2.Text)> 1) then         //Jeżeli jest styczeń to nie wykonuje pętli (Punkt 3)
  begin
   for i:= 1 to strtoint(edit2.Text) - 1 do
    begin
     dni:= dni + dni_miesiecy[i];        //Dodaje miesiące bez miesiąca który obliczamy
    end;
   dni:= dni + strtoint(edit1.Text) - 1;//Odejmuje jeden dzień i dodaje do reszty
  end
  else
  begin
   dni:= strtoint(edit1.Text) - 1;        //Jeżeli jest styczeń to odejmuje jeden dzień i zapisuje do zmiennej 
  end;                                            //Koniec punktu 3
 suma:= strtoint(edit3.Text) + rok + dni; //Sumuje wyniki (punkt 4)
 suma:= suma mod 7;                           //Pobiera resztę z dzielenia
 if(suma = 0) then suma := 7;                //Jeżeli niema reszty ustawia 7
 form1.Caption:= dni_tygodnia[suma];   //No i wyświetlamy Dzień tygodnia
end;


To by było na tyle :-) Jak wspominałem jest to mój pierwszy gotowiec!

9 komentarzy

Brak avatara
Tadeko 2014-05-08 11:41

Opis działania zawiera poważny błąd. W latach przestępnych dla stycznia i lutego od wyliczonej sumy trzeba koniecznie odjąć 1.

Brak avatara
0x51 2014-04-05 11:57

@Oleksy_Adam, przecież pisał wyraźnie, że jest początkujący.

Oleksy_Adam 2009-01-02 15:30

Czy ktoś Cię zasztyletował? Ja tu widzę konstruktywną krytykę. Nie najechaliśmy na Ciebie tylko na Twój algorytm. Wyciągnij wnioski i popraw artykuł. IHMO zasztyletowałem Twój kod.

scott91 2008-12-31 14:57

Prosiłem byście mnie nie zasztyletowali, jestem początkujący a kodzik z głowy brałem wstyd sie przyznać ale niewiedziałem, że mój kod można tak skrócić. Ale dziękuje za szczere komentarze bo chciałem usłyszeć od innych co myślą o moim kodzie. Pozdrawiam

Oleksy_Adam 2008-12-30 22:30

Racja, zapomniałem, że US ma totalnie wszystko nieco inaczej od reszty świata. Masakra z nimi.

MartinEagle 2008-12-30 20:19

Trzeba przyznać, że Scott91 zaistniał na 4p.

Dla mnie każdy sposób dobry, byle skuteczny.
Przykład innego sposobu na DoW: http://www.algorytm.org/index.[...]=view&id=227&Itemid=28

@Oleksy_Adam pkt. 6:     Jest pewna nieścisłość w array'u. Kod z help'a Delphi'ego podaje:

procedure TForm1.Button1Click(Sender: TObject);
 
var
  ADate: TDateTime;
  days: array[1..7] of string;
begin
  days[1] := 'Sunday';
  days[2] := 'Monday';
  days[3] := 'Tuesday';
  days[4] := 'Wednesday';
  days[5] := 'Thursday';
  days[6] := 'Friday';
  days[7] := 'Saturday';
  ADate := StrToDate(Edit1.Text);
  ShowMessage(Edit1.Text + ' is a ' + days[DayOfWeek(ADate)];
end;

Sądzę, że nie trzeba nic więcej dodawać.

Pozdrawiam
ME

bordeux 2008-12-30 13:59

Oleksy_Adam: Hehehe.. brutalna prawda :P

Patyk 2008-12-29 18:38

@Oleksy_Adam: Porządne zestawienie, może warto byłoby wydzielić to do osobnego artykułu? :>

Oleksy_Adam 2008-12-29 08:55

1). Datę przechowuje się jako TDateTime.
2). Jest gotowa funkcja DayOfWeek().
3). Do rozpakowania daty na składowe służy EncodeDate().
4). Zawiłość kodu i ilość StrToInt() jest porażająca.
5). Jak już musisz pokazać algorytm obliczania to wklej ten:

Pascal\Delphi:

FUNCTION dtyg(d, m, r: integer): integer;
VAR
  w: integer;
BEGIN
  IF m>2 THEN m := m-2 ELSE
  BEGIN
    m := m+10;
    r := r-1;
  END;
  w := r DIV 100;
  r := r MOD 100;
  dtyg := (d + (13*m-1) DIV 5 + r  + r DIV 4 + w DIV 4 + 5*w) MOD 7;
END;


C\C++\C#
int dtyg(int d, int m, int r)
{
   int w;
   if (m > 2)
      m -= 2;
   else
   {
      m += 10;
      r--;
   }
   w = r/100;
   r %= 100;
   return (d + (13*m-1)/5 + r + r/4 + w/4 + 5*w) % 7;
}


VB\VBA
Public Function dtyg(d As Integer, m As Integer, r As Integer)
Dim w As Integer
 
If m > 2 Then
  m = m - 2
Else
  m = m + 10
  r = r - 1
End If
w = r \ 100
r = r Mod 100
 
dtyg = (d + (13 * m - 1) \ 5 + r + r \ 4 + w \ 4 + 5 * w) Mod 7
End Function


6). Skrócona wersja Twojego kodu
const
  Dow :array[1..7] of string[20] = ('N', 'PN', 'WT', 'SR', 'CZ', 'PT', 'S');
 
Result := Dow[DayOfWeek(Now())];

7). Na forum powinien być zakaz uczenia brzydkich kodów.