lib/timespan.rb in timespan-0.4.6 vs lib/timespan.rb in timespan-0.4.9
- old
+ new
@@ -1,10 +1,17 @@
require 'duration'
require 'chronic'
require 'chronic_duration'
require 'spanner'
+# Range intersection that works with dates!
+require 'sugar-high/range'
+require 'sugar-high/delegate'
+require 'sugar-high/kind_of'
+
+require 'timespan/core_ext'
+
require 'timespan/units'
require 'timespan/compare'
require 'timespan/printer'
require 'timespan/span'
require 'active_support/core_ext/date/calculations.rb'
@@ -42,11 +49,10 @@
ALL_KEYS = START_KEYS + END_KEYS + DURATION_KEYS
def initialize options = {}
@is_new = true
-
@init_options = options
validate! if options == {}
options = {:duration => options} if options.kind_of? Numeric
@@ -58,45 +64,74 @@
configure! options
@is_new = false
end
- def self.from start, duration, options = {}
- start = case start.to_sym
- when :now, :asap
- Time.now
- when :today
- Date.today
- when :tomorrow
- Date.today + 1.day
- when :next_week # requires active_support
- date = Date.today.next_week
- options[:start] ? date.beginning_of_week : date
- when :next_month
- date = Date.today.next_month
- options[:start] ? date.at_beginning_of_month.next_month : date
- else
- start
+ class << self
+ def max_date
+ @max_date ||= Time.now + 10.years
end
- self.new start_date: start, duration: duration
- end
+ def min_date
+ @min_date ||= Time.now
+ end
- def self.untill ending
- ending = case ending.to_sym
- when :tomorrow
- Date.today + 1.day
- when :next_week # requires active_support
- date = Date.today.next_week
- options[:start] ? date.beginning_of_week : date
- when :next_month
- date = Date.today.next_month
- options[:start] ? date.at_beginning_of_month.next_month : date
- else
- ending
+ def max_date= date
+ @max_date = date if valid_date?(date)
end
- self.new start_date: Date.now, end_date: ending
+
+ def min_date= date
+ @max_date = date if valid_date?(date)
+ end
+
+ def asap options = {}
+ self.new options.merge(asap: true)
+ end
+
+ def from start, duration, options = {}
+ start = case start.to_sym
+ when :now, :asap
+ Time.now
+ when :today
+ Date.today
+ when :tomorrow
+ Date.today + 1.day
+ when :next_week # requires active_support
+ date = Date.today.next_week
+ options[:start] ? date.beginning_of_week : date
+ when :next_month
+ date = Date.today.next_month
+ options[:start] ? date.at_beginning_of_month.next_month : date
+ else
+ start
+ end
+
+ self.new start_date: start, duration: duration
+ end
+
+ def untill ending
+ ending = case ending.to_sym
+ when :tomorrow
+ Date.today + 1.day
+ when :next_week # requires active_support
+ date = Date.today.next_week
+ options[:start] ? date.beginning_of_week : date
+ when :next_month
+ date = Date.today.next_month
+ options[:start] ? date.at_beginning_of_month.next_month : date
+ else
+ ending
+ end
+ self.new start_date: Date.now, end_date: ending
+ end
+ alias_method :until, :untill
+
+ protected
+
+ def valid_date? date
+ date.any_kind_of?(Date, Time, DateTime)
+ end
end
def start_time= time
@start_time = convert_to_time time
unless is_new?
@@ -120,25 +155,41 @@
calculate!
end
end
alias_method :end_date=, :end_time=
- def until time
+ def asap?
+ @asap
+ end
+
+ def min
+ asap ? Time.now : start_time
+ end
+
+ def max
+ end_time
+ end
+
+ def untill time
self.end_time = time
self
end
+ alias_method :until, :untill
def convert_to_time time
+ time = Duration.new time if time.kind_of? Numeric
case time
when String
Chronic.parse(time)
when Date, DateTime
time.to_time
+ when Duration
+ (Time.now + time).to_time
when Time
time
else
- raise ArgumentError, "A valid time must be either a String, Date, Time or DateTime, was: #{time.inspect}"
+ raise ArgumentError, "A valid time must be either a String, Duration, Date, Time or DateTime, was: #{time.inspect} (#{time.class})"
end
end
protected
@@ -151,21 +202,43 @@
# uses init_options to configure
def configure! options = {}
from = options[first_from(START_KEYS, options)]
to = options[first_from(END_KEYS, options)]
dur = options[first_from(DURATION_KEYS, options)]
+ asap = options[:asap]
+ if options[:at_least]
+ to = Timespan.max_date
+ from = Time.now + options[:at_least]
+ end
+
+ if options[:at_most]
+ to = Time.now + options[:at_most]
+ from = Time.now
+ end
+
+ if options[:between]
+ from = Time.now + options[:between].min
+ to = Time.now + options[:between].max
+ end
+
+ # puts "configure: to:#{to}, from:#{from}, dur:#{dur}, asap:#{asap}"
+
+ @asap = asap if asap
self.duration = dur if dur
self.start_time = from if from
self.end_time = to if to
+ # puts "configured: start:#{self.start_time}, end:#{self.end_time}, duration:#{self.duration}, asap:#{self.asap?}"
+
default_from_now!
calculate_miss!
rescue ArgumentError => e
raise TimeParseError, e.message
- rescue Exception => e
- calculate_miss!
- validate!
+ # rescue Exception => e
+ # puts "Exception: #{e}"
+ # calculate_miss!
+ # validate!
end
def default_from_now!
self.start_time = now unless start_time || (end_time && duration)
self.end_time = now unless end_time || (start_time && duration)
\ No newline at end of file