📄 jclschedule.pas
字号:
end;
end;
function TWeeklySchedule.NextValidStamp(const Stamp: TTimeStamp): TTimeStamp;
begin
Result := Stamp;
MakeValidStamp(Result);
if EqualTimeStamps(Stamp, Result) then
begin
// Time stamp has not been adjusted (it was valid). Determine the next time stamp
Inc(Result.Date);
MakeValidStamp(Result); // Skip over unwanted days and weeks
end;
end;
function TWeeklySchedule.GetDaysOfWeek: TScheduleWeekDays;
begin
CheckInterfaceAllowed;
Result := FDaysOfWeek;
end;
function TWeeklySchedule.GetInterval: Cardinal;
begin
CheckInterfaceAllowed;
Result := FInterval;
end;
procedure TWeeklySchedule.SetDaysOfWeek(Value: TScheduleWeekDays);
begin
CheckInterfaceAllowed;
if Value = [] then
raise ESchedule.CreateRes(@RsScheduleNoDaySpecified);
FDaysOfWeek := Value;
end;
procedure TWeeklySchedule.SetInterval(Value: Cardinal);
begin
CheckInterfaceAllowed;
if Value = 0 then
raise ESchedule.CreateRes(@RsScheduleIntervalZero);
FInterval := Value;
end;
//=== { TMonthlySchedule } ===================================================
type
TMonthlySchedule = class(TScheduleAggregate)
private
FIndexKind: TScheduleIndexKind;
FIndexValue: Integer;
FDay: Cardinal;
FInterval: Cardinal;
protected
class function RecurringType: TScheduleRecurringKind; override;
function ValidStamp(const Stamp: TTimeStamp): Boolean; override;
procedure MakeValidStamp(var Stamp: TTimeStamp); override;
function NextValidStamp(const Stamp: TTimeStamp): TTimeStamp; override;
function ValidStampMonthIndex(const TYear, TMonth, TDay: Word): Boolean;
procedure MakeValidStampMonthIndex(var TYear, TMonth, TDay: Word);
public
constructor Create(const Controller: IUnknown);
// IJclMonthlySchedule
function GetIndexKind: TScheduleIndexKind;
function GetIndexValue: Integer;
function GetDay: Cardinal;
function GetInterval: Cardinal;
procedure SetIndexKind(Value: TScheduleIndexKind);
procedure SetIndexValue(Value: Integer);
procedure SetDay(Value: Cardinal);
procedure SetInterval(Value: Cardinal);
property IndexKind: TScheduleIndexKind read GetIndexKind write SetIndexKind;
property IndexValue: Integer read GetIndexValue write SetIndexValue;
property Day: Cardinal read GetDay write SetDay;
property Interval: Cardinal read GetInterval write SetInterval;
end;
constructor TMonthlySchedule.Create(const Controller: IUnknown);
begin
inherited Create(Controller);
FIndexKind := sikNone;
FIndexValue := sivFirst;
FDay := 1;
FInterval := 1;
end;
class function TMonthlySchedule.RecurringType: TScheduleRecurringKind;
begin
Result := srkMonthly;
end;
function TMonthlySchedule.ValidStamp(const Stamp: TTimeStamp): Boolean;
var
SYear, SMonth, SDay: Word;
TYear, TMonth, TDay: Word;
begin
DecodeDate(TimeStampToDateTime(Schedule.StartDate), SYear, SMonth, SDay);
DecodeDate(TimeStampToDateTime(Stamp), TYear, TMonth, TDay);
Result := (((TYear * 12 + TMonth) - (SYear * 12 + SMonth)) mod Integer(Interval) = 0) and
ValidStampMonthIndex(TYear, TMonth, TDay);
end;
procedure TMonthlySchedule.MakeValidStamp(var Stamp: TTimeStamp);
var
SYear, SMonth, SDay: Word;
TYear, TMonth, TDay: Word;
MonthDiff: Integer;
begin
DecodeDate(TimeStampToDateTime(Schedule.StartDate), SYear, SMonth, SDay);
DecodeDate(TimeStampToDateTime(Stamp), TYear, TMonth, TDay);
MonthDiff := (TYear * 12 + TMonth) - (SYear * 12 + SMonth);
if MonthDiff mod Integer(Interval) <> 0 then
begin
Inc(TMonth, Integer(Interval) - (MonthDiff mod Integer(Interval)));
if TMonth > 12 then
begin
Inc(TYear, TMonth div 12);
TMonth := TMonth mod 12;
end;
TDay := 1;
end;
MakeValidStampMonthIndex(TYear, TMonth, TDay);
while DateTimeToTimeStamp(JclDateTime.EncodeDate(TYear, TMonth, TDay)).Date < Stamp.Date do
begin
Inc(TMonth, Integer(Interval));
if TMonth > 12 then
begin
Inc(TYear, TMonth div 12);
TMonth := TMonth mod 12;
end;
MakeValidStampMonthIndex(TYear, TMonth, TDay);
end;
Stamp.Date := DateTimeToTimeStamp(JclDateTime.EncodeDate(TYear, TMonth, TDay)).Date;
end;
function TMonthlySchedule.NextValidStamp(const Stamp: TTimeStamp): TTimeStamp;
begin
Result := Stamp;
MakeValidStamp(Result);
if EqualTimeStamps(Stamp, Result) then
begin
// Time stamp has not been adjusted (it was valid). Determine the next time stamp
Inc(Result.Date);
MakeValidStamp(Result); // Skip over unwanted days and months
end;
end;
function TMonthlySchedule.ValidStampMonthIndex(const TYear, TMonth, TDay: Word): Boolean;
var
DIM: Integer;
TempDay: Integer;
begin
DIM := DaysInMonth(JclDateTime.EncodeDate(TYear, TMonth, 1));
case IndexKind of
sikNone:
Result := (TDay = Day) or ((Integer(Day) > DIM) and (TDay = DIM));
sikDay:
Result :=
((IndexValue = sivLast) and (TDay = DIM)) or
((IndexValue <> sivLast) and (
(TDay = IndexValue) or (
(IndexValue > DIM) and
(TDay = DIM)
) or (
(IndexValue < 0) and (
(TDay = DIM + 1 + IndexValue) or (
(-IndexValue > DIM) and
(TDay = 1)
)
)
)
));
sikWeekDay:
begin
case IndexValue of
sivFirst:
TempDay := FirstWeekDay(TYear, TMonth);
sivLast:
TempDay := LastWeekDay(TYear, TMonth);
else
TempDay := IndexedWeekDay(TYear, TMonth, IndexValue);
if TempDay = 0 then
begin
if IndexValue > 0 then
TempDay := LastWeekDay(TYear, TMonth)
else
if IndexValue < 0 then
TempDay := FirstWeekDay(TYear, TMonth);
end;
end;
Result := TDay = TempDay;
end;
sikWeekendDay:
begin
case IndexValue of
sivFirst:
TempDay := FirstWeekendDay(TYear, TMonth);
sivLast:
TempDay := LastWeekendDay(TYear, TMonth);
else
TempDay := IndexedWeekendDay(TYear, TMonth, IndexValue);
if TempDay = 0 then
begin
if IndexValue > 0 then
TempDay := LastWeekendDay(TYear, TMonth)
else
if IndexValue < 0 then
TempDay := FirstWeekendDay(TYear, TMonth);
end;
end;
Result := TDay = TempDay;
end;
sikMonday..sikSunday:
begin
case IndexValue of
sivFirst:
TempDay := FirstDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay));
sivLast:
TempDay := LastDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay));
else
TempDay := IndexedDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay),
IndexValue);
if TempDay = 0 then
begin
if IndexValue > 0 then
TempDay := LastDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay))
else
if IndexValue < 0 then
TempDay := FirstDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay));
end;
end;
Result := TDay = TempDay;
end;
else
Result := False;
end;
end;
procedure TMonthlySchedule.MakeValidStampMonthIndex(var TYear, TMonth, TDay: Word);
var
DIM: Integer;
begin
DIM := DaysInMonth(JclDateTime.EncodeDate(TYear, TMonth, 1));
case IndexKind of
sikNone:
begin
TDay := Day;
if Integer(Day) > DIM then
TDay := DIM;
end;
sikDay:
begin
if (IndexValue = sivLast) or (Integer(IndexValue) > DIM) then
TDay := DIM
else
if IndexValue > 0 then
TDay := IndexValue
else
begin
if -IndexValue > DIM then
TDay := 1
else
TDay := DIM + 1 + IndexValue;
end;
end;
sikWeekDay:
begin
case IndexValue of
sivFirst:
TDay := FirstWeekDay(TYear, TMonth);
sivLast:
TDay := LastWeekDay(TYear, TMonth);
else
begin
TDay := IndexedWeekDay(TYear, TMonth, IndexValue);
if TDay = 0 then
begin
if IndexValue > 0 then
TDay := LastWeekDay(TYear, TMonth)
else
if IndexValue < 0 then
TDay := FirstWeekDay(TYear, TMonth);
end;
end;
end;
end;
sikWeekendDay:
begin
case IndexValue of
sivFirst:
TDay := FirstWeekendDay(TYear, TMonth);
sivLast:
TDay := LastWeekendDay(TYear, TMonth);
else
begin
TDay := IndexedWeekendDay(TYear, TMonth, IndexValue);
if TDay = 0 then
begin
if IndexValue > 0 then
TDay := LastWeekendDay(TYear, TMonth)
else
if IndexValue < 0 then
TDay := FirstWeekendDay(TYear, TMonth);
end;
end;
end;
end;
sikMonday..sikSunday:
begin
case IndexValue of
sivFirst:
TDay := FirstDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay));
sivLast:
TDay := LastDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay));
else
TDay := IndexedDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay),
IndexValue);
if TDay = 0 then
begin
if IndexValue > 0 then
TDay := LastDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay))
else
if IndexValue < 0 then
TDay := FirstDayOfWeek(TYear, TMonth, Ord(IndexKind) - Ord(sikWeekendDay));
end;
end;
end;
end;
end;
function TMonthlySchedule.GetIndexKind: TScheduleIndexKind;
begin
CheckInterfaceAllowed;
Result := FIndexKind;
end;
function TMonthlySchedule.GetIndexValue: Integer;
begin
CheckInterfaceAllowed;
if not (FIndexKind in [sikDay .. sikSunday]) then
raise ESchedule.CreateRes(@RsScheduleIndexValueSup);
Result := FIndexValue;
end;
function TMonthlySchedule.GetDay: Cardinal;
begin
CheckInterfaceAllowed;
Result := FDay;
end;
function TMonthlySchedule.GetInterval: Cardinal;
begin
CheckInterfaceAllowed;
Result := FInterval;
end;
procedure TMonthlySchedule.SetIndexKind(Value: TScheduleIndexKind);
begin
CheckInterfaceAllowed;
FIndexKind := Value;
end;
procedure TMonthlySchedule.SetIndexValue(Value: Integer);
begin
CheckInterfaceAllowed;
if not (FIndexKind in [sikDay .. sikSunday]) then
raise ESchedule.CreateRes(@RsScheduleIndexValueSup);
if Value = 0 then
raise ESchedule.CreateRes(@RsScheduleIndexValueZero);
FIndexValue := Value;
end;
procedure TMonthlySchedule.SetDay(Value: Cardinal);
begin
CheckInterfaceAllowed;
if not (FIndexKind in [sikNone]) then
raise ESchedule.CreateRes(@RsScheduleDayNotSupported);
if (Value = 0) or (Value > 31) then
raise ESchedule.CreateRes(@RsScheduleDayInRange);
FDay := Value;
end;
procedure TMonthlySchedule.SetInterval(Value: Cardinal);
begin
CheckInterfaceAllowed;
if Value = 0 then
raise ESchedule.CreateRes(@RsScheduleIntervalZero);
FInterval := Value;
end;
//=== { TYearlySchedule } ====================================================
type
TYearlySchedule = class(TMonthlySchedule)
private
FMonth: Cardinal;
protected
class function RecurringType: TScheduleRecurringKind; override;
function ValidStamp(const Stamp: TTimeStamp): Boolean; override;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -