Created
July 14, 2010 16:02
-
-
Save ahoward/475616 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
module VSRG | |
class Period | |
class << Period | |
def for(*args, &block) | |
options = args.options | |
first = args.first | |
last = args.last | |
case first | |
when Period | |
@begins_at = first.begins_at | |
@ends_at = first.ends_at | |
when ActiveRecord::Base | |
@begins_at = first.begins_at | |
@ends_at = first.ends_at | |
when Range | |
@begins_at = first.begin | |
@ends_at = first.end | |
when Array | |
@begins_at = first.first | |
@ends_at = first.last | |
else | |
if period_like?(first) | |
@begins_at = first.begins_at | |
@ends_at = first.ends_at | |
else | |
@begins_at = first | |
@ends_at = last | |
end | |
end | |
@begins_at ||= options.getopt(:begins_at) | |
@ends_at ||= options.getopt(:ends_at) | |
if @begins_at.nil? and @ends_at.nil? and not options.empty? | |
@begins_at, @ends_at, *ignored = options.to_a.flatten | |
end | |
new(:begins_at => @begins_at, :ends_at => @ends_at) | |
end | |
def [](*args, &block) | |
Period.for(*args, &block) | |
end | |
def period_like?(other) | |
other.respond_to?(:begins_at) && other.respond_to?(:ends_at) | |
end | |
end | |
attr_accessor :begins_at | |
attr_accessor :ends_at | |
def initialize(*args, &block) | |
options = args.options | |
@begins_at = time_for(args.shift || options[:begins_at]) | |
@ends_at = time_for(args.shift || options[:ends_at]) | |
if finite? | |
raise ArgumentError, 'begins_at > ends_at' if @begins_at > @ends_at | |
end | |
end | |
def time_for(time) | |
VSRG.cast(time, :time) if time | |
end | |
def period | |
self | |
end | |
def finite | |
begins_at and ends_at | |
end | |
alias_method 'finite?', 'finite' | |
def infinite | |
begins_at.nil? or ends_at.nil? | |
end | |
alias_method 'infinite?', 'infinite' | |
def begins_at_infinity | |
!begins_at | |
end | |
alias_method 'begins_at_infinity?', 'begins_at_infinity' | |
def ends_at_infinity | |
!ends_at | |
end | |
alias_method 'ends_at_infinity?', 'ends_at_infinity' | |
def forever | |
begins_at.nil? and ends_at.nil? | |
end | |
alias_method 'forever?', 'forever' | |
def duration | |
return Float::Infinity unless finite? | |
ends_at - begins_at | |
end | |
def <=>(other) | |
other = Period.for(other) | |
return -1 if before?(other) | |
return 1 if after?(other) | |
return -1 if starts_before?(other) # overlapping | |
return -1 if ends_before?(other) # overlapping | |
return 0 | |
end | |
# period operators | |
# | |
def before(other) | |
other = Period.for(other) | |
return false if period.ends_at_infinity? | |
return false if other.begins_at_infinity? | |
less_than?(period.ends_at, other.begins_at) or equal?(period.ends_at, other.begins_at) | |
end | |
alias_method 'before?', 'before' | |
# TODO | |
# | |
def after(other) | |
other = Period.for(other) | |
return false if period.begins_at_infinity? | |
return false if other.ends_at_infinity? | |
more_than?(other.begins_at, period.ends_at) or equal?(other.begins_at, period.ends_at) | |
end | |
alias_method 'after?', 'after' | |
def start_before(other) | |
other = Period.for(other) | |
less_than?(period.begins_at, other.begins_at) | |
end | |
alias_method 'start_before?', 'start_before' | |
alias_method 'starts_before?', 'start_before' | |
def end_before(other) | |
other = Period.for(other) | |
less_than?(period.ends_at, other.ends_at) | |
end | |
alias_method 'end_before?', 'end_before' | |
alias_method 'ends_before?', 'end_before' | |
def start_after(other) | |
other = Period.for(other) | |
more_than?(other.begins_at, period.begins_at) | |
end | |
alias_method 'start_after?', 'start_after' | |
alias_method 'starts_after?', 'start_after' | |
def start_at(other) | |
other = Period.for(other) | |
equal?(other.begins_at, period.begins_at) | |
end | |
alias_method 'start_at?', 'start_at' | |
alias_method 'starts_at?', 'start_at' | |
def start_during(other) | |
other = Period.for(other) | |
less_than?(period.begins_at, other.ends_at) and | |
(more_than?(period.begins_at, other.begins_at) or equal?(period.begins_at, other.begins_at)) | |
end | |
alias_method 'start_during?', 'start_during' | |
alias_method 'starts_during?', 'start_during' | |
def end_after(other) | |
other = Period.for(other) | |
more_than?(other.ends_at, period.ends_at) | |
end | |
alias_method 'end_after?', 'end_after' | |
alias_method 'ends_after?', 'end_after' | |
def end_at(other) | |
other = Period.for(other) | |
equal?(other.ends_at, period.ends_at) | |
end | |
alias_method 'end_at?', 'end_at' | |
alias_method 'ends_at?', 'end_at' | |
def end_during(other) | |
other = Period.for(other) | |
more_than?(period.ends_at, other.begins_at) and | |
(less_than?(period.ends_at, other.ends_at) or equal?(period.ends_at, other.ends_at)) | |
end | |
alias_method 'end_during?', 'end_during' | |
alias_method 'ends_during?', 'end_during' | |
def overlap(other) | |
other = Period.for(other) | |
end | |
alias_method 'overlap?', 'overlap' | |
alias_method 'overlaps', 'overlap' | |
alias_method 'overlaps?', 'overlap' | |
def contains(other) | |
other = Period.for(other) | |
(period.begins_at >= other.begins_at and period.begins_at < other.ends_at) and | |
(period.ends_at <= other.ends_at and period.ends_at > other.ends_at) | |
end | |
alias_method 'contains?', 'contains' | |
# operators | |
# a==b -> -infinity | |
# a==b -> infinity | |
# | |
private | |
def less_than(a, b) | |
return a < b if a and b | |
return true | |
end | |
alias_method 'less_than?', 'less_than' | |
alias_method 'lt', 'less_than' | |
alias_method 'lt?', 'less_than' | |
def less_than_or_equal(a, b) | |
return a <= b if a and b | |
return true | |
end | |
alias_method 'less_than_or_equal?', 'less_than_or_equal' | |
alias_method 'lte', 'less_than_or_equal' | |
alias_method 'lte?', 'less_than_or_equal' | |
def more_than(a, b) | |
return a > b if a and b | |
return true | |
end | |
alias_method 'more_than?', 'more_than' | |
alias_method 'mt', 'more_than' | |
alias_method 'mt?', 'more_than' | |
alias_method 'greater_than?', 'more_than' | |
alias_method 'gt', 'more_than' | |
alias_method 'gt?', 'more_than' | |
def more_than_or_equal(a, b) | |
return a > b if a and b | |
return true | |
end | |
alias_method 'more_than_or_equal?', 'more_than_or_equal' | |
alias_method 'gte', 'less_than_or_equal' | |
alias_method 'gte?', 'less_than_or_equal' | |
def equal(a, b) | |
return a == b if a and b | |
return false | |
end | |
alias_method 'equal?', 'equal' | |
alias_method 'eq', 'equal' | |
alias_method 'eq?', 'equal' | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment