Skip to content

Instantly share code, notes, and snippets.

@oinak
Last active August 29, 2015 13:56
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 oinak/8892108 to your computer and use it in GitHub Desktop.
Save oinak/8892108 to your computer and use it in GitHub Desktop.
#!/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
@oinak
Copy link
Author

oinak commented Feb 8, 2014

> Time.add_holiday 2014,02,10
=> [10]
> now = Time.now
=> 2014-02-09 00:42:18 +0100
> Time.available_after now
=> 2014-02-12 00:42:18 +0100

@oinak
Copy link
Author

oinak commented Mar 26, 2014

this program may only make sense as a meditation about http://rocketships.ca/blog/674/ go read it first

@oinak
Copy link
Author

oinak commented Jun 15, 2014

This gist is an exercise, if you arrived here looking for a serious tool to tackle this problem go check: https://github.com/gocardless/business and/or https://github.com/bokmann/business_time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment