lib/groupdate/series.rb in groupdate-1.0.5 vs lib/groupdate/series.rb in groupdate-2.0.0
- old
+ new
@@ -1,19 +1,20 @@
module Groupdate
class Series
- def initialize(relation, field, column, time_zone, time_range, week_start)
+ def initialize(relation, field, column, time_zone, time_range, week_start, day_start)
if time_range.is_a?(Range)
# doesn't matter whether we include the end of a ... range - it will be excluded later
@relation = relation.where("#{column} >= ? AND #{column} <= ?", time_range.first, time_range.last)
else
@relation = relation.where("#{column} IS NOT NULL")
end
@field = field
@time_zone = time_zone
@time_range = time_range
@week_start = week_start
+ @day_start = day_start
end
def build_series(count)
utc = ActiveSupport::TimeZone["UTC"]
@@ -41,41 +42,46 @@
# use first and last values
sorted_keys = count.keys.sort
sorted_keys.first..sorted_keys.last
end
- # determine start time
- time = time_range.first.to_time.in_time_zone(@time_zone)
- starts_at =
- case @field
- when "second"
- time.change(:usec => 0)
- when "minute"
- time.change(:sec => 0)
- when "hour"
- time.change(:min => 0)
- when "day"
- time.beginning_of_day
- when "week"
- # same logic as MySQL group
- weekday = (time.wday - 1) % 7
- (time - ((7 - @week_start + weekday) % 7).days).midnight
- when "month"
- time.beginning_of_month
- else # year
- time.beginning_of_year
- end
+ if time_range.first
+ # determine start time
+ time = time_range.first.to_time.in_time_zone(@time_zone) - @day_start.hours
+ starts_at =
+ case @field
+ when "second"
+ time.change(:usec => 0)
+ when "minute"
+ time.change(:sec => 0)
+ when "hour"
+ time.change(:min => 0)
+ when "day"
+ time.beginning_of_day
+ when "week"
+ # same logic as MySQL group
+ weekday = (time.wday - 1) % 7
+ (time - ((7 - @week_start + weekday) % 7).days).midnight
+ when "month"
+ time.beginning_of_month
+ else # year
+ time.beginning_of_year
+ end
- series = [starts_at]
+ starts_at += @day_start.hours
+ series = [starts_at]
- step = 1.send(@field)
+ step = 1.send(@field)
- while time_range.cover?(series.last + step)
- series << series.last + step
- end
+ while time_range.cover?(series.last + step)
+ series << series.last + step
+ end
- series.map{|s| s.to_time.utc }
+ series.map{|s| s.to_time.utc }
+ else
+ []
+ end
end
Hash[series.map do |k|
[k, count[k] || 0]
end]
@@ -83,9 +89,11 @@
def method_missing(method, *args, &block)
# https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/calculations.rb
if ActiveRecord::Calculations.method_defined?(method)
build_series(@relation.send(method, *args, &block))
+ elsif [:joins, :includes, :where].include?(method)
+ raise NoMethodError, "#{method} must come before the group_by_#{@field} method"
else
raise NoMethodError, "valid methods are: #{ActiveRecord::Calculations.instance_methods.join(", ")}"
end
end