-
-
Save benoitr/4eb2915f53a0ec4b40b5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "time" | |
require "date" | |
class Date | |
def to_time | |
Time.local(year, month, day) | |
end | |
end | |
class Time | |
def to_date | |
Date.new(year, month, day) | |
end | |
end | |
class BusinessHours | |
def initialize(opening, closing) | |
@schedule = { :default => [opening, closing] } | |
end | |
def update(day, opening, closing) | |
key = day.kind_of?(Symbol) ? Date.parse(day.to_s).wday : Date.parse(day) | |
@schedule[key] = [opening, closing] | |
end | |
def closed(*days) | |
days.each { |day| update(day, "0:00", "0:00") } | |
end | |
def calculate_deadline(interval, start_time) | |
Deadline.new(@schedule, interval, Time.parse(start_time)).calculate | |
end | |
class Deadline | |
def initialize(*args) | |
@schedule, @remaining, @current_time = *args | |
end | |
def calculate | |
increment_day while after_today? | |
current_or_opening_time + @remaining | |
end | |
private | |
def after_today? | |
current_or_opening_time + @remaining > closing_time | |
end | |
def increment_day | |
@remaining -= closing_time - current_or_opening_time if @current_time < closing_time | |
@current_time = @current_time.to_date.next.to_time | |
end | |
def current_or_opening_time | |
[@current_time, opening_time].max | |
end | |
def opening_time | |
Time.parse(current_hours.first, @current_time) | |
end | |
def closing_time | |
Time.parse(current_hours.last, @current_time) | |
end | |
def current_hours | |
@schedule[@current_time.to_date] || @schedule[@current_time.wday] || @schedule[:default] | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "test/unit" | |
require File.dirname(__FILE__) + '/business_hours' | |
class BusinessHoursTest < Test::Unit::TestCase | |
def setup | |
@hours = BusinessHours.new("8:00 AM", "5:00 PM") | |
end | |
def test_within_working_hours | |
assert_equal Time.parse("Dec 21, 2009 3:05 PM"), @hours.calculate_deadline(5*60, "Dec 21, 2009 3:00 PM") | |
end | |
def test_start_at_opening_time | |
assert_equal Time.parse("Dec 21, 2009 8:05 AM"), @hours.calculate_deadline(5*60, "Dec 21, 2009 7:27 AM") | |
end | |
def test_start_next_day_when_after_closing_time | |
assert_equal Time.parse("Dec 21, 2009 8:05 AM"), @hours.calculate_deadline(5*60, "Dec 20, 2009 6:37 PM") | |
end | |
def test_carry_over_remaining_time_onto_next_day | |
assert_equal Time.parse("Dec 22, 2009 8:02 AM"), @hours.calculate_deadline(5*60, "Dec 21, 2009 4:57 PM") | |
end | |
def test_skip_full_day | |
assert_equal Time.parse("Dec 23, 2009 8:57 AM"), @hours.calculate_deadline(10*60*60, "Dec 21, 2009 4:57 PM") | |
end | |
def test_skip_current_day_before_opening | |
assert_equal Time.parse("Dec 22, 2009 9:00 AM"), @hours.calculate_deadline(10*60*60, "Dec 21, 2009 7:57 AM") | |
end | |
def test_update_week_day_hours | |
@hours.update :mon, "8:00 AM", "3:00 PM" | |
@hours.update :tue, "9:00 AM", "5:00 PM" | |
assert_equal Time.parse("Dec 22, 2009 9:02 AM"), @hours.calculate_deadline(5*60, "Dec 21, 2009 2:57 PM") | |
end | |
def test_skip_closed_days | |
@hours.closed :sat, :sun | |
assert_equal Time.parse("Dec 21, 2009 8:02 AM"), @hours.calculate_deadline(5*60, "Dec 18, 2009 4:57 PM") | |
end | |
def test_change_hours_for_specific_dates | |
@hours.update "Dec 24, 2009", "8:00 AM", "3:00 PM" | |
@hours.closed :sat, :sun, "Dec 25, 2009" | |
assert_equal Time.parse("Dec 28, 2009 8:02 AM"), @hours.calculate_deadline(5*60, "Dec 24, 2009 2:57 PM") | |
assert_equal Time.parse("Dec 17, 2009 3:02 PM"), @hours.calculate_deadline(5*60, "Dec 17, 2009 2:57 PM") | |
end | |
def test_start_on_closed_days | |
@hours.closed :tue, "Dec 25, 2009" | |
assert_equal Time.parse("Dec 23, 2009 8:05 AM"), @hours.calculate_deadline(5*60, "Dec 22, 2009 4:57 PM") | |
assert_equal Time.parse("Dec 26, 2009 8:05 AM"), @hours.calculate_deadline(5*60, "Dec 25, 2009 4:57 PM") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment