anonymous / business_hours.rb secret
Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist
View business_hours.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#!/usr/bin/env ruby
 
# require dependencies
require 'time'
require 'date'
 
class BusinessHours
DAYS = [:sun, :mon, :tue, :wed, :thu, :fri, :sat]
ONE_DAY = 24*60*60
 
class Day
attr_accessor :opening, :closing, :date
 
def initialize(opening_time, closing_time, date=nil)
self.update(opening_time, closing_time, date)
end
 
def close
self.opening, self.closing = nil, nil
end
 
def closed?
self.opening.nil?
end
 
def update(opening_time, closing_time, date=nil)
self.opening, self.closing, self.date = opening_time, closing_time, date
end
end
 
attr_accessor :business_hours, :exceptions
 
def initialize(opening_time, closing_time)
self.business_hours, self.exceptions = {}, {}
 
DAYS.each do |day|
self.business_hours[day] = Day.new(opening_time, closing_time)
end
end
 
def update(day, opening_time, closing_time)
if day.is_a?(Symbol)
self.business_hours[day].update(opening_time, closing_time)
else # string expected, it's a special date case
date = Date.parse(day)
self.exceptions[date.to_s] = Day.new(opening_time, closing_time)
end
end
 
def closed(*days)
days.each do |day|
if day.is_a?(Symbol)
self.business_hours[day].close
else
date = Date.parse(day)
self.exceptions[date.to_s] = Day.new(nil, nil)
end
end
end
 
def calculate_deadline(interval, starting_time)
start_at = time = Time.parse(starting_time)
date = time.strftime('%Y-%m-%d')
weekday = time.strftime('%a').downcase.to_sym
 
remaining_time = interval
while remaining_time.is_a?(Integer) && remaining_time > 0
d = self.exceptions[date] || self.business_hours[weekday]
unless d.closed?
from = Time.parse(date + ' ' + d.opening)
to = Time.parse(date + ' ' + d.closing)
if (from..to).include?(start_at)
from = start_at
end
remaining_time = deduct(remaining_time, (from..to))
end
 
return remaining_time unless remaining_time.is_a?(Integer)
 
time = time + ONE_DAY
date = time.strftime('%Y-%m-%d')
weekday = time.strftime('%a').downcase.to_sym
end
end
 
private
 
def deduct(count, range)
total = (range.last-range.first).to_i
if count >= total
count - total
else
range.first + count
end
end
 
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.