![]() |
Kalenderwochen Funktion Falsch?
Hallo zusammen,
ich benutze hier aus der Code-Lib folgende Funktion: Hier zeigt Alex_ITA01 wie es möglich ist, anhand eines Datums die zugehörige Kalenderwoche zu ermitteln. Für Delphi 6 und höher, geht dies genau so gut mit WeekOfTheYear (Unit: DateUtils), doch für die Benutzer älterer Delphi-Versionen ist dies mit folgendem Code möglich:
Delphi-Quellcode:
Wenn ich aber diese verwende, wird mir die Kalenderwoche für den 10.01.2008 falsch berechnet?!
function GetKW(Date: TDateTime): Integer;
var Day: Integer; Y, M, D: Word; begin Day := DayOfWeek(Date) - 1; if (Day <= 0) then Day := 7; DecodeDate(Date + 4 - Day, Y, M, D); result := round(((Date + 8 - Day) - EncodeDate(Y, 1, 1)) / 7); end; @Edit: Bekomme als Ergebnis '1', sollte aber 2 ausspucken... Hat jemand eine Idee warum das so ist? Ich habe die WeekOfTheYear Funktion nicht zur Verfügung! Danke |
DP-Maintenance
Dieses Thema wurde von "Matze" von "Programmieren allgemein" nach "Sonstige Fragen zu Delphi" verschoben.
Delphi-Frage |
Re: Kalenderwochen Funktion Falsch?
... ausser man beachtet, dass es sich um eine Deutsche KW/Datum handelt.
|
Re: Kalenderwochen Funktion Falsch?
Also ich habe damals, und das schon zu Delphi 2 Zeiten, exakt diese Funktion entwickelt. Sie funktioniert richtig, teste mal
Delphi-Quellcode:
bei mir kommt da wie erwartet 2 raus.
ShowMessage(IntToStr(WeekOfDate(EncodeDate(2008, 1, 10))));
Gruß Hagen |
Re: Kalenderwochen Funktion Falsch?
Liste der Anhänge anzeigen (Anzahl: 1)
Moin moin,
mir ist gestern aufgefallen, dass diese funktion wohl doch fehlerhaft ist. Das Problem liegt wohl hier:
Delphi-Quellcode:
Folgender aufruf zeigt den Fehler:
((Date + 8 - Day) - EncodeDate(Y, 1, 1)) / 7
Delphi-Quellcode:
ShowMessage(IntToStr(WeekOfDate(StrToDateTime('06.01.2010 11:59:59')))+#13#10+
IntToStr(WeekOfDate(StrToDateTime('06.01.2010 12:00:00')))); |
Re: Kalenderwochen Funktion Falsch?
|
Re: Kalenderwochen Funktion Falsch?
Delphi-Quellcode:
ich komme hierbei leider zum selben ergebnis :-/
function DayOfWeekGerman(ADate: TDateTime): Integer;
begin Result := DayOfWeek(ADate) -1; if Result <= 0 then Result := 7; end; function WeekOfDate(A: TDateTime): Integer; var Day: Integer; Y,M,D: Word; begin Day := DayOfWeekGerman(A); DecodeDate(A +4 -Day, Y, M, D); Result := Round(((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7); end; procedure TForm1.Button1Click(Sender: TObject); var dat : TDateTime; begin ShowMessage(IntToStr(WeekOfDate(StrToDateTime('06.01.2010 11:59:59')))+#13#10+ IntToStr(WeekOfDate(StrToDateTime('06.01.2010 12:00:00')))); end; Schreibt man den Wert von
Delphi-Quellcode:
in einen double, dann sieht man auch warum.
((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7
Bei '06.01.2010 11:59:59' ergibt dann
Delphi-Quellcode:
Bei '06.01.2010 12:00:00' ergibt dann
((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7 = 1.4999983466
Delphi-Quellcode:
und da
((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7 = 1.5
Delphi-Quellcode:
entsteht der Fehler.
Round(1.5) = 2
|
Re: Kalenderwochen Funktion Falsch?
|
Re: Kalenderwochen Funktion Falsch?
Zitat:
Hagens Routine arbeitet fehlerfrei, solange der TDateTime Wert ganzzahlig ist. Wenn der TDateTime-Wert einen Zeitanteil hat, bringt sie an bestimmten Tagen dann fehlerhafte Resultate, wenn der Zeitanteil >= 12 Stunden ist. Also sollte am Anfang der Routine eine Zeile
Delphi-Quellcode:
eingefügt werden.
A := Int(A);
Vielleicht sollte man die letzte Zeile ändern von
Delphi-Quellcode:
in
Result := Round(((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7);
Delphi-Quellcode:
weil das besser zeigt, was gerechnet werden soll.
Result := Trunc(0.5+((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7);
M.E. sollte die Routine dann so aussehen:
Delphi-Quellcode:
function DayOfWeekGerman(ADate: TDateTime): Integer;
begin Result := DayOfWeek(ADate) -1; if Result <= 0 then Result := 7; end; function WeekOfDate(A: TDateTime): Integer; var Day: Integer; Y,M,D: Word; n:extended; begin A := Int(A); Day := DayOfWeekGerman(A); DecodeDate(A +4 -Day, Y, M, D); Result := Trunc(0.5+((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7); end; |
Re: Kalenderwochen Funktion Falsch?
Zitat:
|
Re: Kalenderwochen Funktion Falsch?
Zitat:
lies doch mal etwas genauer, wie ich das Round(...) ersetzt habe. Ich habe nicht einfach (wie von dir vorgeschlagen) das "Round" durch "Trunc" ersetzt sondern durch Trunc(0.5 + ...). Du schlugst vor, mit Trunc den Nachkommateil abzuschneiden. Ich runde ab, wenn der Nachkommaanteil < 0.5 ist und auf, wenn er >= 0.5 ist. Round würde dann, wenn der Nachkommaanteil = 0.5 ist, auf die nächstgelegene gerade Zahl runden. Bei dieser Routine wird dieser Fall nicht eintreten, weil bei einer Division eines Integerwertes durch 7 der Nachkommateil nie 0.5 sein kann. Ich halte es aber für "sauberer", hier nicht Round zu verwenden, damit klar ist was gerechnet werden soll. |
Re: Kalenderwochen Funktion Falsch?
Zitat:
|
Re: Kalenderwochen Funktion Falsch?
Wenn nur dern Datumbereich beachtet werden soll muss man abschneiden als Trunc()
|
Re: Kalenderwochen Funktion Falsch?
Büdde was? :gruebel:
|
Re: Kalenderwochen Funktion Falsch?
Die Berechnung ist falsch, wenn der TDateTime eine Zeitangabe enthält. Deshalb muss man diese abschneiden
|
Re: Kalenderwochen Funktion Falsch?
Moin moin,
Zitat:
Vom übergebenen Datum interessiert ja nur der Datumteil, also die Stellen vor dem Komma. Ob ich nun z.B. 40184 durch y teile oder 40184.xxxxx durch y, die Vorkommastellen vom Ergebnis bleiben gleich. Und da bei
Delphi-Quellcode:
nur unser übergebenes Datum Nachkommastellen haben könnte,
((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7
können wir auch bei dem Ergebnis den Nachkommaanteil ignorieren. Also reicht es, das Round durch Trunc zu ersetzen, wie du schon im Beitrag #8 geschrieben hast. |
Re: Kalenderwochen Funktion Falsch?
Zitat:
|
Re: Kalenderwochen Funktion Falsch?
Zitat:
|
Re: Kalenderwochen Funktion Falsch?
Zitat:
Beispiele: 01.01.2010 : 52 (Richtig : 53) 02.01.2010 : 52 (Richtig : 53) 03.01.2010 : 52 (Richtig : 53) Alle Tage des Jahres 2009. Im Zeitraum 15.10.1582 bis 31.12.2499 bringt ein einfaches Trunc(...) an 144918 (von 335006) Tagen ein falsches Ergebnis. (Zumindest wenn ich bei all dem, was ich gemacht habe nicht völlig gepennt habe) Der Fehler tritt bei mir auf: 1) An allen Tagen eines Jahres, wenn der 01.01. ein Dienstag, Mittwoch oder Donnerstag ist. (144269 Mal) 2) Am 01.01. und 02.01. eines Jahres, wenn der 01.01. ein Samstag ist und in die 53. Woche des Vorjahres fällt. (60 Mal) 3) Am 01.01., 02.01. und 03.01. eines Jahres, wenn der 01.01. ein Freitag ist. (396 Mal) 4) Am 30.12. und 31.12. eines Jahres, wenn der 30.12. ein Montag ist. (60 Mal) 5) Am 31.12. eines Jahres, wenn er ein Montag ist. (133 Mal) |
Re: Kalenderwochen Funktion Falsch?
Ok, dann nehm ich zurück, was ich gesagt hab. Meine Testfälle waren einfach nicht richtig konstruiert. Wenn es keine größeren Proteste gibt, werde ich das morgen im Laufe des Tages in die Funktion in der CL einarbeiten.
|
Re: Kalenderwochen Funktion Falsch?
Zitat:
Die Nachkommastellen dürfen keinesfalls einfach ignoriert werden - es sei denn man legt Wert auf Fehler. |
Re: Kalenderwochen Funktion Falsch?
Zitat:
Ich hab mal in die Funktion die Zwischenwerte eingefügt, da wird dann wohl jedem klar, daß ein simples Trunc nicht ausreicht. Aufruf : XWeekOfDate(EncodeDate(2009,01,01));
Delphi-Quellcode:
Ein Trunc (ohne vorher 0.5 zu addieren) würde als Resultat 0 ergeben.
function xWeekOfDate(A: TDateTime): Integer;
var Day: Integer; Y,M,D: Word; n:extended; begin A := Int(A); // A=39814 Day := DayOfWeek(A) -1; // Day=4 if Day <= 0 then Day := 7; // Day=4 DecodeDate(A +4 -Day, Y, M, D); // Y=2009 Result := Trunc(((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7); // Result = 0 // A+8-Day = 39818 // EncodeDate(Y,1,1) = 39814 // (A+8-Day)-EncodeDate(Y,1,1) = 4 // ((A+8-Day)-EncodeDate(Y,1,1))/7 = 0.5714285713 // Result = Trunc(0.5714285713) // Result = 0 Result := Trunc(0.5+((A +8 -Day) - EncodeDate(Y, 1, 1)) / 7); // Result = 1 // Result = Trunc(0.5 + 0.5714285713) // Result = Trunc(1.0714285713) // Result = 1 end; Ein Trunc (bei vorheriger addition von 0.5) ergibt das korrekte Resultat 1. Im Stillen habe ich gehofft, daß negaH mal ein paar Kommentare abgibt - scheint ihm wohl zu albern zu sein. Übrigens @negaH : eine sehr elegante Lösung hast da gefunden. Es wäre schön, wenn alle, die so oft "aus der Hüfte geschossene" Kommentare abgeben, vorher prüfen, ob das, was sie schreiben wollen auch korrekt ist. |
Re: Kalenderwochen Funktion Falsch?
Zitat:
Im Übrigen sollte man innerhalb von 24 Stunden den http://www.delphipraxis.net/template.../icon_edit.gif-Button nutzen, wenn man noch etwas hinzufügen möchte. ;) |
Re: Kalenderwochen Funktion Falsch?
Zitat:
Falls sich der Hinweis darauf bezieht, daß ich kurz hintereinander zwei Beiträge geschrieben habe : Ich hab das ganz bewußt in zwei Beiträge gepackt, weil ich auf zwei Beiträge von zwei Usern reagiert habe. |
Re: Kalenderwochen Funktion Falsch?
Moin moin,
@Klaus: :thumb: Zitat:
(warum auch immer). Ich hätte wohl erstmal versuchen sollen, den dahinter liegenden Algo zu verstehen :oops: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:41 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