Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

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

AW: Wann beginnt bei einem Jahr x die Sommerzeit ?

  Alt 13. Jan 2014, 13:51
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 wDayOfWeek oder 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.
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 (13. Jan 2014 um 16:58 Uhr) Grund: Jetzt auch für Delphi-Versionen ohne Anonyme Methoden :o)
  Mit Zitat antworten Zitat