Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Wann beginnt bei einem Jahr x die Sommerzeit ? (https://www.delphipraxis.net/178490-wann-beginnt-bei-einem-jahr-x-die-sommerzeit.html)

Codix32 12. Jan 2014 22:45

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1243345)
Zitat:

Zitat von Codix32 (Beitrag 1243339)
@Furtbichler,

die Funktion ist ungenau.

Für das Jahr 2018 kriege ich den 1.04.2018 als Sommerzeitbeginn,
weil der 1.04.2018 ein Sonntag ist.

Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,4,1);
   result := (result - DayOfWeek(Result))+1;
End;

Es ist auch nur ein kleiner Fehler drin (das war der Intelligenztest :mrgreen:)
Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
   result := EncodeDate(Jahr,4,1) - 1; // letzter Tag im März, statt erster Tag im April :o)
   result := (result - DayOfWeek(Result))+1;
End;

Ups, danke Sir Rufo,

ich hab gerade so was gemacht und vom Aussehen her gefällt mir es nicht:
Delphi-Quellcode:
Function AnfangDerSommerzeit(Jahr : Word) : TDateTime;
Begin
 if DayOfweek(EncodeDate(Jahr,4,1)) > 1 then
   result := EncodeDate(Jahr,4,1)
 else
   result := EncodeDate(Jahr,3,31);

   result := (result - DayOfWeek(Result))+1;
End;

Furtbichler 13. Jan 2014 06:28

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Codix32 (Beitrag 1243346)
Ups, danke Sir Rufo,

Dem schließe ich mich an.
Zitat:

ich hab gerade so was gemacht und vom Aussehen her gefällt mir es nicht:
Lass es doch so wie von Sir Rufo korrigiert.
Meine erste Version war übrigens:
Delphi-Quellcode:
Result := EncodeDate(Year,4,1);
Repeat
  Result := Result - 1;
Until DayOfWeek(Result)=1;
Ich persönlich finde die Schleife leichter verständlich: Nimm den 1.April und zähle dann Rückwärts bis zum letzten Sonntag im März.

Nach kurzem Studium der DateUtils würde ich doch folgende Version nehmen:
Delphi-Quellcode:
Function LastSundayInMarch(Year : Word) : TDateTime;
Begin
  Result := EncodeDate(Year,4,1);
  Result := Result - DateUtils.DayOfTheWeek(Result);
End;
Gut zu wissen, das 'DayOfTheWeek' und 'DayOfWeek' unterschiedliche Ergebnisse liefern :wall:

hoika 13. Jan 2014 06:37

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Hallo,

ich habe das jetzt ähnlich umgesetzt,
also mit einer Schleife, die ab dem 31.3. solange rückwärts zählt,
bis ein Sonntag rauskommt (es sei denn, der 31.3. ist bereits ein Sonntag).

Und ich habe auch Unit-Tests dazugepackt ;)

Übrigens:
Das mit dem Result :=
gibt es meines Wissens bereits seit Turbo-Pascal.


Heiko

Furtbichler 13. Jan 2014 06:56

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von hoika (Beitrag 1243353)
Und ich habe auch Unit-Tests dazugepackt ;)

Zeig mal! :thumb:

Union 13. Jan 2014 08:32

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Damit die Funktion allgmein einsetzbar wird, sollten aber keine Konstanten für, Monat, Wochentag und Sequenz verwendet werden sondern die aus der TTimeZoneInformation Struktur.

himitsu 13. Jan 2014 09:11

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von Union (Beitrag 1243364)
Damit die Funktion allgmein einsetzbar wird, sollten aber keine Konstanten für, Monat, Wochentag und Sequenz verwendet werden sondern die aus der TTimeZoneInformation Struktur.

Du meinst so ähnlich, wie in #6 ?

Union 13. Jan 2014 09:14

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Ja. In den letzten Beispielen wurde ja immer konstant mit April, Sonntag und "letzter" gearbeitet.

