Domanda

Sto cercando un algoritmo che aiuterà calcolare una lunghezza di tempo giornata lavorativa di lavoro. Avrebbe un intervallo di date di ingresso e quindi consentire sottraendo parzialmente o interseca completamente intervallo intervalli di tempo da tale intervallo data e il risultato sarebbe il numero di minuti (o la frazione / multiplo di un giorno) sinistra nell'intervallo data originale, dopo aver sottratto le varie fette che non lavorano a tempo.

Ad esempio:

intervallo di date di ingresso: 1/4/2010 11:21 - 1/5/2010 15:00
Sottrarre eventuali fette parzialmente o completamente intersecano come questo:
Rimuovere tutto il giorno Domenica
Non-domenica remove 11:00-12:00
Non-domenica tempo rimuovere dopo 5:00
Non-domenica tempo rimuovere prima delle 8:00
-domenica non tempo remove 9:15-09:30
Uscita: # di minuti dalla fine l'intervallo di date di ingresso

Non ho bisogno di niente di eccessivamente generale. Potrei hardcode le regole per semplificare il codice. Se qualcuno sa di codice di esempio o di una libreria / funzione da qualche parte, o ha qualche idea pseudo-codice, mi piacerebbe qualcosa da cui partire. Non ho visto nulla in DateUtils, per esempio. Anche una funzione di base che calcola il numero di minuti di sovrapposizione in due intervalli di date per sottrarre fuori sarebbe un buon inizio.

È stato utile?

Soluzione

requisiti interessanti ... Ma non è così difficile da raggiungere in modo "hardcoded".

Godetevi

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;

Altri suggerimenti

È sufficiente utilizzare le routine in DateUtils e altrove, per attuare le norme ti descrivi.

Se volete un'idea per iniziare, a braccio Io suggerirei di calcolo dei minuti nel vostro range di ingresso (ricordando che un valore TDateTime è un punto galleggiante dove il valore integrale è il numero di giorni e la parte frazionaria è una porzione di un giorno) quindi incrementare attraverso la gamma e per ogni passo intero (giorno) sottrarre il numero appropriato di minuti per quel giorno dal totale basato su regole e l'inizio / fine tempo dei primi / ultimi giorni in la gamma quando si verificano quei giorni nell'intervallo (giorni intermedi essendo naturalmente periodi completi di 24 ore).

In realtà per fornire più dettagliato "contorno" si potrebbe anche implementare la routine completa per voi, che potrei fare se avessi avuto più tempo, che purtroppo io non al momento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top