Module: RailsuiCharts::Interval

Defined in:
lib/railsui_charts/interval.rb

Overview

Date arithmetic for the supported bucket sizes: truncating a value to the bucket it belongs in, stepping between buckets, and finding the window before a window.

This is plumbing rather than product. Filters needs it to resolve a preset into a range, so it stays here even though the bucketing that builds on it lives in Rails UI Charts Pro.

Constant Summary collapse

SUPPORTED =
%i[hour day week month].freeze

Class Method Summary collapse

Class Method Details

.coerce(value) ⇒ Object



34
35
36
37
38
39
40
41
42
# File 'lib/railsui_charts/interval.rb', line 34

def coerce(value)
  case value
  when Time, DateTime then in_zone(value)
  when Date then value
  when String then parse(value)
  when Numeric then in_zone(Time.at(value))
  else value.respond_to?(:to_time) ? in_zone(value.to_time) : nil
  end
end

.count(range, interval) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/railsui_charts/interval.rb', line 55

def count(range, interval)
  total = 0
  cursor = range.first

  while cursor <= range.last
    total += 1
    cursor = step_forward(cursor, interval)
  end

  total
end

.each(range, interval) ⇒ Object

Every bucket start between the two ends, inclusive.



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/railsui_charts/interval.rb', line 76

def each(range, interval)
  return enum_for(:each, range, interval) unless block_given?

  cursor = truncate(range.first, interval)
  finish = truncate(range.last, interval)

  while cursor <= finish
    yield cursor
    cursor = step_forward(cursor, interval)
  end
end

.preceding(range, interval: :day) ⇒ Object

The equal-length window immediately before this one.



45
46
47
48
49
50
51
52
53
# File 'lib/railsui_charts/interval.rb', line 45

def preceding(range, interval: :day)
  return if range.nil?

  length = count(range, interval)
  finish = step_back(range.first, interval)
  start = length.pred.times.inject(finish) { |value, _| step_back(value, interval) }

  start..finish
end

.step_back(value, interval) ⇒ Object



71
72
73
# File 'lib/railsui_charts/interval.rb', line 71

def step_back(value, interval)
  shift(value, interval, -1)
end

.step_forward(value, interval) ⇒ Object



67
68
69
# File 'lib/railsui_charts/interval.rb', line 67

def step_forward(value, interval)
  shift(value, interval, 1)
end

.truncate(value, interval) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/railsui_charts/interval.rb', line 22

def truncate(value, interval)
  time = coerce(value)
  return if time.nil?

  case interval.to_sym
  when :hour then time.change(min: 0, sec: 0)
  when :week then time.to_date.beginning_of_week
  when :month then time.to_date.beginning_of_month
  else time.to_date
  end
end

.validate!(interval) ⇒ Object

Raises:

  • (ArgumentError)


15
16
17
18
19
20
# File 'lib/railsui_charts/interval.rb', line 15

def validate!(interval)
  interval = interval.to_sym
  raise ArgumentError, "Unsupported interval: #{interval}. Supported: #{SUPPORTED.join(', ')}" unless SUPPORTED.include?(interval)

  interval
end