Business date/holiday handling
I've posted this question for C# but I may be working in Ruby instead. So I'm asking the same question about Ruby:
I'm looking for a Ruby class/library/module that works similarly to the Perl module Date::Manip
as far as business/holiday dates. Using that module in Perl, I can pass it a date and find out whether it's a business day (ie, Mon-Fri) or a holiday. Holidays are very simple to define in a config file (see Date::Ma开发者_如何学Cnip::Holidays
). You can enter a 'fixed' date that applies to every year like:
12/25 = Christmas
or 'dynamic' dates for every year like:
last Monday in May = Memorial Day
or 'fixed' dates for a given year like:
5/22/2010 = Bob's Wedding
You can also pass in a date and get back the next/previous business day (which is any day that's not a weekend and not a holiday).
Does anyone know of anything like that in the Ruby world?
You may use the holidays-gem. http://rubygems.org/gems/holidays
Some national (and regional) holidays are already predefined, you may define your own holiday definitions.
The business_time
gem should do what you need.
The example at bottom of the README doc is a good starting example:
require 'rubygems'
require 'active_support'
require 'business_time'
# We can adjust the start and end time of our business hours
BusinessTime::Config.beginning_of_workday = "8:30 am"
BusinessTime::Config.end_of_workday = "5:30 pm"
# and we can add holidays that don't count as business days
# July 5 in 2010 is a monday that the U.S. takes off because
# our independence day falls on that Sunday.
three_day_weekend = Date.parse("July 5th, 2010")
BusinessTime::Config.holidays << three_day_weekend
friday_afternoon = Time.parse("July 2nd, 2010, 4:50 pm")
tuesday_morning = 1.business_hour.after(friday_afternoon)
You probably going to need the chronic
gem to help you build the holiday dates from your config file. However YMMV because your example last monday in may doesn't work in chronic
. Hackaround is do something like this:
# last monday in May (2010)
Chronic.parse('last monday', :now => Time.parse('2010-06-01'))
And look at the tickle
gem which works on top of chronic
for a way to add recurring events.
/I3az/
You could take a look at my Workpattern gem. It allows you to specify working and resting times. It was aimed at producing a "Calendar" like is used in planning tools such as Microsoft Project and Primavera P6, so you can specify right down to the minute.
Here is a simple example:
Create a new Workpattern mywp=Workpattern.new('My Workpattern',2011,10)
This is for 10 years from 2011 but you can make it longer or shorter.
Tell it you want the Weekends to be resting and that you also want to rest during the week so you work between 9 and 12 in the morning and 1 and 6 in the afternoon.
mywp.resting(:days => :weekend)
mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(0,0),:to_time=>Workpattern.clock(8,59))
mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(12,0),:to_time=>Workpattern.clock(12,59))
mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(18,0),:to_time=>Workpattern.clock(23,59))
Now just calculate using minutes
mydate=DateTime.civil(2011,9,1,9,0)
result_date = mywp.calc(mydate,1920) # => 6/9/11@18:00
1920 is 4 days * 8 hours a day * 60 minutes and hour.
I wrote the gem to learn Ruby - only scratched the surface.
Check out the biz
gem.
Here's an example configuration:
require 'biz'
Biz.configure do |config|
config.hours = {
mon: {'09:00' => '17:00'},
tue: {'00:00' => '24:00'},
wed: {'09:00' => '17:00'},
thu: {'09:00' => '12:00', '13:00' => '17:00'},
sat: {'10:00' => '14:00'}
}
config.holidays = [Date.new(2014, 1, 1), Date.new(2014, 12, 25)]
config.time_zone = 'America/Los_Angeles'
end
When you use the optional core extensions, it's as easy as the following to find out if a date is a business day:
require 'biz/core_ext'
Date.new(2014, 12, 25).business_day? # => false
精彩评论