Pergunta

Estou procurando um algoritmo que ajudará a calcular uma duração do tempo de trabalho do dia de trabalho. Ele teria um intervalo de data de entrada e, em seguida, permitiria subtrair as fatias de intervalo de tempo parcial ou completamente cruzadas a partir desse intervalo de data e o resultado seria o número de minutos (ou a fração/múltiplo de um dia) deixada no intervalo original, após subtrair fora das várias fatias de tempo que não funcionam.

Por exemplo:

Data de entrada: 1/4/2010 11:21 - 1/5/2010 15:00
Subtraia quaisquer fatias parcial ou completamente cruzadas como esta:
Remova o dia todo domingo
Não renda removidos 11:00 - 12:00
Os não sucessos removem o tempo após as 17:00
Os não sucessos removem o tempo antes das 8:00 da manhã
Não rendados Remove o tempo das 9:15 - 9:30
Saída: # de minutos restantes na data de entrada

Eu não preciso de nada excessivamente general. Eu poderia codificar as regras para simplificar o código. Se alguém souber do código de amostra ou de uma biblioteca/função em algum lugar, ou tiver algumas idéias de pseudo-código, eu adoraria algo para começar. Não vi nada em DateUtils, por exemplo. Mesmo uma função básica que calcula o número de minutos de sobreposição em duas faixas de data para subtrair seria um bom começo.

Foi útil?

Solução

Requisitos interessantes ... mas não tão difíceis de alcançar de uma maneira "codificada".

Apreciar

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;

Outras dicas

Basta usar as rotinas nos DateUtils e em outros lugares para implementar as regras que você descreve.

Se você deseja uma idéia para começar, fora do manguito, eu sugiro calcular as atas no seu intervalo de entrada (lembrando que um valor tdateTime é um ponto flutuante em que o valor integral é o número de dias e a parte fracionária é uma parte de um dia) depois incrementar através do intervalo e para cada etapa inteira (dia) subtrair o número apropriado de minutos para esse dia a partir do total com base nas suas regras e no horário inicial/final dos primeiros/últimos dias no intervalo quando Esses dias são encontrados no intervalo (é claro que os dias intermediários estão obviamente completos de 24 horas).

Realmente, para fornecer um "esboço" mais detalhado, pode -se implementar a rotina completa para você, o que eu poderia fazer se tivesse mais tempo, o que, infelizmente, eu não agora.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top