himitsu 13. Jan 2014 10:51

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Schön ist ja, daß es nicht nur diese eine Regelung gibt und andere Länder die Sommerzeit zu einem anderem Termin beginnen und beenden.
In den USA machen die es z.B. 2-3 Wochen früher und Mexiko hinkt uns eine Woche hinterher.
Und einige Länder kennen solche eine schwachsinnige Zeitumstellung überhaupt nicht.

Da wäre es schon "intelligenter" wenn man aus der aktuellen Zoneninfo die passenden Daten verwendet.



Jetzt muß nur noch jemand kommen und schauen wie das eigentlich unter Mac, iOS, Android und Co. ausschaut,
denn diese WinAPI wird dort wohl nicht ganz funktionieren.


Wozu muß man das aber eigentlich wissen?
Mit zeitlichen Sprüngen muß man ja so oder so rechnen, angefangen beim Schaltjahr, bis hin zu den "heimlichen" Schaltsekunden,
über falsch gehende Uhren, welche urplöztlich syncronisiert werden und die unterschiedlichen Netzwerklatenzen zwischen PC und Zeitserver.

Furtbichler 13. Jan 2014 12:08

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Zitat:

Zitat von himitsu (Beitrag 1243399)
Da wäre es schon "intelligenter" wenn man aus der aktuellen Zoneninfo die passenden Daten verwendet.

Ja natürlich, aber wenn ich mir den Thread bisher anschaue, vor allen Dingen die eingangs erwähnten Wünsche sowie Definitionen der ptb, halte ich die weltweitgültige Version zwar für Endgeil, aber hier vielleicht etwas überkandidelt.

Wobei: Wenn man sie hat (und sie funktioniert und hat Unittests), ist Ruhe im Karton.

Sir Rufo 13. Jan 2014 13:51

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?
 
Hier mal eine Variante zum Berechnen der variablen Tage

Der Aufruf erfolgt dann so
Delphi-Quellcode:
uses
  DayLightSaving;

var
  LStartDate, LEndDate : TDate;
begin
  LStartDate := TDayLightSaving.GetDate( 2014, 3, domLast, dowSunday );
  LEndDate := TDayLightSaving.GetDate( 2014, 10, domLast, dowSunday );
end;
Dabei habe ich bewusst nicht die Werte für
Delphi-Quellcode:
wDayOfWeek
oder
Delphi-Quellcode:
wDay
aus der Windows-API übernommen. Diese müssen also zunächst übersetzt werden in den richtigen ENUM-Wert für
Delphi-Quellcode:
    TDLSDayOfWeek = ( dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturyday );
    TDLSDayOfMonth = ( domFirst, domSecond, domThird, domForth, domLast );
Delphi-Quellcode:
unit DayLightSaving;

interface

{.$DEFINE USE_ANONYMOUS}

  uses
    DateUtils;

  type
    TDLSDayOfWeek = ( dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturyday );
    TDLSDayOfMonth = ( domFirst, domSecond, domThird, domForth, domLast );

