Language agnostic 日期范围与可为空的日期重叠

Language agnostic 日期范围与可为空的日期重叠,language-agnostic,datetime,math,Language Agnostic,Datetime,Math,我正在寻找这里所问问题的扩展答案: 其中任一日期范围内的任何日期都可以为空。我提出了以下解决方案,但我不确定是否可以进一步简化 (StartA == NULL || StartA <= EndB) && (EndA == NULL || EndA >= StartB) && (StartB == NULL || StartB <= EndA) && (EndB == NULL || EndB >= StartA) (St

我正在寻找这里所问问题的扩展答案:

其中任一日期范围内的任何日期都可以为空。我提出了以下解决方案,但我不确定是否可以进一步简化

(StartA == NULL || StartA <= EndB) &&
(EndA == NULL || EndA >= StartB) &&
(StartB == NULL || StartB <= EndA) &&
(EndB == NULL || EndB >= StartA)
(StartA==NULL | | StartA=StartB)&&
(StartB==NULL | | StartB=StartA)
假设:

StartA到EndA和StartB到EndB的日期时间范围


编辑:很抱歉,我很快把上面的逻辑放在了一起,当任何一个范围的开始日期和结束日期都为空时,这似乎失败了。请参阅下面David的解决方案,以获得更好的解释方法。

这可能是您能得到的最简单的解决方案,尽管我还没有实际证明它


可能不值得进一步简化,因为在最坏的情况下,该块最终大约是8个操作(由于短路评估,平均为4个)。

这种情况可以通过对该问题的稍微概括来处理

让CondA表示日期范围A完全在日期范围B之后(如果StartA>EndB则为True) 让CondB表示日期范围A完全早于日期范围B(如果EndA 在这种情况下,假设希望空日期表示“无开始/结束界限”,则会修改条件。例如,对于
CondA
,为了使日期范围A完全在日期范围B之后,日期范围A必须有一个定义的开始时间,日期范围B必须有一个定义的结束时间,并且A的开始时间必须在B的结束时间之后:

CondA := (StartA != null) && (EndB != null) && (StartA > EndB)
CondB
与A和B切换相同:

CondB := (StartB != null) && (EndA != null) && (StartB > EndA)
继续

如果A和B都不为真,则存在重叠

现在,我认为德摩根定律是这样说的

不是(A或B)不是A也不是B

重叠==!康达&!康德 == ![(StartA!=null)&&(EndB!=null)&&(StartA>EndB)]&& ![(StartB!=null)&&(EndA!=null)&&(StartB>EndA)]
==[(StartA==null)| |(EndB==null)| | |(StartA如果条件为真,则所有答案均以为基础。我想在此添加一些注释

1-变量类型是一个结构,您不能将其设置为null,除非您使用的是可为null的类型,如“DateTime?”

2-要查找重叠范围,请执行以下步骤

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;
                }
            }
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;
}
如果(EndA!=null&&EndB!=null)
{
EndOverLap=EndA
如果不考虑空值,答案是

(StartA=StartB)
(详细说明请参见)

考虑开始日期和结束日期为空,
使用C三元运算符语法:
(StartA!=null?StartA:EndB=StartB!=null?StartB:EndA)

或C#4.x样式的空运算符:

(StartA??EndB=StartB??EndA)

或在SQL中:


(合并(开始,结束)谢谢你的详细解释,David!是的,我在发布后很快就意识到我的初始解决方案失败了。这是一个很好的方法,就像deMorgan定律一样,但你不能将第二部分作为编程语句来实现,因为如果startA或EndB中的任何一个都等于null,那么比较运算符将失败。请尽量保持And{&}运算符,因为它在大多数新编译器中都会起短路作用。这在低和编程时都是正确的。![(StartA!=null)&&&&(EndB!=null)&&&(StartA>EndB)&[(StartB!=null)&&(EndA!=null)&(StartB>EndA)]@瓦利德:如果你说的是我的最后两行代码,那当然可以作为一个语句来实现。如果
startA
endB
等于
null
,这将被该条件的显式测试捕获,
如果startA为null,你将有一个错误,因为compare操作符不能与null。将所有的或门{Logic}转换为and{Logic},然后在开始时将所有的compare转换为null,从而重新组织语句,这样短路和{Logic}就可以工作了。
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)]
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;
                }
            }