module Stagger

Constants

SECONDS_IN_DAY
VERSION

Public Class Methods

distribute(items, number_of_days, delay: 0) click to toggle source

Evenly distributes items acros business days @param [Array, items] items to stagger @param [Integer, number_of_days] number of business days to distribute within @param [Integer, delay] number of seconds to delay the staggering @return [Array] array of arrays, where first subarray element is a scheduled DateTime, second is the staggered item

# File lib/stagger.rb, line 11
def distribute(items, number_of_days, delay: 0)
  return [] if Array(items).empty? || number_of_days.to_i < 1
  time = get_starting_time(delay)
  period_in_seconds = get_period_in_seconds(items.size, number_of_days, time)
  items.reduce [] do |arr, item|
    if business_day?(time)
      arr << [item, time]
      time = time + period_in_seconds
      arr
    else
      time = time + SECONDS_IN_DAY
      redo
    end
  end
end

Private Class Methods

active_support_time?() click to toggle source
# File lib/stagger.rb, line 74
def active_support_time?
  Time.respond_to?(:zone)
end
at_beginning_of_day(time) click to toggle source
# File lib/stagger.rb, line 57
def at_beginning_of_day(time)
  active_support_time? ? time.at_beginning_of_day : Time.new(time.year, time.month, time.day)
end
at_end_of_day(time) click to toggle source
# File lib/stagger.rb, line 61
def at_end_of_day(time)
  if active_support_time?
    time.at_end_of_day
  else
    at_beginning_of_day(time) + SECONDS_IN_DAY - 0.000000000001
  end
end
business_day?(time) click to toggle source
# File lib/stagger.rb, line 29
def business_day?(time)
  if time.sunday? || time.saturday?
    false
  else
    time
  end
end
current_time() click to toggle source
# File lib/stagger.rb, line 70
def current_time
  active_support_time? ? Time.zone.now : Time.now
end
get_period_in_seconds(items_size, number_of_days, starting_time) click to toggle source
# File lib/stagger.rb, line 48
def get_period_in_seconds(items_size, number_of_days, starting_time)
  now = current_time
  total_period = number_of_days * SECONDS_IN_DAY
  if business_day?(now)
    total_period -= (now - at_beginning_of_day(now))
  end
  total_period / items_size
end
get_starting_time(delay) click to toggle source
# File lib/stagger.rb, line 37
def get_starting_time(delay)
  tc = current_time + delay
  if tc.saturday?
    at_beginning_of_day(tc) + SECONDS_IN_DAY * 2
  elsif tc.sunday?
    at_beginning_of_day(tc) + SECONDS_IN_DAY
  else
    tc
  end
end