Delphi 如何只添加一些日期时间变量?

Delphi 如何只添加一些日期时间变量?,delphi,delphi-7,Delphi,Delphi 7,当我需要将日期1/1/2016增加7天时,我可以简单地执行以下操作: IncDay(myDate, 7); // Result 8/1/2016 如果我需要忽略某些日期(如周六),那么结果是2016年1月10日,我该怎么办?显然,基于有些模糊的评论,您希望将日期增加几天,不包括周六。您可以通过使用DateUtils中的函数来实现这一点。这将告诉您指定日期在一周中的哪一天 所以你的函数是这样的: function IncExcludingSaturday(FromDate: TDateTime;

当我需要将日期
1/1/2016
增加7天时,我可以简单地执行以下操作:

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

如果我需要忽略某些日期(如周六),那么结果是2016年1月10日,我该怎么办?

显然,基于有些模糊的评论,您希望将日期增加几天,不包括周六。您可以通过使用
DateUtils
中的函数来实现这一点。这将告诉您指定日期在一周中的哪一天

所以你的函数是这样的:

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;
这是实现你目标的一种相当粗糙的方式。您可以在这里找到更有趣的想法:


现在,在问题中,您建议从2016年1月1日起的7天(不包括周六)将您带到2016年1月9日。但这肯定是错误的,因为那天是星期六。正确答案肯定是2016年1月10日,也就是周日。换句话说,我们需要跳过两个星期六,即2号和9号。

显然,根据有些隐晦的评论,您希望将日期增加几天,不包括星期六。您可以通过使用
DateUtils
中的函数来实现这一点。这将告诉您指定日期在一周中的哪一天

所以你的函数是这样的:

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;
这是实现你目标的一种相当粗糙的方式。您可以在这里找到更有趣的想法:


现在,在问题中,您建议从2016年1月1日起的7天(不包括周六)将您带到2016年1月9日。但这肯定是错误的,因为那天是星期六。正确答案肯定是2016年1月10日,也就是周日。换句话说,我们需要跳过两个星期六,即2号和9号。

使用DayOfWeek函数确定一周中的哪一天。现在你知道下周六是什么时候了,它是否会进入你的月经期。如果您的月经周期大于一周,那么您可以将月经周期中的周六数乘以整周数。如果您的月经周期大于7周,则必须每7周增加一天。

使用DayOfWeek函数确定一周中的哪一天。现在你知道下周六是什么时候了,它是否会进入你的月经期。如果您的月经周期大于一周,那么您可以将月经周期中的周六数乘以整周数。如果您的月经周期大于7周,则每7周您必须再增加一天。

这将为
ANumberOfDays
范围内的每个星期六的计算增加一天:

{.$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.
编辑

上面可能会返回星期六的日期,这取决于
不清楚你要问什么
条件定义。

这会为
ANumberOfDays
范围内的每个星期六的计算增加一天:

{.$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.
编辑

上面可能会返回周六的日期,这取决于
不清楚你要问什么
条件定义。

对于排除某个特定工作日的特殊情况,你已经得到了几个答案。这不是特别灵活

您可以尝试实现一个函数,该函数将一组“有效”的工作日作为其参数之一。增加日期的天数约为
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;
类型
TValidDateFunc=函数(ADate:TDateTime):布尔值;
函数IncValidDays(astardate:TDateTime;AIncBy:Integer;AIsValid:TValidDateFunc):TDateTime;
变量
LINC方向:整数;
开始
//使用负AIncBy支持dec
如果AIncBy>=0,则
LINC方向:=1
其他的
LINC方向:=-1;
结果:=astardate;
而(AIncBy 0)呢
开始
IncDay(结果、关键方向);
如果(结果)有效,则
Dec(林卡方向的AIncBy);
结束;
结束;
现在,您可以简单地编写您想要确定有效日期的任何函数,并在上述函数中使用它。例如

function DateNotSaturday(ADate: TDateTime): Boolean;
begin
  Result := (DayOfTheWeek(ADate) <> DaySaturday);
end;


NewDate := IncValidDays(SomeDate, 10, DateNotSaturday);
函数DateNotSaturday(ADate:TDateTime):布尔值;
开始
结果:=(星期一(ADate)星期六);
结束;
NewDate:=IncValidDays(SomeDate,10,DateNotSaturday);
注意,现在编写一个只使用非公共假日的工作日的函数变得非常容易。例如

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;
函数IsWorkDay(ADate:TDateTime):布尔值;
变量
第一天,第二个月,第二天:单词;
开始
解码日期(日期、月、月、日);
结果:=真;
结果:=结果和(星期一(ADate)星期六);
结果:=结果和(星期日(ADate)DAYSTANDY);
结果:=结果和((第1天)或(第1个月))//不包括元旦。
...
结束;
这种方法的最大优点是,你不必处理“双重忽略”日期的风险,因为它既是周末又是公共假日

注意:在Delphi的最新版本中,可以用匿名方法替换回调函数


对于排除单个特定工作日的特殊情况,您已经得到了几个答案。这不是特别灵活

您可以尝试实现一个函数,该函数将一组“有效”的工作日作为其参数之一。增加日期的天数约为
AIncBy