Как рассчитать количество рабочих дней между двумя датами?

Мне нужно рассчитать количество рабочих дней (рабочих дней) между двумя заданными датами. Рабочие дни - это дни недели, кроме субботы и воскресенья. Я не рассматриваю праздники в этом списке.

Как рассчитать количество рабочих дней между двумя датами?

Ответ 1

Вам нужно использовать 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;

Вы можете немного улучшить это, не беспокоясь о порядке параметров (другими словами, не имеет значения, будет ли начало до конца или конца перед запуском, функция все равно будет работать):

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;

Ответ 2

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;

Обычная BusinessDaysSinceFixedDate вычисляет количество рабочих дней с фиксированной даты. Конкретная дата, которая не имеет значения, - понедельник, 25 декабря 1899 года. Он просто подсчитывает количество прошедших недель (X div 7) и умножает на 5. Затем он добавляет смещение для корректировки в зависимости от дня недели. Обратите внимание, что (X mod 7) вернет отрицательное значение для отрицательной даты, то есть даты до 30 декабря 1899 года.

Обычная BusinessDaysBetweenDates просто вызывает BusinessDaysSinceFixedDate для даты начала и окончания и вычитает один из другого.

Ответ 3

Без циклизации всех дней и входных параметров, не зависящих от порядка.

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;