AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Cross-Platform-Entwicklung FMX - DX10 - Falsche Wochennummer im TCalendar
Thema durchsuchen
Ansicht
Themen-Optionen

FMX - DX10 - Falsche Wochennummer im TCalendar

Ein Thema von Harry Stahl · begonnen am 5. Jan 2016 · letzter Beitrag vom 6. Jan 2016
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.479 Beiträge
 
Delphi 11 Alexandria
 
#1

FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 5. Jan 2016, 23:48
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: https://quality.embarcadero.com/browse/RSP-13358

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

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?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 00:53
unit FMX.Calendar.Style; Zeile 584f

Man beachte den Kommentar in Zeile 583:
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));
Da hat also ein Programmierer von Emba einen (angeblichen) Fehler in der Funktion WeekOfTheYear festgestellt. Aber anstatt diesen Fehler einmal intern an das System.DateUtils -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:

Jedes Jahr startet mit der Woche 1

Aber seine wir froh, dass er nicht einfach die WeekOfTheYear -Routine "gefixt" hat

@Harry

Melde doch mal diesen WeekOfTheYear "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?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 6. Jan 2016 um 01:06 Uhr)
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
961 Beiträge
 
Delphi 6 Professional
 
#3

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 09:39
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

Geändert von HolgerX ( 6. Jan 2016 um 09:43 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 10:41
Und bei Delphi 6 gibt es die 'angebliche' Fehlerbehandlung noch nicht
Es ist ja ein FXM-Problem. in der VCL passt es ja.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#5

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 12:17
Entschuldigt, aber ich glaube ihr sucht falsch.
Zitat:
Das Jahr umfasst mindestens 52 Wochen, die v. a. im Geschäftsleben als Kalenderwochen (KW) durchnummeriert werden, wobei es bei den Wochen-Nummerierungen verschiedene Definitionen gibt. Je nach angewandter Regel kann die erste Woche des Jahres unterschiedlich sein:
ISO (DIN/ÖNORM/SN): die Woche, die den ersten Donnerstag des Jahres enthält (ISO 8601, früher DIN 1355-1). Äquivalent sind folgende Definitionen (da ISO 8601 den Montag als ersten Tag der Woche definiert): die Woche, die den 4. Januar enthält
die Woche, in der der 1. Januar ein Montag, Dienstag, Mittwoch oder Donnerstag ist, sonst die darauf folgende Woche
die erste Woche, in die mindestens vier Tage des neuen Jahres fallen bzw. die erste Woche, in die mehr Tage auf das neue Jahr fallen als auf das alte Jahr

USA: jene, in die der 1. Januar fällt
Selten: die erste vollständige Woche des Jahres
https://de.wikipedia.org/wiki/Woche

Je nach Sichtweise ist das also nicht unbedingt falsch.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 12:20
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.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.479 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 18:31
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:
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;
Wird erforderlich, um Umbrüche der Wochennummern im Dez/Januar richtig auszugeben.

Edit: Den letzten IF-Block habe ich gerade (22:10) noch ergänzt.

Geändert von Harry Stahl ( 6. Jan 2016 um 21:37 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 18:44
Ä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));
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.479 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 20:27
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.

Davon mal abgesehen sollte der WA aber schnell von EMBA kommen, ist hier ja nicht unsere Aufgabe, deren Arbeit zu machen.
Miniaturansicht angehängter Grafiken
month1.jpg   month2.jpg   month3.jpg  

Geändert von Harry Stahl ( 6. Jan 2016 um 20:37 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: FMX - DX10 - Falsche Wochennummer im TCalendar

  Alt 6. Jan 2016, 22:00
Nun ja, es ist eigentlich kein Hexenwerk, sondern nur logisches Vorgehen.
Delphi-Quellcode:
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;
Sorry for being short

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:
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.
Sieht dann so aus
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
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 6. Jan 2016 um 22:08 Uhr)
  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 18: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