Pregunta

Estoy buscando un algoritmo que le ayudará a calcular una duración de tiempo de trabajo jornada de trabajo. Tendría un intervalo de fechas de entrada y luego permitir restando parcial o intersección completamente rebanadas de intervalo de tiempo a partir de ese intervalo de fecha y el resultado sería el número de minutos (o la fracción / múltiple de un día) a la izquierda en el intervalo de fechas original, después de restar a cabo las diversas rodajas que no trabajan de tiempo.

Por ejemplo:

rango de fechas de entrada: 1/4/2010 11:21 - 1/5/2010 15:00
Restar algún segmento de intersección parcial o totalmente como este:
Retire todo el domingo
No quite domingos 11:00-12:00
No domingos Retire después de 5:00 PM
No domingos Retire antes de las 8:00
-domingos no Retire las 09:15-media después de las nueve de la mañana
Salida: Número de minutos restantes en el intervalo de fechas de entrada

No necesito nada demasiado general. Podría codificar las reglas para simplificar el código. Si alguien sabe de código de ejemplo en alguna parte o una biblioteca / función, o tiene algunas ideas pseudo-código, me gustaría algo para empezar. No vi nada en DateUtils, por ejemplo. Incluso una función básica que calcula el número de minutos de la superposición de dos intervalos de tiempo para restar a cabo sería un comienzo bueno.

¿Fue útil?

Solución

requisitos interesantes ... Pero no es tan difícil de lograr en una forma "hardcoded".

Disfrute

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;

Otros consejos

Simplemente utilizar las rutinas de DateUtils y otros países para poner en práctica las reglas que usted describe.

Si quieres una idea para empezar, fruto de la casualidad me gustaría sugerir el cálculo de los minutos en su rango de entrada (recordando que un valor TDateTime es un punto flotante en el que el valor de la integral es el número de días y la parte fraccionaria es una parte de un día), entonces incrementar a través de la gama y para cada paso entero (días) restar el número apropiado de minutos para ese día del total en base a sus reglas y el inicio / final de los tiempos de los primeros últimos días / IN la gama cuando esos días se encuentran en el intervalo (días intermedios ser de períodos curso completo de 24 horas).

En serio para proporcionar cualquier "esquema" más detallado se podría también aplicar la rutina completa para usted, lo que podría hacer si tuviera más tiempo, lo que por desgracia no lo hago en este momento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top