Subtrair o tempo Delphi varia de um intervalo de data, calcule o tempo restante
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.
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.