![]() |
Kompliziertes Problem mit Wochentagberechnung
Ich sitze gerade vor einem Problem und ich weiß nicht so recht weiter.
In meinem Programm kann ich einen Task für ausgewählte Wochentage deaktivieren. Wird der Task am Dienstag gestartet und Dienstag ist in der Liste der ausgewählten Wochentage, dann gehts nicht weiter - alles gewollt bisher. An einer anderen Stelle im Code gibt es eine kleine Berechnung. Sagen wir mal es ist der 31.08.2017 gegeben. Der 31.08 ist ein Donnerstag und befindet sich in der Liste. Das Problem: wie erhalte ich den nächst-möglichen freien Tag, der nicht in der Liste steht? Mein aktueller Code sieht so aus. Moben gegebenem Szenario (Datum 31.08.2017) funktioniert er nicht, da die while-Schleife natürlich direkt abbricht:
Delphi-Quellcode:
Ich hoffe mich versteht jemand?
// aExcludeDays =
// 0, -1, -1, -1, -1, -1, -1 // 0 = False, -1 = True (True = verbotener Wochentag) // StartTimestamp = // 31.08.2017 als Unix-Timestamp // DayOfWeek = // Der aktuelle Wochentag // Wandelt das Format in ISO 8601 (Montag erster Tag) um function GetDayOfWeek(const DateTime: TDateTime): ShortInt; begin Result := -1; case DayOfWeek(DateTime) of 1: // Sunday Result := 6; 2: // Monday Result := 0; 3: // Tuesday Result := 1; 4: // Wednesday Result := 2; 5: // Thursday Result := 3; 6: // Friday Result := 4; 7: // Saturday Result := 5; end; end; function GetNextAvailableWeekDay(const aExcludeDays: TArray<string>; StartTimestamp, DayOfWeek: Integer): Integer; var iTmp: Integer; begin if DayOfWeek >= 0 then begin iTmp := 0; while (Length(aExcludeDays) > DayOfWeek) and (StrToBool(aExcludeDays[DayOfWeek])) do begin if iTmp = 7 then begin StartTimestamp := 0; Break; end; Inc(StartTimestamp, 86400); DayOfWeek := TDateUtils.GetDayOfWeek(IncSecond(Now, StartTimestamp)); Inc(iTmp); end; end; Result := StartTimestamp; end; Edit Ich glaube ich habs. Bin mir aber nicht sicher. GetDayOfWeek() geht sicher auch schöner
Delphi-Quellcode:
Ok ich habs doch nicht.
while (Length(aExcludeDays) > aDayOfWeek) do // and (StrToBool(aExcludeDays[DayOfWeek])) do
begin if iTmp = 8 then // 8 statt 7 // Wenn die Woche 1x komplett durch ist, Endlosschleife vermeiden! begin StartTimestamp := 0; Break; end; Inc(StartTimestamp, 86400); aDayOfWeek := TDateUtils.GetDayOfWeek(StartTimestamp); // hier "StartTimestamp" statt "IncSecond(Now, StartTimestamp)" Inc(iTmp); if not StrToBool(aExcludeDays[aDayOfWeek - 1]) then // Schlussprüfung Break; end |
AW: Kompliziertes Problem mit Wochentagberechnung
GetDayOfWeek ....
![]() ![]() Und wenn die While-Schleife zu früh abbricht, dann stimmt deine Bedingung wohl nicht. Oder wenn die Schleife immer mindestens einmal durchlaufen soll, dann es womöglich mal mit einer Repeat-Schleife versuchen. |
AW: Kompliziertes Problem mit Wochentagberechnung
Also diese Antwort hat mir jetzt leider nicht geholfen :roll:
Zitat:
Zitat:
Zitat:
Ich habs jetzt gelöst. Schön ist aber anders
Delphi-Quellcode:
// aExcludeDays =
// 0, -1, -1, -1, -1, -1, -1 // 0 = False, -1 = True (True = verbotener Wochentag) // StartTimestamp = // 31.08.2017 als Unix-Timestamp // Beim Aufruf von dieser Funktion mit übergebenem Start-Datum 31.08.2017 (Donnerstag) und obigem Array, // muss das Resultat der 04.09.2017 (Montag) sein, da er kein "verbotener" Tag ist. procedure GetNextAvailableWeekDay(const aExcludeDays: TArray<string>; StartTimestamp: Integer): Integer; var iTmp, aDayOfWeek: Integer; bDayExcluded: Boolean; begin iTmp := 0; // Prüfe, ob das Startdatum (hier 31.08.2017) ein "verbotener" Tag ist. aDayOfWeek := TDateUtils.GetDayOfWeek(UnixToDateTime(StartTimestamp)); bDayExcluded := StrToBool(aExcludeDays[aDayOfWeek]); // Wenn der Tag "verboten" wurde (mit -1 oben im Array), dann springe hier rein if bDayExcluded then begin while True do begin Inc(StartTimestamp, 86400); // Füge dem Startdatum einen Tag hinzu aDayOfWeek := TDateUtils.GetDayOfWeek(UnixToDateTime(StartTimestamp)); // Hole den Wochentag (Woche beginnt mit Montag) // Prüfe erneut, ob das Datum ein "verbotener" Tag ist bDayExcluded := StrToBool(aExcludeDays[aDayOfWeek]); // Ist das Datum ein erlaubter/freier Tag, dann können wir hier abbrechen und es als Ergebnis verwenden if not bDayExcluded then Break; Inc(iTmp); if iTmp = 8 then begin StartTimestamp := 0; Break; end; end; end; Result := StartTimestamp; end; |
AW: Kompliziertes Problem mit Wochentagberechnung
Zitat:
Delphi-Quellcode:
Ist nur so ein Gefühl, aber die negative Logik bei aExcludeDays würde ich in aAllowedDays umkehren. Aber das hängt vielleicht auch vom Kontext ab.
type
TDayOfWeekSet = set of 0..6; // Wandelt das Format in ISO 8601 (Montag erster Tag) um function GetDayOfWeek(const DateTime: TDateTime): ShortInt; begin Result := (DayOfWeek(DateTime) + 5) mod 7; end; function GetNextAvailableWeekDay(const aExcludeDays: TDayOfWeekSet; StartTimestamp: Integer): Integer; var dt: TDateTime; I: Integer; begin dt := UnixToDateTime(StartTimestamp); for I := 0 to 6 do begin if not (GetDayOfWeek(dt) in aExcludeDays) then Exit(DateTimeToUnix(dt)); dt := IncDay(dt); end; Result := 0; end; procedure TestCase; var dt: TDateTime; begin dt := UnixToDateTime(GetNextAvailableWeekDay([1..6], DateTimeToUnix(EncodeDate(2017, 08, 31)))); Assert(SameDate(dt, EncodeDate(2017, 09, 04))); end; |
AW: Kompliziertes Problem mit Wochentagberechnung
Du willst den "nächsten" Tag, also exclusive dem Aktuellen/Übergebenen.
Da muß die Schleife mindestens einmal durchlaufen werden, also prüft man am Ende (repeat-until) soll inkl. des Aktuellen/Übergebenen auswertet werden, dann vor der Schleife prüfen (while-do). Und scheinbar hast du die Hilfe nicht gesehn? GetDayOfWeek = DayOfTheWeak Zitat:
siehe TDayOfWeekSet ... aber eventuell auch als 1..7, je nach Datenformat PS: Für die "unverständlichen" Zahlen gibt es auch Wochentagskonstanten, die man verwenden darf. Und wieso muß DayOfWeek an die Funktion übergeben werden, wenn du auch den Startwert aus StartTimestamp rausholen kannst? PS: Eine Fehlerprüfung (z.B. Assert) am Anfang wäre nicht schlecht, falls jemand auf die Idee kommt und alle Tage verbietet. -> Endlosschleife |
AW: Kompliziertes Problem mit Wochentagberechnung
>while True do
So was ist immer ein repeat/until. |
AW: Kompliziertes Problem mit Wochentagberechnung
Zitat:
Diesen lese ich mit Ini ReadString, das Resultat packe ich in ein Array und übergebe es der Funktion. In ein Set würde ich meine Auswahl folgendermaßen speichern
Delphi-Quellcode:
Nur wie soll man so etwas in eine Datei abspeichern?
for i := 0 to 6 do
begin aCheckBox := (FindComponent('cbDay' + IntToStr(i)) as TCheckBox); if Assigned(aCheckBox) and aCheckBox.Checked then aDayOfWeekSet := aDayOfWeekSet + [aCheckBox.Tag]; end; |
AW: Kompliziertes Problem mit Wochentagberechnung
Zitat:
|
AW: Kompliziertes Problem mit Wochentagberechnung
Ok speichern so
Delphi-Quellcode:
Das funktioniert soweit.
IniS.WriteInteger(section, ident, Byte(aDayOfWeekSet));
Mit dem Laden tue ich mich aber noch schwer
Delphi-Quellcode:
var
exclude: TDayOfWeekSet; begin exclude := TDayOfWeekSet(Byte(IniS.ReadInteger(section, ident, 0))); // in der Ini steht 8/Mittwoch // cdDay2 = Mittwoch cbDay2.Checked := 8 in exclude; end; |
AW: Kompliziertes Problem mit Wochentagberechnung
Zitat:
Delphi-Quellcode:
Byte(exclude) := IniS.ReadInteger(section, ident, 0);
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz