Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从日期范围中减去Delphi时间范围,计算剩余时间_Delphi_Date_Range_Overlap_Intersect - Fatal编程技术网

从日期范围中减去Delphi时间范围,计算剩余时间

从日期范围中减去Delphi时间范围,计算剩余时间,delphi,date,range,overlap,intersect,Delphi,Date,Range,Overlap,Intersect,我正在寻找一个算法,将有助于计算一个工作日的工作时间长度。它将有一个输入日期范围,然后允许从该日期范围中减去部分或完全相交的时间范围切片,结果将是减去各种非工作时间切片后,原始日期范围中剩余的分钟数(或一天的分数/倍数) 例如: 输入日期范围:2010年4月1日上午11:21-2010年5月1日下午3:00 减去任何部分或完全相交的切片,如下所示: 删除全天星期日 非周日取消11:00-12:00 非星期日下午5:00后的移除时间 非星期日上午8:00之前的搬迁时间 非星期日搬迁时间上午9:15

我正在寻找一个算法,将有助于计算一个工作日的工作时间长度。它将有一个输入日期范围,然后允许从该日期范围中减去部分或完全相交的时间范围切片,结果将是减去各种非工作时间切片后,原始日期范围中剩余的分钟数(或一天的分数/倍数)

例如:

输入日期范围:2010年4月1日上午11:21-2010年5月1日下午3:00
减去任何部分或完全相交的切片,如下所示:
删除全天星期日
非周日取消11:00-12:00
非星期日下午5:00后的移除时间
非星期日上午8:00之前的搬迁时间
非星期日搬迁时间上午9:15-9:30
输出:#输入日期范围内剩余的分钟数


我不需要任何过于笼统的东西。我可以硬编码规则来简化代码。如果有人知道某个地方的示例代码或库/函数,或者有一些伪代码的想法,我想从一些东西开始。例如,我在DateUtils中没有看到任何东西。即使是计算两个日期范围内要减去的重叠分钟数的基本函数也是一个好的开始。

只需使用DateUtils和其他地方的例程即可实现您自己描述的规则

如果你想要一个开始的想法,我建议立即计算输入范围内的分钟数(记住TDateTime值是一个浮点数,其中整数值是天数,小数部分是一天的一部分),然后在整个范围内递增,并针对每个整步(天)根据您的规则和该范围内第一天/最后一天的开始/结束时间,从总分钟数中减去该天的适当分钟数(中间几天当然是完整的24小时周期)


要提供更详细的“大纲”,不妨为您实现完整的例程,如果我有更多的时间,我可能会这样做,但遗憾的是,我现在没有。

有趣的需求。。。但以“硬编码”的方式实现并不难

享受


我在DateUtils中没有看到任何特定的例程,这些例程看起来对相交/切片日期范围或类似的事情很有用。如果有人知道任何特定的RTL或第三方例程,我洗耳恭听。我不是德尔福专家,所以我很可能遗漏了什么。我想我可以假设要减去的片段彼此不相交(如果我正确定义了规则),这似乎简化了一些实现。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;