【问题标题】:Date overlapping: generalized way to split the dates to get the overlapping interval?日期重叠:分割日期以获得重叠间隔的通用方法?
【发布时间】:2020-06-22 12:56:04
【问题描述】:

假设我们有两个日期间隔:

A-------------B
       C-------------------------D

其中AC 是开始日期,BD 是日期间隔ABCD 的结束日期。

我发现如果(B+D)>=(A+C) 我们有日期重叠。但是如果(B+D)<(A+C),我们没有日期重叠。

我一直在寻找的东西,但没有成功,它找出了一个通用算法,该算法将日期间隔AB 的拆分集返回给我。在上述情况下,AB 的拆分集将是:

A----------(C-1) 'I mean, begining date of interval CD diminished by one day
C----------B     'The actual date overlapping

我不是在寻找一种可以测试所有可能情况的算法,而是一种适用于任何情况的通用算法。

这个算法存在吗?我真的很感激任何帮助!!!

我能弄清楚的所有情况是(但我不确定是否是其他情况):

A---------------B
    C--------------------D

             A---------------B
C--------------------D

A---------------B
    C------D

    A------B
C---------------D

A---------------B
C---------------D

      A--------B
C--------------D

A--------------B
     C---------D

A--------------B
C-------D

A-------B
C--------------D

编辑

根据 Gary 的学生出色的选择答案,我能够弄清楚我需要的功能,如下所示。我不需要知道结果 inverval 的拆分集中的哪一个区间是重叠的,但是通过函数的一些更改,这很容易实现。

Sub Test()
arr = fSplitOverlap( _
DateSerial(2020, 3, 1), DateSerial(2020, 3, 31), _
DateSerial(2020, 3, 1), DateSerial(2020, 3, 10))
For i = LBound(arr) To UBound(arr) Step 2
    Debug.Print arr(i), arr(i + 1)
Next i
End Sub


Function fSplitOverlap(ByVal Di1 As Date, ByVal Df1 As Date, _
ByVal Di2 As Date, ByVal Df2 As Date) As Variant

Dim arr() As Date

Dim DiOver As Date, DfOver As Date
Dim HaveFirsDisjoint1 As Boolean: HaveFirsDisjoint1 = False
DiOver = Application.WorksheetFunction.Max(Di1, Di2)
DfOver = Application.WorksheetFunction.Min(Df1, Df2)

'TEST OVERLAP
If DateDiff("d", DiOver, DfOver) >= 0 Then

    'TEST FIRST POSSIBLE DISJOINT INVERVAL
    If DateDiff("d", Di1, DateAdd("d", -1, DiOver)) >= 0 Then
        ReDim Preserve arr(1 To 4)
        arr(1) = Di1
        arr(2) = DateAdd("d", -1, DiOver)
        arr(3) = DiOver
        arr(4) = DfOver
        HaveFirsDisjoint1 = True
    End If

    'TEST SECOND POSSIBLE DISJOINT INVERVAL
    If DateDiff("d", DateAdd("d", 1, DfOver), Df1) >= 0 Then
        If HaveFirsDisjoint1 = True Then
            ReDim Preserve arr(1 To 6)
            arr(1) = Di1
            arr(2) = DateAdd("d", -1, DiOver)
            arr(3) = DiOver
            arr(4) = DfOver
            arr(5) = DateAdd("d", 1, DfOver)
            arr(6) = Df1
        Else
            ReDim Preserve arr(1 To 4)
            arr(1) = DiOver
            arr(2) = DfOver
            arr(3) = DateAdd("d", 1, DfOver)
            arr(4) = Df1
        End If
    End If

End If

fSplitOverlap = arr

End Function

【问题讨论】:

  • 您说您不想测试“所有可能的情况”,但您需要处理“任何情况”。有什么区别?
  • 你好@TimWilliams!我不知道如何用英语更好地表达自己,但我一直在寻找由所选答案提供的普遍推理,而不是逐一检查我列出的每个可能案例,以及未列出的其他可能案例。

标签: excel vba algorithm date data-structures


【解决方案1】:

从您的图片中可以清楚地看出,如果 A>DC>B 则这些区域是不相交的

否则重叠将是MIN(B,D) - MAX(A,C) + 1

所以在 VBA 中:

Sub Overlap()
    Dim A As Date, B As Date, C As Date, D As Date

    A = DateValue("1/11/2020")
    B = DateValue("1/20/2020")
    C = DateValue("1/15/2020")
    D = DateValue("2/13/2020")

    If A > D Or C > B Then
        MsgBox "no overlap"
        Exit Sub
    End If
    With Application.WorksheetFunction
        MsgBox .Min(B, D) - .Max(A, C) + 1
    End With
End Sub

这里的重叠是:

  1. 1/15
  2. 1/16
  3. 1/17
  4. 1/18
  5. 1/19
  6. 1/20

【讨论】:

  • 非常感谢您向我们展示了有关重叠日期间隔的一般推理!我根据您的回答编辑了我的文字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 2011-02-03
  • 2021-09-21
  • 1970-01-01
  • 2021-12-24
相关资源
最近更新 更多