如何只添加几天到日期时间变量?

时间:2016-01-20 08:40:52

标签: delphi delphi-7

当我需要将日期1/1/2016增加7天时,我可以做到:

IncDay(myDate, 7); // Result 8/1/2016

如果我需要忽略某些日子(例如星期六),我该怎么办,结果是10/1/2016

4 个答案:

答案 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。但是,对于有效/无效的工作日“接近”开始日期,调整结果会相当棘手。即使在所有这些复杂性之后,您仍然无法处理特殊日期,例如公共假期。

幸运的是,有不同的方法实施起来更简单,更灵活。唯一的缺点是它对“大”增量效率低。

  • 一般方法是一次增加1天。
  • 并在每次增量时检查新日期的有效性。
  • 仅当新日期有效时,将增量计数器减1。
  • 在循环中重复上述操作,直到增量计数器减少为0。

以下使用回调函数检查每个日期的有效性。

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周需要再增加一天。