![]() |
FMX - DX10 - Falsche Wochennummer im TCalendar
Wie ich leider gerade feststellen musste, zeigt die FMX-TCalendar-Komponente die falsche Wochennummer an (für diese Woche, den 6. Januar schon die 2. Woche, ist aber tatsächlich die erste, das Jahr 2015 hatte 53 Wochen).
Siehe Meldung bei QC hier: ![]() Nur gut, dass ich die MAC-Version meines Termin- und Aufgabenprogramms noch unter Beta-Status veröffentlicht habe, mit falschen Wochenzahlen ist das echt mies:cry: Ich hatte gerade mal versucht, die Quelle des Übels auszumachen, damit ich das evtl. selber mit einem Fix beheben kann. Irgendwie komme ich aber nicht an die Stelle ran. Die FMX-Calendar-Komponente wird vermutlich mit einem Style gezeichnet, dazu werden wohl Botschaften verschickt, ich weiß aber nicht wohin und welche Stelle ich quasi abhören müsste, um an die konkrete Zeichenroutine zu kommen. Ein Debugg-Versuch (z.B. ab OnPainting) führte leider nicht zum Ziel. Hat da evtl. Jemand eine Idee? |
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Delphi-Quellcode:
Zeile 584f :stupid:
unit FMX.Calendar.Style;
Man beachte den Kommentar in Zeile 583:
Delphi-Quellcode:
Da hat also ein Programmierer von Emba einen (angeblichen) Fehler in der Funktion
// WeekOfTheYear doesn't consider a current Locale. So for 01.01.2017 returns 52.
if MonthOf(FDateTime) = MonthJanuary then FirstWeekOfMonth := 1 else FirstWeekOfMonth := WeekOfTheYear(RecodeDay(FDateTime, 1));
Delphi-Quellcode:
festgestellt. Aber anstatt diesen Fehler einmal intern an das
WeekOfTheYear
Delphi-Quellcode:
-Team zu melden (ja, dafür hätte er wohl 4 Wochen Kaffee für alle holen müssen) denkt er sich eine ganz tolle Methode aus:
System.DateUtils
Jedes Jahr startet mit der Woche 1 :roll: Aber seine wir froh, dass er nicht einfach die
Delphi-Quellcode:
-Routine "gefixt" hat :mrgreen:
WeekOfTheYear
@Harry Melde doch mal diesen
Delphi-Quellcode:
"Fehler" und verweise stumpf und vor allem erbost auf den Kommentar. Die stellen selber Fehler fest und korrigieren die nicht. Mal sehen was passiert ... ob wir das Geschrei bis hier hören können? :stupid:
WeekOfTheYear
|
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Hmm..
Stellt sich die Frage, was liefert WeekOfYear für den 1.1.2016? Muss eigentlich KW 53 sein, so wie (richtig) 1.1.2017 noch zur KW 52 gehört ;) Blubber Blubber (noch zu Früh) "WeekOfTheYear" Und bei Delphi 6 gibt es die 'angebliche' Fehlerbehandlung noch nicht ;) |
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Zitat:
|
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Entschuldigt, aber ich glaube ihr sucht falsch.
Zitat:
![]() Je nach Sichtweise ist das also nicht unbedingt falsch. Gruß K-H |
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Nein, wir suchen nicht falsch, denn ab Februar wird die Wochennummer wieder so angezeigt wie die VCL Komponente das macht.
Die FMX-Variante ist grundsätzlich falsch implementiert. |
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Super, erst mal Danke für die Ausweisung der Stelle.
Allerdings reicht es leider nicht, die 3 Zeilen zu löschen, wie von Dir auf QC vorgeschlagen, denn dann zählt die Woche mit 54,55 Woche in Januar 2016 weiter (entscheidend ist die Zeichenroutine, die da unten weiter geht). Das ist mein aktueller Stand eines Workarounds (muss jetzt runter, haben Besuch), scheint zu funktionieren:
Delphi-Quellcode:
Wird erforderlich, um Umbrüche der Wochennummern im Dez/Januar richtig auszugeben.
procedure TStyledCalendar.FillWeeksNumbers;
var I: Integer; CaptionControl: ICaption; FirstWeekOfMonth: Byte; WeekCorrection, MNr: Integer; begin if FWeeks = nil then Exit; FWeeks.Visible := Model.WeekNumbers; // WeekOfTheYear doesn't consider a current Locale. So for 01.01.2017 returns 52. if ((MonthOf(FDateTime) = MonthJanuary)) then begin if (Weekoftheyear (FDateTime) <> 53) then begin FirstWeekOfMonth := WeekOfTheYear(RecodeDay (FDateTime, 1)); end else begin FirstWeekOfMonth := 1; end; end else begin FirstWeekOfMonth := WeekOfTheYear(RecodeDay (FDateTime,1)); end; // First week in FDay may be a last week of previous month. So we need to keep offset for correct counting of weeks. WeekCorrection := (DefineItemIndexOfFirstDayInCurrentMonth - 1) div 7; for I := 0 to FWeeks.ControlsCount - 1 do if Supports(FWeeks.Controls[I], ICaption, CaptionControl) then begin MNr := FirstWeekOfMonth + I - WeekCorrection; // Year 2015 has 53 Weeks; If Drawing parts of January in DEC-Calendar, start again with "1" in drawing if MNr > 53 then begin FirstWeekOfMonth := 0; MNr := 1; end; // eg. Dez. 2016 has 52 Weeks, so start after that again with "1" in drawing if ((MonthOf(FDateTime) = MonthDecember)) then begin if (MNr = 53) and (WeeksInAYear (YearOf (FDateTime)) =52) then begin FirstWeekOfMonth := 0; MNr := 1; end; end; // No 53.week in second week-Row in January possible if ((MonthOf(FDateTime) = MonthJanuary)) then begin if (MNr = 53) and (I = 1) then begin FirstWeekOfMonth := 0; MNr := 1; end; end; CaptionControl.Text := MNr.ToString; end; end; Edit: Den letzten IF-Block habe ich gerade (22:10) noch ergänzt. |
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Ähm, dieser Workaround ist noch schlimmer als der Bug im Original-Code.
Diese Änderungen reichen (einfaches Auskommentieren)
Delphi-Quellcode:
// WeekOfTheYear doesn't consider a current Locale. So for 01.01.2017 returns 52.
// if MonthOf(FDateTime) = MonthJanuary then // FirstWeekOfMonth := 1 // else FirstWeekOfMonth := WeekOfTheYear(RecodeDay(FDateTime, 1)); |
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Liste der Anhänge anzeigen (Anzahl: 3)
Also noch mal, Dein Vorschlag korrigiert zwar die falsche Berechnung an dieser Stelle, aber nicht die Ausgabe der Wochennummern insgesamt für den Kalender.
Deine "Korrektur" bringt u.a. die in den anliegenden Screenshots ersichtlichen fehlerhaften Ausgaben als Ergebnis (fehlerhafte Wochennummern in gelb). Ich gebe ja gerne zu, dass in der halben Stunde Zeit, die ich gerade hatte, der Workaround sicher nicht optimal geschrieben ist, sieht aber nach kurzen Tests (Vergleich einiger Jahre mit einem richtigen Kalender) vom Ergebnis erst mal ganz gut aus. Für alternative (schönere Lösungen) bin ich aber immer gerne zu haben.:wink: Davon mal abgesehen sollte der WA aber schnell von EMBA kommen, ist hier ja nicht unsere Aufgabe, deren Arbeit zu machen. |
AW: FMX - DX10 - Falsche Wochennummer im TCalendar
Nun ja, es ist eigentlich kein Hexenwerk, sondern nur logisches Vorgehen.
Delphi-Quellcode:
Sorry for being short :mrgreen:
procedure TStyledCalendar.FillWeeksNumbers;
var I: Integer; CaptionControl: ICaption; LMonday : TDate; begin if FWeeks = nil then Exit; FWeeks.Visible := Model.WeekNumbers; // Vom Monatsanfang den Wochenanfang ermitteln LMonday := StartOfTheWeek( StartOfTheMonth( FDateTime ) ); // für jede Zeile for I := 0 to FWeeks.ControlsCount-1 do begin // die Wochennummer ermitteln if Supports(FWeeks.Controls[I], ICaption, CaptionControl) then CaptionControl.Text := WeekOfTheYear(lMonday).ToString; // Tag eine Woche weiterzählen lMonday := IncWeek( lMonday ); end; end; Für die Überprüfung kann man auch gerne dieses kleine Konsolen-Programm starten (zeigt das Kalandar-Blatt) für den aktuellen Monat an.
Delphi-Quellcode:
Sieht dann so aus
program MonthCalendar;
{$APPTYPE CONSOLE} {$R *.res} uses System.DateUtils, System.SysUtils; procedure OutputMonthCalendarFor( const aDate: TDate; aRows: Integer = 6; aWeekNumbers: Boolean = true ); var lFirstMonday: TDate; lDay : TDate; row, day : Integer; begin lFirstMonday := StartOfTheWeek( StartOfTheMonth( aDate ) ); if aWeekNumbers then write( ' ' ); WriteLn( FormatDateTime( 'mmmm yyyy', aDate ):26 ); WriteLn; lDay := lFirstMonday; if aWeekNumbers then write( ' ' ); for day := 1 to 7 do begin write( FormatDateTime( '" "ddd" "', lDay ) ); lDay := IncDay( lDay, 1 ); end; WriteLn; lDay := lFirstMonday; for row := 0 to aRows - 1 do begin if aWeekNumbers then write( WeekOfTheYear( lDay ):2, ' ' ); for day := 0 to 6 do begin if lDay = DateOf( aDate ) then write( '<', DayOf( lDay ):2, '>' ) else write( ' ', DayOf( lDay ):2, ' ' ); lDay := IncDay( lDay, 1 ); end; WriteLn; end; end; begin try OutputMonthCalendarFor( Date ); except on E: Exception do WriteLn( E.ClassName, ': ', E.Message ); end; ReadLn; end.
Code:
Januar 2016
Mo Di Mi Do Fr Sa So 53 28 29 30 31 1 2 3 1 4 5 < 6> 7 8 9 10 2 11 12 13 14 15 16 17 3 18 19 20 21 22 23 24 4 25 26 27 28 29 30 31 5 1 2 3 4 5 6 7 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:56 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 by Thomas Breitkreuz