lib/timespan.rb in timespan-0.1.0 vs lib/timespan.rb in timespan-0.1.2

- old
+ new

@@ -1,47 +1,179 @@ +require 'duration' + class TimeSpan - attr_reader :start_time, :end_time, :millis + attr_reader :start_time, :end_time, :seconds - def initialize start_time, end_time, options = {} + alias_method :start_date, :start_time + alias_method :end_date, :end_time + + def initialize options = {} + @is_new = true + + set_with_options options + + @is_new = false + end + + def start_time= start_time @start_time = start_time - @end_time = end_time + refresh! + end + alias_method :start_date=, :start_time= - @millis = start_time - end_time + def end_time= start_time + @start_time = start_time + refresh! end + alias_method :end_date=, :end_time= - def to_seconds - @to_seconds ||= millis * 1000 + def seconds= seconds + @seconds = seconds + refresh! end - alias_method :to_s, :to_seconds - alias_method :to_secs, :to_seconds + def duration + @duration ||= Duration.new(seconds) + end + + def duration= duration + raise ArgumentError, "the duration option must be set to a Duration instance" unless duration.kind_of? Duration + @duration = duration + refresh! unless is_new? + end + + def to_s + if duration + "TimeSpan: from #{start_time} lasting #{duration} = #{seconds} secs" if start_time + "TimeSpan: from #{end_time} to #{duration} before = #{seconds} secs" if end_time + return + end + + if start_time && end_time + "TimeSpan: #{start_time} to #{end_time} = #{seconds} secs" + return + end + + if seconds + "TimeSpan: #{seconds} seconds" + end + end + + include Comparable + + def <=> time + raise ArgumentError, "Not a valid argument for timespan comparison, was #{time}" unless valid_compare?(time) + case time + when TimeSpan + millis <=> time.seconds + when Time + millis <=> time.to_i + when Date, DateTime + time.to_time.to_i + when Integer + millis <=> time + end + end + + alias_method :to_secs, :seconds + alias_method :to_seconds, :seconds + + def to_milliseconds + @to_seconds ||= (seconds * 1000.0).round + end + alias_method :to_mils, :to_milliseconds + alias_method :millis, :to_mils + def to_minutes - @to_minutes ||= to_seconds * 60 + @to_minutes ||= (to_seconds / 60.0).round end alias_method :to_m, :to_minutes alias_method :to_mins, :to_minutes def to_hours - @to_hours ||= to_minutes * 60 + @to_hours ||= (to_minutes / 60.0).round end alias_method :to_h, :to_hours def to_days - @to_days ||= to_hours * 24 + @to_days ||= (to_hours / 24).round end alias_method :to_d, :to_days def to_weeks - @to_weeks ||= to_days * 7 + @to_weeks ||= (to_days / 7).round end alias_method :to_w, :to_weeks def to_months - @to_months ||= to_days * 30 + @to_months ||= (to_days / 30).round end alias_method :to_mon, :to_months def to_years - @to_years ||= (to_days.to_f * 365.25).round + @to_years ||= (to_days.to_f / 365.25).round end alias_method :to_y, :to_years + + def units + %w{seconds minutes hours days weeks months years} + end + + protected + + def set_with_options options = {} + case options + when Hash + duration = options[:duration] + @start_time = options[:from] + @end_time = options[:to] + when Integer + else + raise ArgumentError, "Timespan must take Hash or Integer, was: #{options}" + end + + set_seconds options + end + + def set_seconds options = nil + set_seconds_opts(options) + + unless @duration + if @end_time && @start_time + @seconds ||= (@end_time - @start_time).to_i + end + else + @seconds ||= @duration.total + end + end + + def set_seconds_opts options = {} + case options + when Integer + @seconds = options + when Hash + @seconds = options[:seconds] if options[:seconds] + self.duration = options[:duration] if options[:duration] + end + end + + def is_new? + @is_new + end + + # reset all stored instance vars for units + def refresh! + units.each do |unit| + var_name = :"@#{unit}" + instance_variable_set var_name, nil + end + set_seconds + end + + def valid_compare? time + valid_compare_types.any? {|type| time.kind_of? type } + end + + def valid_compare_types + [TimeSpan, Time, Date, DateTime, Integer] + end end \ No newline at end of file