Вычитание Delphi Time варьируется от диапазона даты, рассчитайте оставшееся время
Вопрос
Я ищу алгоритм, который поможет рассчитать длину рабочего времени рабочего дня. Он будет иметь диапазон дат ввода, а затем разрешить вычитание частично или полностью пересекающихся кусочки диапазона времени в течение даты, и результат будет иметь количество минут (или фракция / краткий день), оставленные в исходном диапазоне даты после вычитания из различных ломтиков неработающего времени.
Например:
Диапазон даты ввода: 1/4/2010 11:21 утра - 1/5/2010 3:00 вечера
Вычитайте любые частично или полностью пересекающиеся срезы, такие как это:
Удалить весь день воскресенье
Non-Groundays Удалить 11:00 - 12:00
Не воскресенье Удалить время после 5:00 вечера
Не воскресенье Удалить время до 8:00 утра
Не воскресенье Удалить время 9:15 - 9:30
Выход: # минуты, оставшиеся в диапазоне даты ввода
Мне не нужно ничего чрезмерно общего. Я мог бы жесткокодировать правила упростить код. Если кто-то знает о примерном коде или библиотеке / функции где-то, или имеет некоторые идеи псевдо-кода, я бы хотел что-то начать с. Например, я ничего не видел в Датеэтилях. Даже основная функция, которая рассчитывает количество минут перекрытия в два диапазонах даты, чтобы вычесть было бы хорошим началом.
Решение
Интересные требования ... но не так сложно достичь в «хардкодированном» пути.
Наслаждаться
uses
Math, DateUtils;
function TimeRangeOverlap(Range1Start, Range1Finish, Range2Start, Range2Finish : TDateTime) : TDateTime;
begin
Result := Max(Min(Range1Finish, Range2Finish) - Max(Range1Start, Range2Start), 0);
end;
function TotalTime(Start, Finish : TDateTime) : TDateTime;
var DayStart, DayFinish : TDateTime;
I : Integer;
begin
Result := 0;
for I := Floor(Start) to Floor(Finish) do //For each day in range;
begin
if DayOfWeek(I) = 1 then CONTINUE; //Remove all sundays.
DayStart := Max(Start, I); //Midnight on the start of the day, except on the first day;
DayFinish := Min(Finish, I + 1 - OneMillisecond); //Midnight minus 1 msec of the following day.
Result := Result + DayFinish - DayStart;
//Adjustment part
Result := Result - TimeRangeOverlap(DayStart, DayFinish, I + EncodeTime(11,00,00,00), I + EncodeTime(12,00,00,00)); //Remove time between 11:00 and 12:00
Result := Result - TimeRangeOverlap(DayStart, DayFinish, I + EncodeTime(17,00,00,00), I + 1); //Remove time after 5:00 PM
Result := Result - TimeRangeOverlap(DayStart, DayFinish, I , I + EncodeTime(8,00,00,00)); //Remove time after 8:00 AM
Result := Result - TimeRangeOverlap(DayStart, DayFinish, I + EncodeTime(9,15,00,00), I + EncodeTime(9,30,00,00)); //Remove time between 9:15 and 9:30
end;
end;
Другие советы
Просто используйте процедуры в DateutiLs и в других местах, чтобы реализовать правила, которые вы сами будете описывать.
Если вы хотите, чтобы идею начать вас запустить, выключить манжету, я бы предложил рассмотреть протокол в вашем входном диапазоне (вспоминать, что значение TDateTime - это точка с плавающей точкой, в которой интегральное значение - это количество дней, а дробная часть - это часть дна) затем увеличивать диапазон и для каждого целочисленного шага (день) вычтете соответствующее количество минут в течение этого дня от общего объема на основе ваших правил и времени начала / конца первых / последних дней в диапазоне, когда Эти дни встречаются в диапазоне (промежуточные дни, конечно, выполнены 24-часовые периоды).
Действительно, чтобы предоставить еще более подробную «наброску», который может также реализовать полную рутину для вас, что я мог бы сделать, если у меня было больше времени, что к сожалению, я сейчас не сейчас.