Jump to content

DateDiff_WorkDaysOnly


gcue
 Share

Go to solution Solved by Gianni,

Recommended Posts

Thought I'd share this snippet I created based off jdelaney's post

Calculates date in the past based off of only work days (ie: a week of just workdays).  Any feedback welcome :)

$start_date = "2023/03/27"
$weekdays_ago = 2

$date = DateDiff_WeekDaysOnly($start_date, $weekdays_ago)

Func DateDiff_WeekDaysOnly($start_date, $weekdays_ago)

    $weekdays = 0
    $days_reduce = 0

    While $weekdays <> $weekdays_ago
        $days_reduce -= 1

        $running_date = _DateAdd("d", $days_reduce, $start_date)
        $aTemp = StringSplit($running_date, "/")
        $iDate = _DateToDayOfWeek($aTemp[1], $aTemp[2], $aTemp[3])

        If $iDate <> 1 And $iDate <> 7 Then
            $weekdays += 1
        EndIf
    WEnd

    $date_desired = _DateAdd("d", $days_reduce, $start_date)

    Return $date_desired

EndFunc   ;==>DateDiff_WeekDaysOnly

 

Edited by gcue
Link to comment
Share on other sites

You could also implement the ability to calculate future dates, and also add another parameter to be able to indicate non-working days as you like (e.g. if someone works only Monday, Friday and Sunday he could pass '3,4,5,7' as holidays (assuming 1=Sunday, 2 =Monday , 3=Tuesday, 4=Wednesday, 5=Thursday, 6=Friday, 7=Saturday)
For fun, I wrote a function that has these possibilities using SQL (sqlite), but in order not to hijack your topic, for those interested, I post it in the session dedicated to SQL at this link: https://www.autoitscript.com/forum/topic/210024-a-workday-function-using-sqlite/

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

Instead of counting every single days, it would be faster and somewhat more elegant to divide the number of working days into weeks and then only count the remaining few days :

#include <Date.au3>

Local $sDate = FastWorkDays(_NowDate(), -21)
ConsoleWrite($sDate & @CRLF)

Func FastWorkDays($sDate, $iNumDay)
  If Not $iNumDay Then Return SetError(1)
  Local $iSign = $iNumDay < 0 ? -1 : 1
  Local $iNumWeek = Int(($iNumDay - $iSign) / 5)
  $iNumDay = Mod($iNumDay - $iSign, 5) + $iSign
  $sDate = _DateAdd("w", $iNumWeek, $sDate)
  Local $aTemp, $iDate
  While $iNumDay
    $sDate = _DateAdd("d", $iSign, $sDate)
    $aTemp = StringSplit($sDate, "/")
    $iDate = _DateToDayOfWeek($aTemp[1], $aTemp[2], $aTemp[3])
    If $iDate = "1" Or $iDate = "7" Then ContinueLoop
    $iNumDay -= $iSign
  WEnd
  Return $sDate
EndFunc

:)

Edited by Nine
Link to comment
Share on other sites

On 4/8/2023 at 2:20 PM, Nine said:

Instead of counting every single days, it would be faster and somewhat more elegant to divide the number of working days into weeks and then only count the remaining few days :

#include <Date.au3>

Local $sDate = FastWorkDays(_NowDate(), -21)
ConsoleWrite($sDate & @CRLF)

Func FastWorkDays($sDate, $iNumDay)
  If Not $iNumDay Then Return SetError(1)
  Local $iSign = $iNumDay < 0 ? -1 : 1
  Local $iNumWeek = Floor(($iNumDay - $iSign) / 5)
  $iNumDay = Mod($iNumDay - $iSign, 5) + $iSign
  $sDate = _DateAdd("w", $iNumWeek, $sDate)
  Local $aTemp, $iDate
  While $iNumDay
    $sDate = _DateAdd("d", $iSign, $sDate)
    $aTemp = StringSplit($sDate, "/")
    $iDate = _DateToDayOfWeek($aTemp[1], $aTemp[2], $aTemp[3])
    If $iDate = "1" Or $iDate = "7" Then ContinueLoop
    $iNumDay -= $iSign
  WEnd
  Return $sDate
EndFunc

:)

Hi @Nine
if i'm not doing something wrong, there seems to be a bug there:
tried with FastWorkDays('2023/04/10', -2)
got 2023/03/30 instead of 2023/04/06

p.s.
also, since _NowDate() is localized, better to use _NowCalcDate

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

@Gianni  You are right, Floor is not working as I expected on negative numbers.  Thanks for testing (It seems I didn't test enough).  Replacing it with Int solves the problem.  Previous code corrected.

Edited by Nine
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...