{$IFDEF USE_ANONYMOUS}
    TDLSDateFunction = reference to function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
{$ELSE}

    IDLSDateFunction = interface
      ['{10C582CE-AE7E-4489-9D98-B147C37F6427}']
      function GetDate( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    end;

    TDLSNthDateFunction = class( TInterfacedObject, IDLSDateFunction )
    var
      FN : Integer;
    public
      constructor Create( N : Integer );
      function GetDate( const AYear : Word; const AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    end;

    TDLSLastDateFunction = class( TInterfacedObject, IDLSDateFunction )
    public
      function GetDate( const AYear : Word; const AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    end;
{$ENDIF}

    TDayLightSaving = class
    private const
      // System.DateUtils.DayOfTheWeek
      DayOfTheWeekValue : array [TDLSDayOfWeek] of Integer = ( DaySunday, DayMonday, DayTuesday, DayWednesday, DayThursday, DayFriday, DaySaturday );
      class function GetDateFromLastWeekDayOfMonth( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
      class function GetDateFromNthWeekDayOfMonth( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek; N : Integer ) : TDate;
{$IFDEF USE_ANONYMOUS}
      class var _DateFunctions : array [TDLSDayOfMonth] of TDLSDateFunction;
{$ELSE}
      class var _DateFunctions : array [TDLSDayOfMonth] of IDLSDateFunction;
{$ENDIF}
    protected
      class constructor Create;
    public
      class function GetDate( const AYear, AMonth : Word; ADayOfMonth : TDLSDayOfMonth; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    end;

implementation

  uses
    SysUtils;

  { TDayLightSaving }

  class function TDayLightSaving.GetDateFromLastWeekDayOfMonth( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := EncodeDate( AYear, AMonth, 1 ); // Erster Tag im Monat
      Result := IncMonth( Result, 1 );         // Erster Tag im Folgemonat
      Result := IncDay( Result, -1 );          // Letzer Tag im Monat
      Result := Result - ( DaysPerWeek + DayOfTheWeek( Result ) - DayOfTheWeekValue[ADayOfWeek] ) mod DaysPerWeek;
    end;

  class function TDayLightSaving.GetDateFromNthWeekDayOfMonth( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek; N : Integer ) : TDate;
    begin
      Result := EncodeDate( AYear, AMonth, 1 ); // Erster Tag im Monat
      Result := Result + DaysPerWeek * ( N - 1 ) + ( DaysPerWeek - DayOfTheWeek( Result ) + DayOfTheWeekValue[ADayOfWeek] ) mod DaysPerWeek;
    end;

{$IFDEF USE_ANONYMOUS}

  class constructor TDayLightSaving.Create;
    begin
      TDayLightSaving._DateFunctions[domFirst] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, 1 );
          end;
      TDayLightSaving._DateFunctions[domSecond] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, 2 );
          end;
      TDayLightSaving._DateFunctions[domThird] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, 3 );
          end;
      TDayLightSaving._DateFunctions[domForth] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, 4 );
          end;
      TDayLightSaving._DateFunctions[domLast] := function( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate
          begin
            Result := GetDateFromLastWeekDayOfMonth( AYear, AMonth, ADayOfWeek );
          end;
    end;

  class function TDayLightSaving.GetDate( const AYear, AMonth : Word; ADayOfMonth : TDLSDayOfMonth; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := _DateFunctions[ADayOfMonth]( AYear, AMonth, ADayOfWeek );
    end;
{$ELSE}

  class constructor TDayLightSaving.Create;
    begin
      TDayLightSaving._DateFunctions[domFirst] := TDLSNthDateFunction.Create( 1 );
      TDayLightSaving._DateFunctions[domSecond] := TDLSNthDateFunction.Create( 2 );
      TDayLightSaving._DateFunctions[domThird] := TDLSNthDateFunction.Create( 3 );
      TDayLightSaving._DateFunctions[domForth] := TDLSNthDateFunction.Create( 4 );
      TDayLightSaving._DateFunctions[domLast]  := TDLSLastDateFunction.Create;
    end;

  class function TDayLightSaving.GetDate( const AYear, AMonth : Word; ADayOfMonth : TDLSDayOfMonth; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := _DateFunctions[ADayOfMonth].GetDate( AYear, AMonth, ADayOfWeek );
    end;

  { TDLSNthDateFunction }

  constructor TDLSNthDateFunction.Create( N : Integer );
    begin
      inherited Create;
      FN := N;
    end;

  function TDLSNthDateFunction.GetDate( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := TDayLightSaving.GetDateFromNthWeekDayOfMonth( AYear, AMonth, ADayOfWeek, FN );
    end;

  { TDLSLastDateFunction }

  function TDLSLastDateFunction.GetDate( const AYear, AMonth : Word; ADayOfWeek : TDLSDayOfWeek ) : TDate;
    begin
      Result := TDayLightSaving.GetDateFromLastWeekDayOfMonth( AYear, AMonth, ADayOfWeek );
    end;

{$ENDIF}

end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:23 Uhr.
Seite 3 von 4     123 4      

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