Вычитание Delphi Time варьируется от диапазона даты, рассчитайте оставшееся время

StackOverflow https://stackoverflow.com/questions/2588964

Вопрос

Я ищу алгоритм, который поможет рассчитать длину рабочего времени рабочего дня. Он будет иметь диапазон дат ввода, а затем разрешить вычитание частично или полностью пересекающихся кусочки диапазона времени в течение даты, и результат будет иметь количество минут (или фракция / краткий день), оставленные в исходном диапазоне даты после вычитания из различных ломтиков неработающего времени.

Например:

Диапазон даты ввода: 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-часовые периоды).

Действительно, чтобы предоставить еще более подробную «наброску», который может также реализовать полную рутину для вас, что я мог бы сделать, если у меня было больше времени, что к сожалению, я сейчас не сейчас.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top