class TimeArray::TimeArray
Attributes
Public Class Methods
# File lib/time_array/time_array.rb, line 23 def initialize(start_time, values=Vector.new, options={}) manage_options options set_start_time start_time set_values values end
Public Instance Methods
# File lib/time_array/time_array.rb, line 182 def *(vec) oper(vec, :*) end
# File lib/time_array/time_array.rb, line 174 def +(vec) oper(vec, :+) end
# File lib/time_array/time_array.rb, line 178 def -(vec) oper(vec, :-) end
# File lib/time_array/time_array.rb, line 186 def /(vec) oper(vec, :/) end
# File lib/time_array/time_array.rb, line 138 def align_with(other_array) # @start_time = other_array.start_time if @start_time.nil? # ==== return self if empty? return clear_data if other_array.empty? new_start_time = [start_time, other_array.start_time].max new_end_time = [end_time, other_array.end_time].min if end_time.nil? || other_array.end_time.nil? || new_start_time>new_end_time clear_data else @v = @v[((new_start_time-start_time)/3600).to_i, 1+((new_end_time-new_start_time)/3600).to_i] end @start_time = new_start_time self end
# File lib/time_array/time_array.rb, line 134 def aligned_with?(other_array) self.start_time==other_array.start_time && @v.size==other_array.size end
Set array values to the given new value
# File lib/time_array/time_array.rb, line 43 def all_to(new_value) @v = Vector.new(@v.size, new_value) self end
Get the average of values
# File lib/time_array/time_array.rb, line 88 def avg(options = {}) c = count(options) return nil if c.zero? # if the array is empty will be returned nil sum(options) / c end
# File lib/time_array/time_array.rb, line 128 def clear_data raise NilStartTimeError if @start_time.nil? @v = Vector.new self end
# File lib/time_array/time_array.rb, line 38 def clone TimeArray.new(@start_time, (@v.clone rescue Vector.new), zone: Time.zone.name) end
Will return a Compact
object, a compacted version of values compact.gu gives the greatest_unit
, compact.v gives the values array
# File lib/time_array/time_array.rb, line 216 def compact gu = greatest_unit puts "gu: #{gu.inspect}" return Compact.new(@v, gu) if gu==:hour i, st, v = 0, @start_time, [] while i<@v.size v << @v[i] next_st = st+1.send(gu) h = (next_st-st)/3600 i = i+h.to_i st = next_st end Compact.new(v, gu) end
Count the values
# File lib/time_array/time_array.rb, line 77 def count(options = {}) if options[:values] raise ArgumentError, "Option not recognized" if !%w(positive negative non_positive non_negative non_zero zero all).include?(options[:values].to_s) @v.send("count_"+options[:values].to_s) else @v.count_all end end
Iterates each hour, the elements are the values of array time_array.each do |value|
value
end
# File lib/time_array/time_array.rb, line 333 def each(&block) @v.each &block end
Iterates each hour, the elements are TimeAndValue
objects time_array.each_with_time do |el|
e.time e.value
end
# File lib/time_array/time_array.rb, line 356 def each_with_time(&block) arr = @v.map.with_index{|v, i| TimeAndValue.new(@start_time+i.hours, v)} arr.each(&block) end
def xy_array(options={}) # for the moment has been left out
# File lib/time_array/time_array.rb, line 118 def empty? @v.nil? || @v.empty? end
Return the time assiociated with the last value
# File lib/time_array/time_array.rb, line 123 def end_time return nil if empty? @start_time + (@v.size-1).hours end
execute the block (likely a calculation) on each vector element. and return a new time_array obj
# File lib/time_array/time_array.rb, line 324 def execute(&block) v = @v.map &block TimeArray.new(@start_time, v, zone: Time.zone.name) end
# File lib/time_array/time_array.rb, line 194 def first_values(number) @v[0,number] end
Find the greatest unit time. If the values are contant along the month, the greatest unit is :month
# File lib/time_array/time_array.rb, line 235 def greatest_unit v = @v.first unit = Unit::YEAR # Unit::ETERNITY each_with_time do |el| # el.time # el.value if v!=el.value if el.time.year_changed? and unit>Unit::YEAR unit = Unit::YEAR else if el.time.month_changed? and unit>Unit::MONTH unit = Unit::MONTH else if el.time.day_changed? and unit>Unit::DAY unit = Unit::DAY else unit = Unit::HOUR break end end end end v = el.value end return Unit.name(unit) end
# File lib/time_array/time_array.rb, line 202 def group_by(interval) raise ArgumentError, "interval not valid. Valid intervals are :hour, :day, :wday, :month, :year" unless Units.valid?(interval) t = start_time h = GroupHash.new{|h,k| h[k]=[]} @v.each do |v| h[t.send(interval)]<<v t+=1.hour end h end
# File lib/time_array/time_array.rb, line 265 def if_zero_then(other_array) return self if other_array.nil? raise NilVectorError if @v.nil? || (other_array.is_a?(TimeArray) && other_array.v.nil?) c = self.clone if other_array.is_a? Numeric default_value = other_array else c.align_with(other_array) end c.size.times do |i| c.set_value(i, default_value || other_array.value(i) || 0.0) if c.value(i).zero? end c end
Get the maximum value
# File lib/time_array/time_array.rb, line 102 def max @v.compact.max rescue nil end
Get the minimum value
# File lib/time_array/time_array.rb, line 95 def min @v.compact.min rescue nil end
get the count of month hours
# File lib/time_array/time_array.rb, line 300 def month_count h = {} @v.size.times do |i| time = @start_time + i.hours h[time.month] ||= 0.0 h[time.month] += 1 end # @v.each_with_index do |value, i| # time = @start_time + i.hours # h[time.month] ||= 0.0 # h[time.month] += 1 # end c = self.clone c.size.times do |i| time = @start_time + i.hours c.set_value(i, h[time.month]) end c end
# File lib/time_array/time_array.rb, line 284 def month_sum h = {} @v.each_with_index do |value, i| time = @start_time + i.hours h[time.month] ||= 0.0 h[time.month] += value end c = self.clone c.size.times do |i| time = @start_time + i.hours c.set_value(i, h[time.month]) end c end
# File lib/time_array/time_array.rb, line 157 def print_values start_time = @start_time - 1.hour @v.collect{|v| "#{(start_time+=1.hour).strftime('%Y-%m-%d %H:%M %a')}\t#{v}" }.join("\n") end
Round every values of the array
# File lib/time_array/time_array.rb, line 109 def round!(ndigit=3) @v.collect!{|e| e.nil? ? nil : e.round(ndigit)} self end
# File lib/time_array/time_array.rb, line 198 def set_value(index, new_value) @v[index]=new_value if index>=0 && index<@v.size end
# File lib/time_array/time_array.rb, line 48 def size @v.size end
get the sum of the values
# File lib/time_array/time_array.rb, line 54 def sum(options = {}) if options[:values] opt = options[:values].to_sym case opt when :positive, :non_negative @v.sum_positive when :negative, :non_positive @v.sum_negative when :zero 0.0 when :all, :non_zero @v.sum_all else raise ArgumentError, "Option '#{opt}' not recognized" end else @v.sum_all end end
# File lib/time_array/time_array.rb, line 34 def time_zone Time.zone end
# File lib/time_array/time_array.rb, line 162 def to_s "Start time: #{@start_time}\nData (size: #{@v.size}):\n#{print_values}" end
mah!
# File lib/time_array/time_array.rb, line 167 def until_the_end_of_the_year(fill_value=0.0) t = Time.zone.parse("#{@start_time.year+1}-01-01") hh = (t-@start_time)/( 60 * 60) # final size @v += Vector.new(hh-@v.size, fill_value) if hh>@v.size self end
# File lib/time_array/time_array.rb, line 190 def value(index) @v[index] end
Get value associated to a date
# File lib/time_array/time_array.rb, line 339 def value_at(datetime_or_year, month=nil, day=nil, hour=nil) if datetime_or_year.is_a? Time dt = datetime_or_year else dt = Time.zone.parse("#{datetime_or_year}-#{month}-#{day} #{hour}:00") end i = ((dt - @start_time)/3600.0).to_i raise DateTimeOutRangeError if i<0 || i>(size-1) value(i) end
# File lib/time_array/time_array.rb, line 30 def zone Time.zone.name end
Private Instance Methods
# File lib/time_array/time_array.rb, line 389 def expand(data) vector = Vector.new raise NilStartTimeError if @start_time.nil? start_time = @start_time.clone prev_value = start_time.send(@unit) data.each do |v| while start_time.send(@unit)==prev_value vector << v start_time+=1.hour end prev_value = start_time.send(@unit) end vector end
# File lib/time_array/time_array.rb, line 431 def floor_start_time(t, unit=:hour) return nil if t.nil? case @unit # when :'15minutes' # t = t - t.sec - (60 * (t.min % 15)) # floor to hour when :hour t = Time.zone.parse("#{t.year}-#{t.month}-#{t.day} #{t.hour}:00:00") # t = t - t.sec - (60 * (t.min % 60)) # floor to hour when :day t = Time.zone.parse("#{t.year}-#{t.month}-#{t.day}") when :month t = Time.zone.parse("#{t.year}-#{t.month}-01") when :year t = Time.zone.parse("#{t.year}-01-01") end t end
# File lib/time_array/time_array.rb, line 451 def manage_options(options) options = options.symbolize_keys.assert_valid_keys(:unit, :zone) # unit options = {unit: :hour}.merge(options) @unit = options[:unit].to_sym Units.validate(@unit) # zone Time.zone = options[:zone] || "Rome" end
¶ ↑
# File lib/time_array/time_array.rb, line 365 def oper(other_array, op) return self if other_array.nil? raise NilVectorError if @v.nil? || (other_array.is_a?(TimeArray) && other_array.v.nil?) c = self.clone if other_array.is_a? Numeric default_value = other_array else c.align_with(other_array) end # c.data(Array.new(other_array.size){[:+, :-].include?(op) ? 0.0 : 1.0}) if @v.nil? c.size.times do |i| c.set_value(i, c.value(i).to_f.send(op, (default_value || other_array.value(i) || 0.0))) end c end
start_time
must be a Time
(or similar) or a String valid start_time
“yyyy”, “yyyy-m”, “yyyy-mm”, “yyyy-mm-dd”, “yyyy-mm-dd yy”
# File lib/time_array/time_array.rb, line 415 def read_start_time(start_time) if start_time.is_a?(String) start_time.gsub!("/", "-") start_time = "20#{r[0]}-01-01" if r = start_time.match(/^\d{2}$/) # "yy" start_time = "#{r[0]}-01-01" if r = start_time.match(/^\d{4}$/) # "yyyy" start_time = "#{r[0]}-01" if r = start_time.match(/^\d{4}-\d{1,2}$/) # "yyyy-m" or "yyyy-mm" start_time = Time.zone.parse(start_time) raise ArgumentError, "Start time not valid" if start_time.nil? end start_time end
# File lib/time_array/time_array.rb, line 406 def set_start_time(start_time) st = read_start_time(start_time) @start_time = floor_start_time(st, @unit) end
# File lib/time_array/time_array.rb, line 383 def set_values(data) # the values are always stored as hour values @v = @unit==:hour ? Vector.new(data) : expand(data) end