class Montrose::Clock

Public Class Methods

new(opts = {}) click to toggle source
# File lib/montrose/clock.rb, line 7
def initialize(opts = {})
  @options = Montrose::Options.merge(opts)
  @time = nil
  @every = @options.fetch(:every) { fail ConfigurationError, "Required option :every not provided" }
  @interval = @options.fetch(:interval)
  @start_time = @options.fetch(:start_time)
  @at = @options.fetch(:at, []).sort
end

Public Instance Methods

peek() click to toggle source
# File lib/montrose/clock.rb, line 23
def peek
  next_time(false)
end
tick() click to toggle source

Advances time to new unit by increment and sets new time as “current” time for next tick

# File lib/montrose/clock.rb, line 19
def tick
  @time = next_time(true)
end

Private Instance Methods

advance_step(time) click to toggle source
# File lib/montrose/clock.rb, line 39
def advance_step(time)
  time.advance(step)
end
current_at_index() click to toggle source

@private

Keep track of which index we are currently at for :at option.

# File lib/montrose/clock.rb, line 96
def current_at_index
  @current_at_index ||= @at.index do |hour, min, sec = 0|
    @start_time.hour == hour && @start_time.min == min && @start_time.sec == sec
  end
end
next_time(tick) click to toggle source
# File lib/montrose/clock.rb, line 29
def next_time(tick)
  return @start_time if @time.nil?

  if @at.present?
    next_time_at(@time, tick)
  else
    advance_step(@time)
  end
end
next_time_at(time, tick) click to toggle source

@private

Returns next time using :at option. Tries to calculate a time for the current date by incrementing the index of the :at option. Once all items have been exhausted the minimum time is generated for the current date and we advance to the next date based on interval

# File lib/montrose/clock.rb, line 65
def next_time_at(time, tick)
  if current_at_index && (next_time = time_at(time, current_at_index + 1))
    @current_at_index += 1 if tick

    next_time
  else
    min_time = time_at(time, 0)
    @current_at_index = 0 if tick

    advance_step(min_time)
  end
end
smallest_step() click to toggle source
# File lib/montrose/clock.rb, line 47
def smallest_step
  unit_step(:second) ||
    unit_step(:minute) ||
    unit_step(:hour) ||
    unit_step(:day, :mday, :yday) ||
    unit_step(:week) ||
    unit_step(:month) ||
    unit_step(:year)
end
step() click to toggle source
# File lib/montrose/clock.rb, line 43
def step
  (@step ||= smallest_step) || fail(ConfigurationError, "No step for #{@options.inspect}")
end
step_key(unit) click to toggle source

@private

Change ‘unit’ to :units

# File lib/montrose/clock.rb, line 134
def step_key(unit)
  "#{unit}s".to_sym
end
time_at(time, index) click to toggle source

@private

Returns time with hour, minute and second from :at option at specified index

# File lib/montrose/clock.rb, line 83
def time_at(time, index)
  parts = @at[index]

  return unless parts

  hour, min, sec = parts
  time.change(hour: hour, min: min, sec: sec || 0)
end
unit_step(unit, *alternates) click to toggle source

@private

Returns hash representing unit and amount to advance time when options contain given unit as a key or as a value of the key :every in options

options = { every: :day, hour: 8.12 } unit_step(:minute)

> nil

unit_step(:hour)

> { hour: 1 }

options = { every: :hour, interval: 6 } unit_step(:minute)

> nil

unit_step(:hour)

> { hour: 6 }

# File lib/montrose/clock.rb, line 120
def unit_step(unit, *alternates)
  is_frequency = @every == unit
  if ([unit] + alternates).any? { |u| @options.key?(u) } && !is_frequency
    # smallest unit, increment by 1
    {step_key(unit) => 1}
  elsif is_frequency
    {step_key(unit) => @interval}
  end
end