AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Den letzten Donnerstag eines Monats
Thema durchsuchen
Ansicht
Themen-Optionen

Den letzten Donnerstag eines Monats

Ein Thema von HPB · begonnen am 8. Dez 2017 · letzter Beitrag vom 3. Jan 2018
Antwort Antwort
Seite 1 von 2  1 2      
HPB

Registriert seit: 2. Jun 2008
365 Beiträge
 
Delphi XE7 Professional
 
#1

Den letzten Donnerstag eines Monats

  Alt 8. Dez 2017, 16:16
Guten Tag Delphianer,
wie kann man immer z. B. den letzten Donnerstag eines Monats ermitteln?
Eine Routine in Delphi gibt es wohl dazu nicht?
Vielen Dank im Voraus für evtl. Hilfen.
HPB
  Mit Zitat antworten Zitat
LTE5

Registriert seit: 13. Nov 2017
355 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#2

AW: Den letzten Donnerstag eines Monats

  Alt 8. Dez 2017, 16:17
Vielleicht hilft dir das

Last Monday of Month
  Mit Zitat antworten Zitat
HPB

Registriert seit: 2. Jun 2008
365 Beiträge
 
Delphi XE7 Professional
 
#3

AW: Den letzten Donnerstag eines Monats

  Alt 8. Dez 2017, 16:26
Das sieht sehr viel Versprechend aus. Ich werde es morgen mal testen.
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#4

AW: Den letzten Donnerstag eines Monats

  Alt 8. Dez 2017, 16:27
Wenn das Projekt bereits mit einer Datenbank arbeitet, kann man die idR. auch dafür einsetzen, vor allem wenn dieser "Donnerstag" sowieso im Zusammenhang mit irgendwelchen Arbeitszeiten in einem Unternehmen steht.
Gruß, Jo
  Mit Zitat antworten Zitat
LTE5

Registriert seit: 13. Nov 2017
355 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#5

AW: Den letzten Donnerstag eines Monats

  Alt 8. Dez 2017, 16:33
Ohne Datenbank vielleicht so

Delphi-Quellcode:
procedure LastThursday(Date: TDate); overload;
begin
 LastThurday(DateUtils.YearOf(Date), DateUtils.MonthOf(Date));
end;

procedure LastThursday(Year, Month: Word); overload;
var
 i, tmp, Day, DaysMonth: Integer;
begin
 DaysMonth := DaysInAMonth(Year, Month);
 Day := DaysMonth;

 while Day > 1 do // geht sicher auch kürzer, denn man braucht ja nur maximal 7 Tage ab Monatsende rückwärts zu prüfen
  begin
   tmp := (Day + 5) mod 7;

   if tmp = 5 then
    begin
     ShowMessage('Letzter Donnerstag im Monat: ' + FormatDateTime('dd/mm/yyyy', EncodeDate(Year, Month, Day)));
     Break;
    end;

   Dec(Day);
  end;
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
 LastThurday(2017, 12);

 LastThurday(DateUtils.YearOf(Date), DateUtils.MonthOf(Date));

 LastThurday(Date);
end;
Zitat:
Eine Routine in Delphi gibt es wohl dazu nicht?
Jetzt schon.

Das geht noch 10x schöner und besser, das ist klar. Das ist dann aber Herr Raabes Job - der Code-Optimierer in Person.

Geändert von LTE5 ( 8. Dez 2017 um 16:43 Uhr)
  Mit Zitat antworten Zitat
ConstantGardener

Registriert seit: 24. Jan 2006
Ort: Halberstadt
375 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Den letzten Donnerstag eines Monats

  Alt 8. Dez 2017, 19:14
Delphi-Quellcode:
function TForm2.LetzterDonnerstag(AYear, AMonth: Word): TDate;
var ADate : TDate;
    ADay : Word;
begin
 ADate:=IncMonth(EncodeDate(AYear,AMonth,1))-1; // letzer Tag des Monats
 ADay :=DayOfTheWeek(ADate); // ist was für ein Tag ?
 if ADay<4 then
  result:=ADate+(4-ADay)-7 // Montag-Mittwoch ?
 else
  result:=ADate+(4-ADay)
end;

evtl. so?
Andreas Schachtner
  Mit Zitat antworten Zitat
Solutor

Registriert seit: 24. Dez 2017
15 Beiträge
 
Delphi XE2 Enterprise
 
#7

AW: Den letzten Donnerstag eines Monats

  Alt 25. Dez 2017, 17:39
Dieser Funktion übergibt man das Jahr, den Monat und den Wochentag von dem man wissen möchte wann der letzte davon im Monat ist.
Als Ergebnis bekommt man das Datum (TDatetime) dieses letzen Tages.
Die Wochendatge sind nach der alten Weise vergeben. 1-7 wovon 1 der Sonntag ist.

Für das geforderte Problem würde man die 5 für Donnerstag als letzten Parameter übergeben.

Da hier keine Schleifen, sondern nur eine verkettete If Abfrage sowie eine Addition, bzw. Subtraktion verwendet wird,
dürfte diese Funktion auch recht schnell sein.

Delphi-Quellcode:
Function GetLastWeekDayOfMonth(yyyy,mm,d:Integer):TDatetime;
Var Adate:TDatetime;
    y,m,z:Integer;
begin
   z:=DayOfWeek(DateUtils.EndOfAMonth(yyyy,mm));
   if z=d then
   begin
      Result:=DateUtils.EndOfAMonth(yyyy,mm);
   end
   else
   if z>d then
   begin
      z:=z-d;
      Result:=DateUtils.EndOfAMonth(yyyy,mm)-z;
   end
   else
   begin
      z:=z-d;
      Result:=DateUtils.EndOfAMonth(yyyy,mm)-z-7;
   end;
