如何计算两个日期之间的工作日数?

Sar*_*kar 12 delphi delphi-xe2

我需要计算两个给定日期之间的工作日(工作日)数.工作日是一周中的所有日子,周六和周日除外.我不打算考虑假期.

如何计算两个日期之间的工作日数?

Dav*_*ois 13

function BusinessDaysSinceFixedDate ( const nDate : tDateTime ) : integer;
const
  Map : array [ -6 .. 6 ] of integer
      = (  0, 0, 1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 9 ); 
var
  X : integer;
begin
  X := trunc ( nDate );
  Result := 5 * ( X div 7 ) + Map [ X mod 7 ];
end;

function BusinessDaysBetweenDates ( const nStartDate : tDateTime;
                                    const nEndDate   : tDateTime ) : integer;
begin
  Result :=   BusinessDaysSinceFixedDate ( nEndDate )
            - BusinessDaysSinceFixedDate ( nStartDate );
end;
Run Code Online (Sandbox Code Playgroud)

例程BusinessDaysSinceFixedDate计算自固定日期以来的工作日数.具体日期是无关紧要的,是1899年12月25日星期一.它只计算已经过的周数(X div 7)并将其乘以5.然后它根据日期加上一个偏移量来纠正.周.请注意,(X mod 7)将为负数日期返回负值,即1899年12月30日之前的日期.

例程BusinessDaysBetweenDates只调用BusinessDaysSinceFixedDate作为开始日期和结束日期,并从另一个日期中减去一个.

  • +1.您可以将`Abs`添加到`BusinessDaysBetweenDates`的结果中(因此Days的结果将始终为正). (4认同)

LU *_* RD 12

没有循环所有日子和输入参数不依赖于顺序.

Uses DateUtils,Math;

function WorkingDaysBetween( const firstDate,secondDate : TDateTime) : Integer;
var
  startDate,stopDate : TDateTime;
  startDow,stopDow : Integer;
begin
  if (firstDate < secondDate) then
  begin
    startDate := firstDate;
    stopDate := secondDate;
  end
  else
  begin
    startDate := secondDate;
    stopDate := firstDate;
  end; 
  startDow := DayOfTheWeek(startDate);
  stopDow := DayOfTheWeek(stopDate);
  if (stopDow >= startDow) then
    stopDow := Min(stopDow,6)
  else
    Inc(stopDow,5); 

  Result := 
    5*WeeksBetween(stopDate,startDate) + 
    (stopDow - Min(startDow,6));
end;
Run Code Online (Sandbox Code Playgroud)

  • @kobik,谢谢.正确的日期编号功能当然是"DayOfTheWeek()". (5认同)
  • 如果我测试`dt1:= Now`和`dt2:= IncYear(Now,3)`,我会得到与你的函数不同的其他两个结果. (4认同)
  • +1.太好了!我没有机会看到一个非循环解决方案 - 现在我绝对不需要这样做.:-) (3认同)

Ken*_*ite 9

您需要使用DayOfTheWeek(从DateUtils单位)和计数器,从开始日期到结束日期迭代.(你也可能需要一个假期表,也可以从你的计数中排除那些.)

function BusinessDaysBetween(const StartDate, EndDate: TDateTime): Integer;
var
  CurrDate : TDateTime;
begin
  CurrDate := StartDate;
  Result := 0;
  while (CurrDate <= EndDate) do
  begin
    // DayOfTheWeek returns 1-5 for Mon-Fri, so 6 and 7 are weekends
    if DayOfTheWeek(CurrDate) < 6 then
      Inc(Result);
    CurrDate := CurrDate + 1;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

你可以通过不担心参数的顺序来增强这一点(换句话说,如果start在结束之前或结束之前是开始之前,那么函数仍然有效):

function BusinessDaysBetween(const FirstDate, SecondDate: TDateTime): Integer;
var
  CurrDate : TDateTime;
  StartDate, EndDate: TDateTime;
begin
  if SecondDate > FirstDate then
  begin
    StartDate := FirstDate;
    EndDate := SecondDate;
  end
  else
  begin
    StartDate := SecondDate;
    EndDate := FirstDate;
  end;

  CurrDate := StartDate;
  Result := 0;

  while (CurrDate <= EndDate) do
  begin
    if DayOfTheWeek(CurrDate) < 6 then
      Inc(Result);
    CurrDate := CurrDate + 1;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

  • 没有循环就可以做到这一点. (7认同)