#!/bin/env ruby
class Time
Days = Day = 24 * 60 * 60
FixHolidays = Hash.new([]).merge(1 => [1,6], 5 => [1], 10 => [12], 12 => [25])
def self.holidays
@@holidays ||= Hash.new(Hash.new([])) # Year Specific holidays { 2013 => { 1 => [7,8]} }
end
# Add a year spefic holiday: Time.add_holiday 2014,2,10
def self.add_holiday(hyear, hmonth, hday)
holidays[hyear][hmonth] |= [hday]
end
def holiday?
FixHolidays[month].include?(day) || Time.holidays[year][month].include?(day)
end
def weekend?
saturday? || sunday? # wday > 5
end
# If it’s a weekend, the date is unavailable.
# If it’s a holiday, the date is unavailable.
def available?
!weekend? && !holiday? && !today?
end
def late?
hour >= 13
end
def today?
(self - Time.now).abs <= 1 * Day
end
def self.available_after_r(other, candidate = nil, found = 0)
candidate ||= other
needed = (other.late? ? 2 : 1 ) # If it’s after 1pm, take 2nd available
found += 1 if candidate.available?
return candidate if found == needed
available_after_r(other, candidate + 1*Day)
end
def self.available_after(other)
candidate = other
needed = (other.late? ? 2 : 1 ) # If it’s after 1pm, take 2nd available
found = 0
until found == needed
candidate += 1 * Day
found += 1 if candidate.available?
end
candidate
end
end
if $0 == __FILE__
require 'benchmark'
now = Time.now
n = 100_000
Benchmark.bm(10) do |b|
b.report("Iteration") { n.times{ Time.available_after(now)} }
b.report("Recursion") { n.times{ Time.available_after_r(now) }}
end
# $ ruby avail.rb
# user system total real
# Iteration 1.320000 0.140000 1.460000 ( 1.456945)
# Recursion 1.420000 0.160000 1.580000 ( 1.576072)
end