当我需要将日期1/1/2016
增加7天时,我可以做到:
IncDay(myDate, 7); // Result 8/1/2016
如果我需要忽略某些日子(例如星期六),我该怎么办,结果是10/1/2016
?
答案 0 :(得分:3)
显然,根据有些神秘的评论,您希望将日期增加一天,不包括星期六。您可以使用DateUtils
中的DayOfTheWeek
功能来完成此操作。这将告诉您指定日期的星期几。
所以你的功能是这样的:
function IncExcludingSaturday(FromDate: TDateTime; IncDays: Integer): TDateTime;
begin
Assert(IncDays >= 0);
Result := FromDate;
if DayOfTheWeek(Result) = DaySaturday then
Result := IncDay(Result);
while IncDays > 0 do
begin
Result := IncDay(Result);
if DayOfTheWeek(Result) = DaySaturday then
Result := IncDay(Result);
dec(IncDays);
end;
end;
这是实现目标的一种相当粗略的方式。您可以在此处找到更多有趣的提示:AddBusinessDays and GetBusinessDays
现在,在这个问题中你建议从2016年1月1日起7天(星期六除外)带你到2016年9月1日。但那肯定是错的,因为那个日期是星期六。正确的答案肯定是10/01/2016这是一个星期天。换句话说,我们需要跳过两个星期六,即2日和9日。
答案 1 :(得分:2)
这为ANumberOfDays
范围内的每个 Saturday 的计算增加了一天:
{.$DEFINE UNCLEAR_WHAT_YOU_R_ASKING}
function IncDayIgnoringSaturdays(const AValue: TDateTime; const ANumberOfDays: Integer = 1): TDateTime;
var
i, j: Integer;
begin
i := ANumberOfDays;
j := 0;
Result := AValue;
while i > 0 do begin
Result := IncDay(Result);
if DayOfTheWeek(Result) = DaySaturday then
Inc(j);
Dec(i);
end;
Result := IncDay(Result, j);
{$IFDEF UNCLEAR_WHAT_YOU_R_ASKING}
if DayOfTheWeek(Result) = DaySaturday then
Result := IncDay(Result);
{$ENDIF}
end;
begin
WriteLn(DateTimeToStr(IncDayIgnoringSaturdays(StrToDateTime('1/1/2016'), 7)));
WriteLn(DateTimeToStr(IncDayIgnoringSaturdays(StrToDateTime('1/1/2016'), 14)));
ReadLn;
end.
修改强>
以上内容可能会在星期六返回日期,具体取决于UNCLEAR_WHAT_YOU_R_ASKING
条件定义。
答案 2 :(得分:0)
对于排除单个特定工作日的特殊情况,您已获得了几个答案。这不是特别灵活。
您可以尝试实现一个函数,该函数将一组“有效”的工作日作为其参数之一。递增日期的天数约为AIncByDays * 7 / NoOfDaysInSet
。但是,对于有效/无效的工作日“接近”开始日期,调整结果会相当棘手。即使在所有这些复杂性之后,您仍然无法处理特殊日期,例如公共假期。
幸运的是,有不同的方法实施起来更简单,更灵活。唯一的缺点是它对“大”增量效率低。
以下使用回调函数检查每个日期的有效性。
type
TValidDateFunc = function (ADate: TDateTime): Boolean;
function IncValidDays(AStartDate: TDateTime; AIncBy: Integer; AIsValid: TValidDateFunc): TDateTime;
var
LIncDirection: Integer;
begin
// Support dec using negative AIncBy
if AIncBy >= 0 then
LIncDirection := 1
else
LIncDirection := -1;
Result := AStartDate;
while (AIncBy <> 0) do
begin
IncDay(Result, LIncDirection);
if (AIsValid(Result)) then
Dec(AIncBy, LIncDirection);
end;
end;
现在您可以简单地编写您想要的任何函数来确定有效日期并在上述函数中使用它。 E.g。
function DateNotSaturday(ADate: TDateTime): Boolean;
begin
Result := (DayOfTheWeek(ADate) <> DaySaturday);
end;
NewDate := IncValidDays(SomeDate, 10, DateNotSaturday);
请注意,现在编写一个仅使用非公共假期的工作日的功能变得非常容易。 E.g。
function IsWorkDay(ADate: TDateTime): Boolean;
var
LDay, LMonth, LYear: Word;
begin
DecodeDate(ADate, LYear, LMonth, LDay);
Result := True;
Result := Result and (DayOfTheWeek(ADate) <> DaySaturday);
Result := Result and (DayOfTheWeek(ADate) <> DaySunday);
Result := Result and ((LDay <> 1) or (LMonth <> 1)); //Excludes New Years day.
...
end;
这种方法的最大优点是你不必处理“双重忽略”约会的风险,因为这是一个周末和公众假期。
注意:在最新版本的Delphi中,您可以使用匿名方法替换回调函数。
答案 3 :(得分:-1)
使用DayOfTheWeek函数确定星期几。现在你知道下周六何时会进入你的时期。如果您的期限大于一周,那么您可以在您的期间内多个星期六的整数周。如果您的期限超过7周,则每7周需要再增加一天。