end;
  Mit Zitat antworten Zitat
LTE5

Registriert seit: 13. Nov 2017
355 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#8

AW: Den letzten Donnerstag eines Monats

  Alt 25. Dez 2017, 18:09
Deine Funktion ist etwa 60% schneller als die im Beitrag dadrüber.
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.041 Beiträge
 
Delphi XE2 Professional
 
#9

AW: Den letzten Donnerstag eines Monats

  Alt 26. Dez 2017, 01:30
Deine Funktion ist etwa 60% schneller als die im Beitrag dadrüber.

Naja, wenn es um Schnelligkeit geht dann so:

Delphi-Quellcode:
// WeekDay 0=Mo, 6=So
FUNCTION LastWeekDayOfMonth(Year,Month,WeekDay:Integer):TDateTime;
const DIM:Array[1..12] of byte=(31,28,31,30,31,30,31,31,30,31,30,31);
var Day,DN,DoW,Y:Integer;
begin
   Y:=Year;
   Day:=DIM[Month]+Ord((Month=2) and ((Year mod 4=0) and (Year mod 100<>0) or (Year mod 400=0)));
   DN:=Year*365+Day+31*(Month-1);
   If Month>2 then Dec(DN,(23+4*Month) div 10)
      else if Year<>0 then Dec(Year)
         else Dec(DN);
   Inc(DN,Year div 4 - Year div 100 + Year div 400);
   DoW:=(5+DN) mod 7;
   if WeekDay>DOW then Dec(Day,7-WeekDay+DoW) else Dec(Day,Dow-WeekDay);
   Result:=EncodeDate(Y,Month,Day);
end;
Kurz zur Funktion, falls es jemanden interessiert:
In der Funktion wird u.A. DN berechnet. DN ist die Anzahl der Tage, die seit dem fiktiven Datum 01.01.0000 vergangen sind, wobei angenommen wird, dass der Gregorianische Kalender schon immer gegolten hätte.
Der 01.01.0000 hätte also die Nummer 0.

Auf meinem Rechner (i7 2600K 3.4 GHz) arbeitet diese Funktion deutlich schneller.
Bei unten stehendem Test brauchte diese Funktion 187 ms, die aus #7 2262 ms.
Das mag auf anderen Rechnern anders sein.

Hinzu kommt, dass die Funktion aus #7 in bestimmten Fällen falsche Resultate liefert.
Für Dezember 1899 und Montag liefert #7 den 26.12.1899, richtig wäre der 25.12.1899 (Geburtstag von Humphrey Bogart).
Auch für Dienstag bis Freitag im Dezember 1899 tritt diese Verschiebung um einen Tag auf.
Ansonsten arbeitet sie im Zeitraum 1583 bis 2500 korrekt.
Was mir ebenfalls nicht an #7 gefällt, ist, dass sie nicht ein Datum sondern einen Zeitpunkt liefert (nämlich 23:59:59 am jeweiligen Tag) was vermutlich auch die Quelle des Fehlers ist.

Hier die Prozedur mit der ich getestet habe.

Delphi-Quellcode:
PROCEDURE TMain.Test;
var Err,I,Year,Month,DoW1,DoW2:Integer; DT1,DT2:TDateTime; DS1,DS2:String;
    T0,T1,T2:Cardinal;
begin
   // Prüfung ob beide Funktionen identische Ergebnisse bringen
   Err:=0;
   for Year:=1583 to 2500 do
      for Month:=1 to 12 do
         for DoW1:=0 to 6 do begin
            DT1:=LastWeekDayOfMonth(Year,Month,DoW1);
            DS1:=FormatDateTime('dd.mm.yyyy',DT1);
            if DoW1<6 then DoW2:=DoW1+2 else DoW2:=1;
            DT2:=GetLastWeekDayOfMonth(Year,Month,DoW2);
            DS2:=FormatDateTime('dd.mm.yyyy',DT2);
            if DS1<>DS2 then begin
               Inc(Err);
               ShowMessage(IntToStr(Year)+' '+IntToStr(Month)+#13+
                           IntToStr(DoW1)+' '+DS1+#13+
                           IntToStr(DoW2)+' '+DS2);
            end;
         end;
   ShowMessage(IntToStr(Err));
   // Performance Vergleich
   T0:=GetTickCount;
   for I:=1 to 50 do
      for Year:=1583 to 2500 do
         for Month:=1 to 12 do
            for DoW1:=0 to 6 do
               DT1:=LastWeekDayOfMonth(Year,Month,DoW1);
   T1:=GetTickCount;
   for I:=1 to 50 do
      for Year:=1583 to 2500 do
         for Month:=1 to 12 do
            for DoW2:=1 to 7 do
               DT2:=GetLastWeekDayOfMonth(Year,Month,DoW2);
   T2:=GetTickCount;
   ShowMessage(IntToStr(T1-T0)+#13+IntToStr(T2-T1));
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von blawen
blawen

Registriert seit: 30. Nov 2003
Ort: Luterbach (CH)
654 Beiträge
 
Delphi 12 Athens
 
#10

AW: Den letzten Donnerstag eines Monats

  Alt 26. Dez 2017, 11:29
Naja, wenn es um Schnelligkeit geht dann so:

Delphi-Quellcode:
// WeekDay 0=Mo, 6=So
FUNCTION LastWeekDayOfMonth(Year,Month,WeekDay:Integer):TDateTime;
const DIM:Array[1..12] of byte=(31,28,31,30,31,30,31,31,30,31,30,31);
Wie sieht es mit Schaltjahren aus? Diese werden nicht berücksichtigt - oder übersehe ich etwas?
Roland
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz