How to calculate next and previous business days in Rails?
Here's two examples for the number of working days between two dates:
Here's a Ruby holidays gem:
If you are running on rails, You could create a config/initializers/date_time.rb
class DateTime
def next_business_day
# if its a friday saturday or sunday
if self.day > 4
# calculate the remaining days to add to the current day
remaining_days = 7 - self.day + 1
return remaining_days.days.from_now
else
# return tomorrow
return self.tomorrow
end
end
end
usage:
a = DateTime.now
a.next_business_day
=> Mon, 08 Jun 2020 13:46:13 UTC +00:00
This is a method I use in my production scheduling script:
require 'date'
def shift_business_days(date, incr)
date = Date.parse(date.to_s)
incr.abs.times do
date += (incr < 0 ? -1 : 1)
while date.saturday? || date.sunday? do
date += (incr < 0 ? -1 : 1)
end
end
date
end
It takes a date and a positive or negative integer incr
as arguments, and increments or decrements the date by incr
days, skipping weekends. This has the added benefit of being able handle a Date/Time object or any date string that Date.parse can handle.
For example:
# (today is 2019-03-08)
shift_business_days(Time.now, 2)
##=> #<Date: 2019-03-12 ((2458555j,0s,0n),+0s,2299161j)>
shift_business_days('5/20', -10)
##=> #<Date: 2019-05-06 ((2458610j,0s,0n),+0s,2299161j)>
date = Date.today
date.next_weekday
date.prev_weekday
Well, you can use something like yesterday = 1.days.ago to get yesterday's date. Use yesterday.strftime('%w') to get the day of the week as a integer (0=Sunday, 6=Saturday). If yesterday is 0 (Sunday), then the previous day of the week would be 3.days.ago ... you get the idea.
And you can use tomorrow = 1.days.since to get tomorrow's date.
I realise that this is an old thread, but I just had to work this one out for myself and I was looking for a very short bit of code that was trivial to modify if a business had weird opening days (like "closed Sunday/Monday").
def next_business_day(from_day)
workdays = [1,2,3,4,5,6]
test_day = from_day + 1.day
return workdays.include?(test_day.wday) ? test_day : next_business_day(test_day)
end
I suppose it could be shortened again to something like this, but I think it becomes less obvious
def next_business_day(from_day)
test_day = from_day + 1.day
[1,2,3,4,5,6].include?(test_day.wday) ? test_day : next_business_day(test_day)
end