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.