Find date-interval for ±n weekdays

question
proposal
dates

#1

I needed to find the dates for a plus-minus n weekdays interval, you know, when they say the product will be delivered in 5 working/week days. I couldn’t find anything, so I made this:

function weekdaysinterval(today, weekdays)
    function step(x, by)
        counter = 0
        while counter < weekdays
            x += by
            if Dates.dayofweek(x) < 6
                counter += 1
            end
        end
        x
    end
    from = step(today, -Dates.Day(1))
    to = step(today, Dates.Day(1))
    from, to
end

Happy to hear if this is already implemented or if you have any suggestions. Note that this implementation is for weekdays, not workingdays, and as such it assumes that a week is Monday–Friday, including (however, this is not true for some countries, e.g. Israel).


#2

I don’t know how long the intervals are, but the number of days to add should be possible to obtain in a closed form.


#3

Of course :man_facepalming:


#4

I always assumed


did this,
but it doesn’t


#5

How about this:

weekdays(today, weekdays) = today + Dates.Day(weekdays + 2*((Dates.dayofweek(today) + weekdays) ÷ 5))

Seems to give the exact same results as my former function…


#6

But with this info I could do workingdays-intervals. I guess I’ll have to use the open-form function from before.


#7

Looks OK to me, but I am sure I would be tripped up by corner cases. Does it work for negative weekdays?

Also, while technically not a problem, I would use different names for the function and the argument.


#8

Yea, for sure, I should check it out and make sure it always works. To be honest, I was sure someone will point me to an already existing implementation. Seems like a really common need…?


#9

I think there is a one off error (at least it skips Friday) and I don’t think it works for negative values.

Here is some code that should suffice:

function weekdays(today, wd)
    function skipdays(workdays, today)
        adj = (Dates.dayofweek(today) - 1) * sign(workdays)
        weekends = div(workdays + adj, 5) 
        today + Dates.Day(workdays + weekends * 2)
    end

    skipdays(-wd, today), skipdays(wd, today)
end

There is also the Dates adjuster API with Dates.toprev and Dates.tonext that can be used to find such dates iteratively, but in a generic manner (e.g. add holidays into the mix).