Skip to content

Instantly share code, notes, and snippets.

/README Secret

Created June 24, 2010 00:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3a03d223ccbafdb673ed to your computer and use it in GitHub Desktop.
Save anonymous/3a03d223ccbafdb673ed to your computer and use it in GitHub Desktop.
This is a gist of my solution to the 10th RPCFN Challenge (http://rubylearning.com/blog/2010/05/25/rpcfn-business-hours-10/)
Submitted June 23, 2010
This is separated out into three files:
- app.rb (test cases)
- day.rb
- business-hours.rb
require 'day'
require 'business-hours'
require 'time'
hours = BusinessHours.new("9:00 AM", "3:00 PM")
hours.update :sun, "9:00 AM", "10:45 AM"
hours.update :mon, "7:46 AM", "4:00 PM"
hours.update :thu, "10:00 AM", "12:01 PM"
hours.update "Dec 24, 2009", "11:00 AM", "2:00 PM"
hours.closed :tue, :wed, "Jan 21 2010", :fri, "Jan 23 2010"
hours.update "Dec 24, 2009", "2:00 AM", "2:30 PM"
hours.update "01/25/2010", "7:46 AM", "9:00 AM"
hours.update 'something', "7:46 AM", "9:00 AM" # will be parsed as 'today'
hours.update 1, "7:46 AM", "9:00 AM"
hours.update :mon, "7:46 AM", "4:00 PM"
# hours.display # => Used to display currently set business hours & special cases
hours.closed :tue
puts hours.calculate_deadline(2*60*60, "Jan 20, 2010 6:01 PM")
puts hours.calculate_deadline(60*60, "Jan 20, 2010 6:01 PM")
puts hours.calculate_deadline(15*60, "Jan 20, 2010 6:01 PM")
puts hours.calculate_deadline(2*60*60, "Jan 19, 2011 17:55 PM")
hours = BusinessHours.new("9:00 AM", "3:00 PM")
hours.closed :sun, :wed, "Dec 25 2010"
hours.update :fri, "10:00 AM", "5:00 PM"
hours.update "Dec 24, 2010", "8:00 AM", "1:00 PM"
puts hours.calculate_deadline(7*60*60, "Dec 24, 2010 6:45 AM")
class BusinessHours
attr_accessor :days
def initialize(open, closed)
@days = Hash.new
%w(sun mon tue wed thu fri sat).each {|day| @days[day.intern] = Day.new(open, closed)} # => Set hours for each day of the week
end
def update(day, open, closed)
day = Time.parse(day).strftime('%D') if day.kind_of? String # => '%D' used to create a rule for this date
if day.kind_of?(String) || day.kind_of?(Symbol) # => Only symbols/strings should be allowed
@days[day] = Day.new if @days[day].nil?
@days[day].set_hours(open, closed)
else
puts "The first parameter needs to be a Symbol or a String. (Entered #{day} => #{day.class})"
end
end
def display # => Simple display of current hours
puts"[Day] => [Open] to [Closed]"
@days.keys.each {|key| puts @days[key].closed? ? "#{key} => CLOSED" : "#{key} => #{@days[key].open} to #{@days[key].closed}"}
end
def closed(*args)
args.each {|a| update(a, "0:00 AM", "0:00 AM") } # => 0:00 to 0:00 will represent closed
end
def calculate_deadline(time_required, start_string)
start_time = current_time = Time.parse(start_string)
while(time_required > 0)
# => '%D' used to check if a rule has been created specific to this date
day = @days[current_time.strftime('%D')] ? @days[current_time.strftime('%D')] : @days[current_time.strftime('%a').downcase.intern]
# => Creates time objs for the current date's opening/closing
opening_time, closing_time = current_time.parse_time(day.open), closing_time = current_time.parse_time(day.closed)
# => If before opening time, set current_time to opening
current_time = Time.at(opening_time) if opening_time > current_time
if !day.closed? && current_time < closing_time
# => Check if we're going past closing. If not, return. Otherwise, calculate!
current_time + time_required < closing_time ? (return current_time + time_required) : (time_required -= (closing_time.to_i - current_time.to_i))
end
current_time = Time.parse((current_time + 24*60*60).strftime('%D')) # => Go To tomorrow
return "Couldn't finish safely" if (current_time - start_time) >= (24*60*60)*30 # => Saftey! Stop if we pass 30 days.
end
end
end
class Day
attr_accessor :open, :closed
def initialize(open = nil, closed = nil)
self.set_hours(open, closed)
end
def closed?
self.open == '0:00 AM' && self.closed == '0:00 AM'
end
def set_hours(open, closed)
self.open, self.closed = open, closed
end
end
class Time
def parse_time(time)
Time.parse(self.strftime('%D') << " " << time)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment