يطرح زمن دلفي من نطاق تاريخ ، وحساب الوقت المتبقي

StackOverflow https://stackoverflow.com/questions/2588964

سؤال

أنا أبحث عن خوارزمية ستساعد في حساب طول وقت عمل يوم العمل. سيكون له نطاق تاريخ إدخال ، ثم يسمح بطرح شرائح نطاق زمنية تقاطع جزئيًا أو تمامًا من هذا النطاق التاريخ ، وستكون النتيجة هي عدد الدقائق (أو الكسر/مضاعف اليوم) في النطاق التاريخ الأصلي ، بعد طرحه خارج مختلف شرائح الوقت غير العمل.

علي سبيل المثال:

نطاق تاريخ الإدخال: 1/4/2010 11:21 صباحًا - 1/5/2010 3:00 مساءً
قم بطرح أي شرائح متقاطعة جزئيًا أو تمامًا مثل هذا:
أخرج كل يوم الأحد
غير المدعي إزالة 11:00 - 12:00
غير المدعي إزالة الوقت بعد الساعة 5:00 مساء
غير مدفات تزيل الوقت قبل الساعة 8:00 صباحًا
لا يزيل يوم غير مدافع الوقت 9:15 - 9:30 صباحًا
الإخراج: # من الدقائق المتبقية في نطاق تاريخ الإدخال

لا أحتاج إلى أي شيء مفرط عام. يمكنني ترميز القواعد لتبسيط الكود. إذا كان أي شخص يعرف عينة رمز أو مكتبة/وظيفة في مكان ما ، أو لديه بعض الأفكار الزائفة ، فأنا أحب شيئًا لتبدأ به. لم أر أي شيء في DateUtils ، على سبيل المثال. حتى الوظيفة الأساسية التي تحسب عدد دقائق التداخل في نطاقات التاريخ لطرحها ستكون بداية جيدة.

هل كانت مفيدة؟

المحلول

متطلبات مثيرة للاهتمام ... ولكن ليس من الصعب تحقيقها بطريقة "متشددين".

يتمتع

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;

نصائح أخرى

ما عليك سوى استخدام الروتين في DateUtils وأماكن أخرى لتنفيذ القواعد التي تصفها بنفسك.

إذا كنت تريد أن تبدأ فكرة عنك ، فأنا أقترح على الكفة حساب الدقائق في نطاق الإدخال الخاص بك (تذكر أن قيمة tdatetime هي نقطة عائمة حيث تكون القيمة المتكاملة هي عدد الأيام والجزء الكسري هو جزء من اليوم) ثم زيادة النطاق ولكل خطوة عدد صحيح (اليوم) قم بطرح العدد المناسب من الدقائق لهذا اليوم من المجموع بناءً على قواعدك وبدء/نهاية الأيام الأولى/الأخيرة في النطاق عندما تتم مواجهة تلك الأيام في النطاق (الأيام المتداخلة التي تتم بالطبع على مدار 24 ساعة).

حقًا لتوفير أي "مخطط تفصيلي" أكثر تفصيلاً ، قد يقوم المرء بتنفيذ الروتين الكامل لك ، وهو ما قد أفعله إذا كان لدي المزيد من الوقت ، وهو أمر للأسف لا أفعله الآن.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top