I am working on an application where I need to be able to add 3 week days to today’s date. Unfortunately there doesn’t seem to be any built-in functionality for this in Ruby, so I needed to roll my own. At first I searched Google hoping someone had already solved the problem for me, which is most often the case. Not so with this problem. I did however come across this post on Platte daddy, which provided a good starting point, but was designed to simply add 1 weekday, not any number of days that I want.
I ran through a number of iterations until I came up with this helper method:
def add_cwdays(date, n)
#Add number of weekdays plus necessary weekend days
date += n.days + (2*(n/5.floor)).days
#If the above lands on a weekend, keep adding days until it is a weekday
date += 1.days until (1..5).member?(date.wday)
date
end
This was added to my ApplicationHelper.rb file and is called for adding 3 week days to today via:
add_cwdays(Time.now, 3)
I created a helper to DRY the method and I wrote it so that the starting date and the number of workdays is variable. The helper has only 2 lines of code (after some re-factoring), which reduces the readability a bit, but it still makes sense I think.
The first line simply adds the desired number of weekdays, plus any weekend days that would be within the range of week days. If we wanted to add 8 weekdays, we would need to add 10 total calendar days (1 weekend). If we wanted to add 23 weekdays, we would need to add 31 total calendar days (4 weekends). If we wanted to add 4 weekdays, we would need to add 4 total calendar days (no weekends). The weekend addition is made with the (2*(n/5.floor)).days bit of code. Basically take the number of days “n”, divide by five, strip off the decimal and multiply by 2 (for Saturday and Sunday).
The second line of code deals with the eventuality of the first line landing on a weekend. If this happens, we simply add 1 day repeatedly “until” we reach a weekday.
This seems to be working well, if anyone looks this over and sees anything wrong or if there are any opportunities to re-factor and simplify, please post comments.
Sorry you had to go to all that trouble, I should have updated my post instead of just following up, but my colleague Dave extended the code into a Ruby Facets contribution that can take any number of weekdays:
http://daddy.platte.name/2007/02/weekday-code-accepted-into-ruby-facets.html