【问题标题】:Get breaks from a list of times从时间列表中获取休息时间
【发布时间】:2013-04-30 09:09:04
【问题描述】:

我有一个工作项目列表。每个工作项都有开始和结束时间。

所以,基本上是这样的:

List<Work> works = new List<Work>();
works.Add(new Work(
  new DateTime(2013, 4, 30, 9, 0, 0),
  new DateTime(2013, 4, 30, 11, 0, 0));

现在我想得到工作的总时间。同样,基本上这很容易:

09:00-11:00 => 2 hours
13:00-17:00 => 4 hours
----
06:00 hours

这只是总和。

但现在变得很困难:如果我想提取并行时间,我该如何计算这个总和?

例如,

09:00-11:00 => 2 hours
10:00-11:30 => 1.5 hours
13:00-17:00 => 4 hours
----
06:30 hours

是 6.5 小时,但总和是 7.5 小时。两个工作项映射到 10 点到 11 点之间的时间这一事实有所不同。

对于可以以基本上所有可能的方式(周围、开始重叠、结束重叠,包括)相互重叠的任意数量的工作项,我该如何解决这个问题?

【问题讨论】:

  • 是否有设定的时间间隔(例如,最短 0.5 小时)?如果是这样,一个简单的方法是每半小时检查一次围绕它的工作项,然后将它们全部加起来。
  • 很遗憾,时间完全是任意的,可能从几秒到几天不等。
  • 我现在使用这个库解决了这个问题:简单,直接,并且可以工作:-)
  • 作为一个实际问题,也要注意模棱两可的时间。您使用的DateTime 值具有.Kind == Unspecified。如果这些来自 UTC,你就可以了。如果它们来自某个本地时区,那么在穿越夏令时转换时,您的数学可能会出错。如果你不能使用 UTC,你应该使用 DateTimeOffset 来代替。一般来说,“未指定”或“本地”DateTime 值对于数学来说是不安全的。

标签: c# algorithm datetime time timespan


【解决方案1】:

创建 (time, value) 对,其中 value 为 +1 表示工作开始,-1 表示结束。然后按日期对对进行排序。迭代你得到的列表,你可以计算值的总和——当它是正数时,工作正在“继续”。在迭代时,标记值总和从 0 变为正数和从正数变为 0 的时刻。您将得到不相交的区间。

例子:

11 - 13, 12 - 16, 15 - 17, 18 - 19

给你 (11, 1) (12, 1) (13 -1) (15, 1) (16, -1) (17, -1) (18, 1) (19, -1)

总和为 (11, 1) (12, 2) (13 1) (15, 2) (16, 1) (17, 0) (18, 1) (19, 0),

所以不相交的周期是 (11, 17) 和 (18, 19)

【讨论】:

  • 示例代码:pastebin.com/KnhRwrsX 如果需要,请随时编辑您的答案。
  • 我实现了它,它运行良好 :-) 感谢您的提示!
  • 感谢您的示例,我看到这个为时已晚,但现在我将比较您的解决方案和我的解决方案,并充分利用两者:-))
【解决方案2】:

嗯,我曾经解决过类似的问题(不是时间,而是范围重叠)。我应用的解决方案非常简单:

  1. 按升序对元素进行排序
  2. 从第一个元素开始,看是否与下一个元素重叠
  3. 如果是 - 重新处理元素,将重叠部分提取为新元素,将旧元素修改为在重叠期之前/之后结束
  4. 在两个旧元素之间插入新创建的元素
  5. 继续处理

它应该可以正常工作,但是如果您有大量数据,可能会有更好的方法来解决它。这只是最简单的方法(至少对我而言)。您最终将获得没有重叠部分的时间列表,因此您将能够迭代列表并总结时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    相关资源
    最近更新 更多