Question

Je cherche un algorithme qui vous aider à calculer une longueur du temps de travail journée de travail. Il aurait une plage de dates d'entrée et permettent la soustraction plage de temps intersection partiellement ou complètement les tranches de cette plage de dates et le résultat serait le nombre de minutes (ou la fraction / multiple d'un jour) à gauche dans la plage de dates d'origine, après soustraction les différentes tranches de temps non-travail.

Par exemple:

plage de dates d'entrée: 1/4/2010 11:21 - 1/5/2010 15h00
Soustrayez les tranches comme intersection partiellement ou complètement ceci:
Retirer toute la journée dimanche
Non-dimanche supprimer 11h00-12h00
Non-dimanche supprimer après 17h00
Non-dimanche supprimer avant 8h00
Non-dimanche supprimer le temps 09 heures 15-à-9:30
Sortie: Nombre de minutes dans la plage de dates d'entrée

Je ne ai besoin de rien trop général. Je pourrais hardcode les règles pour simplifier le code. Si quelqu'un connaît un exemple de code ou une bibliothèque / fonction quelque part, ou a quelques idées pseudo-code, j'aimerais quelque chose pour commencer. Je ne vois rien dans DateUtils, par exemple. Même une fonction de base qui calcule le nombre de minutes de chevauchement entre deux plages de dates pour soustrayez serait un bon point de départ.

Était-ce utile?

La solution

exigences intéressantes ... Mais pas si difficile à atteindre d'une manière « hardcoded ».

Profitez

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;

Autres conseils

Il suffit d'utiliser les routines DateUtils et ailleurs pour mettre en œuvre les règles que vous vous décrivez.

Si vous voulez une idée pour vous lancer, au large de la manchette, je vous suggère de calculer les minutes dans votre plage d'entrée (se rappelant qu'une valeur TDateTime est un point flottant où la valeur intégrale est le nombre de jours et la partie décimale est une partie d'un jour) incrémenter ensuite à travers l'intervalle et pour chaque étape de nombre entier (de jour) soustraire le nombre approprié de minutes pour ce jour-là par rapport au total sur la base de vos règles et le début / la fin des temps de la première / dernière jours à la plage lorsque ces jours sont rencontrés dans l'intervalle (intervention jours étant bien entendu complets périodes de 24 heures).

Vraiment de fournir des « grandes lignes », on pourrait aussi mettre en œuvre bien plus détaillée la routine complète pour vous, que je pourrais faire si j'avais plus de temps, ce qui malheureusement je ne pas en ce moment.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top