class AS::Duration::Calculator

Attributes

options[R]

Public Class Methods

new(parts) click to toggle source
# File lib/as/duration.rb, line 70
def initialize(parts)
  options = parts.inject({}) do |options, (type, number)|
    options.update(type => number) { |key, old, new| old + new }
  end

  # Remove partial weeks and days for accurate date behaviour
  if Float === options[:weeks]
    options[:weeks], partial_weeks = options[:weeks].divmod(1)
    options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
  end
  if Float === options[:days]
    options[:days], partial_days = options[:days].divmod(1)
    options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
  end

  @options = options
end

Public Instance Methods

advance(time) click to toggle source
# File lib/as/duration.rb, line 88
def advance(time)
  case time
  when Time then advance_time(time)
  when Date then advance_date(time)
  else
    raise ArgumentError, "expected Time or Date, got #{time.inspect}"
  end
end

Private Instance Methods

advance_date(date) click to toggle source
# File lib/as/duration.rb, line 116
def advance_date(date)
  date = advance_date_part(date)

  if seconds_to_advance == 0
    date
  else
    date.to_time + seconds_to_advance
  end
end
advance_date_part(date) click to toggle source
# File lib/as/duration.rb, line 126
def advance_date_part(date)
  date = date >> options.fetch(:years, 0) * 12
  date = date >> options.fetch(:months, 0)
  date = date +  options.fetch(:weeks, 0) * 7
  date = date +  options.fetch(:days, 0)
  date = date.gregorian if date.julian?
  date
end
advance_time(time) click to toggle source
# File lib/as/duration.rb, line 101
def advance_time(time)
  date = advance_date_part(time.to_date)

  time_advanced_by_date_args =
    if time.utc?
      Time.utc(date.year, date.month, date.day, time.hour, time.min, time.sec)
    elsif time.zone
      Time.local(date.year, date.month, date.day, time.hour, time.min, time.sec)
    else
      Time.new(date.year, date.month, date.day, time.hour, time.min, time.sec, time.utc_offset)
    end

  time_advanced_by_date_args + seconds_to_advance
end
seconds_to_advance() click to toggle source
# File lib/as/duration.rb, line 135
def seconds_to_advance
  options.fetch(:seconds, 0) +
  options.fetch(:minutes, 0) * 60 +
  options.fetch(:hours, 0) * 3600
end