Как рассчитать количество рабочих дней между двумя датами?
Мне нужно рассчитать количество рабочих дней (рабочих дней) между двумя заданными датами. Рабочие дни - это дни недели, кроме субботы и воскресенья. Я не рассматриваю праздники в этом списке.
Как рассчитать количество рабочих дней между двумя датами?
Ответы
Ответ 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;