我正在寻找一种有助于计算工作日工作时间长度的算法。它将具有输入日期范围,然后允许从该日期范围中减去部分或完全相交的时间范围切片,结果将是在减去原始日期范围后剩余的分钟数(或一天的分数/倍数)各种非工作时间片。
例如:
输入日期范围:2010年1月4日上午11:21 - 2010年5月1日下午3:00
减去任何部分或完全相交的切片,如下所示:
周日全天取消
非星期日删除11:00 - 12:00
非星期日在下午5点之后删除时间
非星期日在上午8:00之前删除时间
非星期日取消时间9:15 - 9:30上午
输出:输入日期范围内剩余的分钟数
我不需要任何过于笼统的东西。我可以硬编码规则来简化代码。如果有人知道某个示例代码或库/函数,或者有一些伪代码的想法,我会喜欢一些东西。例如,我在DateUtils中没有看到任何内容。即使是计算两个日期范围内重叠分钟数的基本函数也是一个好的开始。
答案 0 :(得分:4)
有趣的要求......但并非如此难以以“硬编码”的方式实现。
享受
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;
答案 1 :(得分:1)
只需使用DateUtils和其他地方的例程来实现您自己描述的规则。
如果你想要一个想法让你开始,我会建议计算输入范围内的分钟数(记住TDateTime值是一个浮点,其中积分值是天数和小数部分是一天的一部分)然后通过范围递增,并且对于每个整数步骤(天),根据您的规则和第一天/最后一天的开始/结束时间从总计中减去当天的适当分钟数。在该范围内遇到那些日子的范围(干预日当然是完整的24小时)。
真的要提供更详细的“大纲”,你可以为你实现完整的例行程序,如果我有更多的时间,我可能会这样做,遗憾的是我现在还没有。