Date Range Overlap with Nullable Dates
我在找一个问题的扩展答案:
确定两个日期范围是否重叠
其中任一日期范围内的任何日期都可以为空。我已经提出了以下解决方案,但我不确定是否可以进一步简化。
1 2 3 4 | (StartA == NULL || StartA <= EndB) && (EndA == NULL || EndA >= StartB) && (StartB == NULL || StartB <= EndA) && (EndB == NULL || EndB >= StartA) |
假设:
从starta到enda和startb到endb的日期时间范围
编辑:对不起,我很快就把上面的逻辑拼凑在一起了,当范围的开始日期和结束日期都为空时,这看起来是失败的。请参阅下面的David解决方案,以获得更好且解释清楚的方法。
这一案件可以通过对查尔斯·布雷塔纳对这个问题的完美答案的一点概括来处理。
0在这种情况下,假设您希望一个空日期表示"没有开始/结束限制",那么条件将被修改。例如,对于
1 | CondA := (StartA != null) && (EndB != null) && (StartA > EndB) |
1 | CondB := (StartB != null) && (EndA != null) && (StartB > EndA) |
持续的,
Then Overlap exists if Neither A Nor B is true
2
和
Now deMorgan's law, I think it is, says that
Not (A Or B) <=> Not A And Not B
1 2 3 4 5 | Overlap == !CondA && !CondB == ![(StartA != null) && (EndB != null) && (StartA > EndB)] && ![(StartB != null) && (EndA != null) && (StartB > EndA)] == [(StartA == null) || (EndB == null) || (StartA <= EndB)] && [(StartB == null) || (EndA == null) || (StartB <= EndA)] |
我认为这实际上比你开发的解决方案更为强大,因为如果
不考虑空值,答案是
考虑到开始和结束日期为空,使用C三元运算符语法:
或C 4.x样式的空运算符:
或在SQL中:
说明:考虑非空答案:
现在,考虑starta为空,表示日期范围A自时间开始(bot)以来就存在。在这种情况下,daterageb不能早于dateragea。因此,第一个条件(starta(bot)<=endb)将始终为真,无论endb是什么。因此,更改此表达式,以便在starta为空时,将endb与自身进行比较,而不是将null与endb进行比较无论endb是什么,表达式
对其他三个输入变量执行相同的操作。
如果条件是真的,所有答案都是根据。我想在这里添加一些注释。
1-datetime变量类型是一个结构,除非使用"datetime?"之类的可空类型,否则不能将其设置为空。
2-要查找重叠范围,请执行以下步骤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | DateTime? StartOverLap = null,EndOverLap = null; if (StartA != null && StartB != null) { StartOverLap = StartA > StartB ? StartA : StartB; } else if (StartA == null && StartB != null) { StartOverLap = StartB; } else if (StartA != null && StartB == null) { StartOverLap = StartA; } if (EndA != null && EndB != null) { EndOverLap = EndA < EndB ? EndA : EndB; } else if (EndA == null && EndB != null) { EndOverLap = EndB; } else if (EndA != null && EndB == null) { EndOverLap = EndA; } if (StartOverLap != null && EndOverLap == null) { if (EndOverLap < StartOverLap) { StartOverLap = null; EndOverLap = null; } } |
这可能是"简单"的,因为你可以得到它,虽然我还没有真正证明它。
进一步简化可能是不值得的,因为在最坏的情况下,该块最终会有8个操作(由于短路评估,平均为4个)。