代码之家  ›  专栏  ›  技术社区  ›  pgras

计算日期添加,但仅计算工作日

  •  3
  • pgras  · 技术社区  · 17 年前

    我想通过使用内置的dateadd函数简单地计算一个新的日期,但要考虑到只计算工作日(或者说“工作日”)。

    我提出了这个简单的算法,它不需要考虑假期之类的事情。我已经用一些简单的日期测试过了,但是如果可以用更好的方式来做的话,我想要一些输入。

    此示例假设一周有5个工作日,即周一至周五,其中一周的第一天是周一。此处使用的日期格式为d-m-yyyy,示例以2009年10月1日为起始日期进行计算。

    Dim d_StartDate As DateTime = "1-10-2009"
    Dim i_NumberOfDays As Integer = 12
    Dim i_CalculateNumberOfDays As Integer 
    
    If i_NumberOfDays > (5 - d_StartDate.DayOfWeek) Then
        i_CalculateNumberOfDays = i_NumberOfDays
    Else
        i_CalculateNumberOfDays = i_NumberOfDays + (Int(((i_NumberOfDays + (7 - d_StartDate.DayOfWeek)) / 5)) * 2)
    End If
    
    MsgBox(DateAdd(DateInterval.Day, i_CalculateNumberOfDays, d_StartDate))
    

    我试着用下面的代码来解释:

    ''' create variables to begin with
    Dim d_StartDate as Date = "1-10-2009"
    Dim i_NumberOfDays as Integer = 5
    
    ''' create var to store number of days to calculate with
    Dim i_AddNumberOfDays as Integer 
    
    
    ''' check if amount of businessdays to add exceeds the 
    ''' amount of businessdays left in the week of the startdate
    If i_NumberOfDays > (5 - d_StartDate.DayOfWeek) Then
    
    
        ''' start by substracting days in week with the current day,
        ''' to calculate the remainder of days left in the current week
        i_AddNumberOfDays = 7 - d_StartDate.DayOfWeek
    
        ''' add the remainder of days in this week to the total
        ''' number of days we have to add to the date
        i_AddNumberOfDays += i_NumberOfDays
    
        ''' divide by 5, because we need to know how many 
        ''' business weeks we are dealing with
        i_AddNumberOfDays = i_AddNumberOfDays / 5
    
        ''' multiply the integer of current business weeks by 2
        ''' those are the amount of days in the weekends we have 
        ''' to add to the total
        i_AddNumberOfDays = Int(i_AddNumberOfDays) * 2
    
        ''' add the number of days to the weekend days
        i_AddNumberOfDays += i_NumberOfDays
    
    Else
    
        ''' there are enough businessdays left in this week
        ''' to add the given amount of days
        i_AddNumberOfDays = i_NumberOfDays
    
    End If
    
    ''' this is the numberof dates to calculate with in DateAdd
    dim d_CalculatedDate as Date
    d_CalculatedDate = DateAdd(DateInterval.Day, i_AddNumberOfDays, d_StartDate)
    

    提前感谢您对此的评论和意见。

    10 回复  |  直到 17 年前
        1
  •  0
  •   rmeador    17 年前

    你的计划似乎应该行得通。确保你将它包装在一个函数中,而不是在你使用它的每个地方进行计算,这样,如果/当你发现你需要考虑假期,你就不必在很多地方更改它。

    我能想到的实现假日支持的最佳方法是在循环中一次添加一天。每次迭代,检查是周末还是假日,如果是,请添加另一天并继续(跳过它)。下面是一个伪代码示例(我不知道VB);没有人保证它是正确的。当然,您需要为isWeekend()和isHoliday()提供自己的实现。

    function addBusinessDays(startDate, numDays)
    {
        Date newDate = startDate;
        while (numDays > 0)
        {
             newDate.addDays(1);
             if (newDate.isWeekend() || newDate.isHoliday())
                 continue;
    
             numDays -= 1;
        }
        return newDate;
    }
    

    我对假期的第一个想法是简单地查找开始日期和结束日期之间的假期数,并将其添加到您的计算中,但这当然不起作用,因为结束日期取决于该时间间隔内的假期数。我认为迭代解决方案是您在假期中得到的最佳解决方案。

        2
  •  1
  •   Tony L. ccalboni    11 年前

    我使用了.DayOfWeek函数来检查是否是周末。这不包括假期实施。它已经过测试。我意识到这个问题很老,但公认的答案不起作用。然而,我确实喜欢它有多干净,所以我想我应该更新它并发布。我确实改变了while循环中的逻辑。

    Function AddBusinessDays(startDate As Date, numberOfDays As Integer) As Date
        Dim newDate As Date = startDate
        While numberOfDays > 0
            newDate = newDate.AddDays(1)
    
            If newDate.DayOfWeek() > 0 AndAlso newDate.DayOfWeek() < 6 Then '1-5 is Mon-Fri
                numberOfDays -= 1
            End If
    
        End While
        Return newDate
    End Function
    
        3
  •  1
  •   Bugs Manjeet    7 年前
    Public Shared Function AddBusinessDays(ByVal startDate As DateTime, _
                                           ByVal businessDays As Integer) As DateTime
        Dim di As Integer
        Dim calendarDays As Integer
    
        '''di: shift to Friday. If it's Sat or Sun don't shift'
        di = (businessDays - Math.Max(0, (5 - startDate.DayOfWeek)))
    
        ''' Start = Friday -> add di/5 weeks -> end = Friday'
        ''' -> if the the remaining (<5 days) is > 0: add it + 2 days (Sat+Sun)'
        ''' -> shift back to initial day'
        calendarDays = ((((di / 5) * 7) _
                       + IIf(((di Mod 5) <> 0), (2 + (di Mod 5)), 0)) _
                       + (5 - startDate.DayOfWeek))
    
        Return startDate.AddDays(CDbl(calendarDays))
    
    End Function
    
        4
  •  0
  •   peterfh    13 年前

        dayOfWeek = startDate.DayOfWeek
        weekendDays = 2 * Math.Floor((dayOfWeek + businessDays - 0.1) / 5)
        newDate = startDate.AddDays(businessDays + weekendDays)
    

    第二行计算我们必须添加的完整周末的数量,然后将它们乘以2以获得天数。

        5
  •  0
  •   D. Zahn    11 年前
    Private Function AddBusinessDays(ByVal dtStartDate As DateTime, ByVal intVal As Integer) As DateTime
    
        Dim dtTemp As DateTime = dtStartDate
    
        dtTemp = dtStartDate.AddDays(intVal)
    
        Select Case dtTemp.DayOfWeek
            Case 0, 6
                dtTemp = dtTemp.AddDays(2)
        End Select
    
        AddBusinessDays = dtTemp
    
    End Function
    
        6
  •  0
  •   andrewsi Laxman Battini    11 年前

    请检查此代码以添加工作日

    Dim strDate As Date = DateTime.Now.Date
    Dim afterAddDays As Date
    Dim strResultDate As String
    Dim n As Integer = 0
    
    For i = 1 To 15
        afterAddDays = strDate.AddDays(i)
        If afterAddDays.DayOfWeek = DayOfWeek.Saturday Or afterAddDays.DayOfWeek = DayOfWeek.Sunday Then
            n = n + 1
        End If
    Next
    
    strResultDate = afterAddDays.AddDays(n).ToShortDateString()
    
        7
  •  0
  •   Patrick    9 年前
    Private Function AddXWorkingDays(noOfWorkingDaysToAdd As Integer) As Date
    
        AddXWorkingDays = DateAdd(DateInterval.Weekday, noOfWorkingDaysToAdd + 2, Date.Today)
        If Weekday(Today) + noOfWorkingDaysToAdd < 6 Then AddXWorkingDays = DateAdd(DateInterval.Weekday, 2, Date.Today)
    
    End Function
    
        8
  •  0
  •   Guru Josh    9 年前

    一种方法是从开始日期开始迭代,如果日期不是周六或周日,则每次迭代加上或减去一天。如果零作为IADDAYS传递,则函数将返回dDate,即使该日期是周六或周日。如果这种情况是可能的,你可以玩弄逻辑来得到你想要的结果。

     Public Function DateAddWeekDaysOnly(ByVal dDate As DateTime, ByVal iAddDays As Int32) As DateTime
        If iAddDays <> 0 Then
            Dim iIncrement As Int32 = If(iAddDays > 0, 1, -1)
            Dim iCounter As Int32
    
            Do
                dDate = dDate.AddDays(iIncrement)
                If dDate.DayOfWeek <> DayOfWeek.Saturday AndAlso dDate.DayOfWeek <> DayOfWeek.Sunday Then iCounter += iIncrement
            Loop Until iCounter = iAddDays
        End If
    
        Return dDate
    End Function
    
        9
  •  0
  •   Mac Dechmann    9 年前

    function addWerktage($date,$tage){
        for($t=0;$t<$tage;$t++){
            $date   = $date + (60*60*24);
            if(date("w",$date) == 0 || date("w",$date) == 6){ $t--; }
        }
        return $date;
    }
    
        10
  •  -2
  •   kapex    14 年前
    Dim result As Date
        result = DateAdd("d", 2, Today)
        If result.DayOfWeek = DayOfWeek.Saturday Then
            result = DateAdd("d", 2, result)
            MsgBox(result)
        ElseIf result.DayOfWeek = DayOfWeek.Sunday Then
            result = DateAdd("d", 1, result)
            MsgBox(result)
        ElseIf result.DayOfWeek = DayOfWeek.Monday Then
            MsgBox(result)
        ElseIf result.DayOfWeek = DayOfWeek.Tuesday Then
            MsgBox(result)
        ElseIf result.DayOfWeek = DayOfWeek.Wednesday Then
            MsgBox(result)
        ElseIf result.DayOfWeek = DayOfWeek.Thursday Then
            MsgBox(result)
        ElseIf result.DayOfWeek = DayOfWeek.Friday Then
            MsgBox(result)
        End If
    
    推荐文章