time_array 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: aa5896db51acd0cd4c78503ea4ed9c0c1b396090
4
+ data.tar.gz: a4978dc1c86f1f1828e03433d2587fa69c54570b
5
+ SHA512:
6
+ metadata.gz: 0385f2d1d7cac766a234350ab93a058561250689f0c77f7eeb0e1d5cdf8718f8311f7dd06c9322cb7a269e953d75351edba8e001ec1c629b3fb0cd526c29901c
7
+ data.tar.gz: ef291bcbacd519537534ac1c29fe2eb983ac624d288854633233024f232ee95ee4665998bf48a2eff749aff32a977dbd9f8d591ca16639c523adbf5a0188e0ed
data/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
1
+ service_name: travis-ci
2
+ repo_token: TZmnh0d75NP1pE97mc0aiDevTRaIp3ImW
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ cache: bundler
3
+
4
+ rvm:
5
+ - jruby
6
+ - 1.9.3
7
+ - 2.0.0
8
+
9
+ notifications:
10
+ email:
11
+ recipients:
12
+ - iwan.buetti@gmail.com
13
+ on_failure: change
14
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in time_array.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ # Note: The cmd option is now required due to the increasing number of ways
2
+ # rspec may be run, below are examples of the most common uses.
3
+ # * bundler: 'bundle exec rspec'
4
+ # * bundler binstubs: 'bin/rspec'
5
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
6
+ # installed the spring binstubs per the docs)
7
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
8
+ # * 'just' rspec: 'rspec'
9
+ guard :rspec, cmd: 'bundle exec rspec' do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
14
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Iwan Buetti
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # TimeArray
2
+
3
+ [![Build Status](https://travis-ci.org/iwan/time_array.png)](https://travis-ci.org/iwan/time_array)
4
+ [![Coverage Status](https://img.shields.io/coveralls/iwan/time_array.svg)](https://coveralls.io/r/iwan/time_array)
5
+ [![Code Climate](https://codeclimate.com/github/iwan/time_array/badges/gpa.svg)](https://codeclimate.com/github/iwan/time_array)
6
+ Define a tool (a class) to deal with time-related arrays: sums, multiplications, and so on.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'time_array'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install time_array
21
+
22
+ ## Usage
23
+
24
+ ```ruby
25
+ include TimeArray
26
+
27
+ time_arr = TimeArray::TimeArray.new("2014", [2.3], unit: :year)
28
+ ```
29
+ Generate a time-related array: 8760 elements of '2.3' values, one for each hour in the year 2014.
30
+
31
+ You can do the same starting from a standard Array:
32
+ ```ruby
33
+ [2.3].timed("2014", unit: :year)
34
+ ```
35
+
36
+
37
+
38
+ In detail:
39
+ ```ruby
40
+ time_arr = [1,2,3.14,4,5].timed("2014")
41
+ ```
42
+ Instance a structure like this:
43
+
44
+ | Time with zone | Value |
45
+ |---------------------------|------:|
46
+ | 2014-01-01 00:00:00 +0100 | 1 |
47
+ | 2014-01-01 01:00:00 +0100 | 2 |
48
+ | 2014-01-01 02:00:00 +0100 | 3.14 |
49
+ | 2014-01-01 03:00:00 +0100 | 4 |
50
+ | 2014-03-01 04:00:00 +0100 | 5 |
51
+
52
+
53
+
54
+ By default the unit of data you pass is hourly, but you can specify different units: day, month or year. The internal representation of data is always hourly. So your daily data is converted to hourly data.
55
+
56
+ ```ruby
57
+ time_arr = [1,2,3].timed("2014", unit: :day)
58
+ time_arr.size # => 24*3
59
+ ```
60
+
61
+ The other option you can specify is the time zone (by default is 'Rome'), TimeArray use ActiveSupport::TimeWithZone to store the time data.
62
+
63
+ ```ruby
64
+ time_arr = [1,2,3].timed("2014", zone: "Rome")
65
+ time_arr.size # => 3
66
+ ```
67
+
68
+ ### Operations
69
+
70
+ ```ruby
71
+ a = [12].timed("2014", unit: :year)
72
+ b = [4].timed("2014", unit: :year)
73
+ a+b # => will be an array of [16,16,16,...], size of 8760
74
+ a-b # => will be an array of [8,8,8,...], size of 8760
75
+ a*b # => will be an array of [48,48,48,...], size of 8760
76
+ a/b # => will be an array of [3,3,3,...], size of 8760
77
+ ```
78
+ If you sum two arrays that are not aligned (in term of time), the result of the operation will be applied to the intersection of the two arrays:
79
+
80
+ ```ruby
81
+ a = [12].timed("2014", unit: :day) # size of 24
82
+ b = [4, 3].timed("2014", unit: :day) # size of 48
83
+ a.aligned_with? b # => false
84
+ a+b # => will be an array of [16,16,16,...], size of 24
85
+ ```
86
+ The same goes for time_arrays defined in two different time zones:
87
+
88
+ ```ruby
89
+ a = [1,2,3,4,5].timed("2014", zone: "Rome")
90
+ b = [1,2,3].timed("2014", zone: "London")
91
+ a.aligned_with? b # => false
92
+ a+b # => [3,5,7]
93
+ ```
94
+
95
+
96
+ ## Contributing
97
+
98
+ 1. Fork it ( https://github.com/iwan/time_array/fork )
99
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
100
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
101
+ 4. Push to the branch (`git push origin my-new-feature`)
102
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+ # Default directory to look in is `/spec`
5
+ # Run with `bundle exec rake spec`
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.rspec_opts = ['--color', '--format', 'progress']
8
+ end
9
+
10
+ task :default => :spec
@@ -0,0 +1,21 @@
1
+ require 'active_support/core_ext/time/zones'
2
+
3
+ module TimeArray
4
+ module ArrayExt
5
+ module ClassMethods
6
+
7
+ end
8
+
9
+ module InstanceMethods
10
+ def timed(start_time, options={})
11
+ TimeArray.new(start_time, self, options)
12
+ end
13
+ end
14
+
15
+ def self.included(receiver)
16
+ receiver.extend ClassMethods
17
+ receiver.send :include, InstanceMethods
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,9 @@
1
+ module TimeArray
2
+ class NilStartTimeError < RuntimeError
3
+
4
+ end
5
+
6
+ class NilVectorError < RuntimeError
7
+
8
+ end
9
+ end
@@ -0,0 +1,31 @@
1
+ module TimeArray
2
+ class GroupHash < Hash
3
+ def sum(options={})
4
+ if options[:values]
5
+ case options[:values]
6
+ when :positive, :non_negative
7
+ each_pair{|k,v| self[k]=v.sum_positive}
8
+ when :negative, :non_positive
9
+ each_pair{|k,v| self[k]=v.sum_negative}
10
+ when :zero
11
+ each_pair{|k,v| self[k]=0.0}
12
+ when :all, :non_zero
13
+ each_pair{|k,v| self[k]=v.sum_all}
14
+ else
15
+ raise ArgumentError, "Option not recognized"
16
+ end
17
+ else
18
+ each_pair{|k,v| self[k]=v.sum_all}
19
+ end
20
+ end
21
+
22
+ def count(options={})
23
+ if options[:values]
24
+ raise ArgumentError, "Option not recognized" if !%w(positive negative non_positive non_negative non_zero zero all).include?(options[:values].to_s)
25
+ each_pair{|k,v| self[k]=v.send("count_"+options[:values])}
26
+ else
27
+ each_pair{|k,v| self[k]=v.count_all}
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ module TimeArray
2
+ class HourArray
3
+ def initialize
4
+
5
+ end
6
+
7
+
8
+ end
9
+ end
@@ -0,0 +1,305 @@
1
+ require 'active_support/core_ext/time/zones'
2
+ require 'active_support/core_ext/time/calculations'
3
+ require 'active_support/core_ext/numeric/time'
4
+ require 'active_support/core_ext/hash'
5
+
6
+
7
+ module TimeArray
8
+ class TimeArray
9
+ attr_reader :start_time, :v, :unit
10
+
11
+ def initialize(start_time, values=Vector.new, options={})
12
+ manage_options(options)
13
+ set_start_time start_time
14
+ set_values values
15
+ end
16
+
17
+
18
+ def zone
19
+ Time.zone.name
20
+ end
21
+
22
+ def time_zone
23
+ Time.zone
24
+ end
25
+
26
+ def clone
27
+ TimeArray.new(@start_time, (@v.clone rescue Vector.new), zone: Time.zone.name)
28
+ end
29
+
30
+ # Set all vector values to a new value
31
+ def all_to(new_value)
32
+ @v = Vector.new(@v.size, new_value)
33
+ # @v.map!{|e| e=new_value}
34
+ self
35
+ end
36
+
37
+ def size
38
+ @v.size
39
+ end
40
+
41
+
42
+ # get the sum of the values
43
+ def sum(options = {})
44
+ if options[:values]
45
+ opt = options[:values].to_sym
46
+ case opt
47
+ when :positive, :non_negative
48
+ @v.sum_positive
49
+ when :negative, :non_positive
50
+ @v.sum_negative
51
+ when :zero
52
+ 0.0
53
+ when :all, :non_zero
54
+ @v.sum_all
55
+ else
56
+ raise ArgumentError, "Option '#{opt}' not recognized"
57
+ end
58
+ else
59
+ @v.sum_all
60
+ end
61
+ end
62
+
63
+ # alias :+ :sum
64
+
65
+ # Count the values
66
+ def count(options = {})
67
+ if options[:values]
68
+ raise ArgumentError, "Option not recognized" if !%w(positive negative non_positive non_negative non_zero zero all).include?(options[:values].to_s)
69
+ @v.send("count_"+options[:values].to_s)
70
+ else
71
+ @v.count_all
72
+ end
73
+ end
74
+
75
+
76
+ # Get the average of values
77
+ def avg(options = {})
78
+ c = count(options)
79
+ return nil if c.zero? # if the array is empty will be returned nil
80
+ sum(options) / c
81
+ end
82
+
83
+ # Get the minimum value
84
+ def min
85
+ @v.compact.min
86
+ rescue
87
+ nil
88
+ end
89
+
90
+ # Get the maximum value
91
+ def max
92
+ @v.compact.max
93
+ rescue
94
+ nil
95
+ end
96
+
97
+ # Round every values of the array
98
+ def round!(ndigit=3)
99
+ @v.collect!{|e| e.nil? ? nil : e.round(ndigit)}
100
+ self
101
+ end
102
+
103
+ # def xy_array(options={}) # for the moment has been left out
104
+
105
+
106
+
107
+ def empty?
108
+ @v.nil? || @v.empty?
109
+ end
110
+
111
+ # Return the time assiociated with the last value
112
+ def end_time
113
+ return nil if empty?
114
+ @start_time + (@v.size-1).hours
115
+ end
116
+
117
+ def clear_data
118
+ raise NilStartTimeError if @start_time.nil?
119
+ @v = Vector.new
120
+ self
121
+ end
122
+
123
+ def aligned_with?(other_array)
124
+ self.start_time==other_array.start_time && @v.size==other_array.size
125
+ end
126
+
127
+ def align_with(other_array)
128
+ # @start_time = other_array.start_time if @start_time.nil? # ====
129
+ return self if empty?
130
+ return clear_data if other_array.empty?
131
+
132
+
133
+ new_start_time = [start_time, other_array.start_time].max
134
+ new_end_time = [end_time, other_array.end_time].min
135
+
136
+ if end_time.nil? || other_array.end_time.nil? || new_start_time>new_end_time
137
+ clear_data
138
+ else
139
+ @v = @v[((new_start_time-start_time)/3600).to_i, 1+((new_end_time-new_start_time)/3600).to_i]
140
+ end
141
+ @start_time = new_start_time
142
+ self
143
+ end
144
+
145
+
146
+ def print_values
147
+ start_time = @start_time - 1.hour
148
+ @v.collect{|v| "#{(start_time+=1.hour).strftime('%Y-%m-%d %H:%M %a')}\t#{v}" }.join("\n")
149
+ end
150
+
151
+ def to_s
152
+ "Start time: #{@start_time}\nData (size: #{@v.size}):\n#{print_values}"
153
+ end
154
+
155
+ # mah!
156
+ def until_the_end_of_the_year(fill_value=0.0)
157
+ t = Time.zone.parse("#{@start_time.year+1}-01-01")
158
+ hh = (t-@start_time)/( 60 * 60) # final size
159
+ @v += Vector.new(hh-@v.size, fill_value) if hh>@v.size
160
+ self
161
+ end
162
+
163
+ def +(vec)
164
+ oper(vec, :+)
165
+ end
166
+
167
+ def -(vec)
168
+ oper(vec, :-)
169
+ end
170
+
171
+ def *(vec)
172
+ oper(vec, :*)
173
+ end
174
+
175
+ def /(vec)
176
+ oper(vec, :/)
177
+ end
178
+
179
+ def value(index)
180
+ @v[index]
181
+ end
182
+
183
+ def first_values(number)
184
+ @v[0,number]
185
+ end
186
+
187
+ def set_value(index, new_value)
188
+ @v[index]=new_value if index>=0 && index<@v.size
189
+ end
190
+
191
+ def group_by(interval)
192
+ raise ArgumentError, "interval not valid. Valid intervals are :hour, :day, :wday, :month" unless Units.valid?(interval)
193
+ t = start_time
194
+ h = GroupHash.new{|h,k| h[k]=[]}
195
+ @v.each do |v|
196
+ h[t.send(interval)]<<v
197
+ t+=1.hour
198
+ end
199
+ h
200
+ end
201
+
202
+ # ===========================================================
203
+
204
+ private
205
+
206
+
207
+ def oper(other_array, op)
208
+ return self if other_array.nil?
209
+ raise NilVectorError if @v.nil? || (other_array.is_a?(TimeArray) && other_array.v.nil?)
210
+
211
+ c = self.clone
212
+ if other_array.is_a? Numeric
213
+ default_value = other_array
214
+ else
215
+ c.align_with(other_array)
216
+ end
217
+
218
+ # c.data(Array.new(other_array.size){[:+, :-].include?(op) ? 0.0 : 1.0}) if @v.nil?
219
+ c.size.times do |i|
220
+ c.set_value(i, c.value(i).to_f.send(op, (default_value || other_array.value(i) || 0.0)))
221
+ end
222
+ c
223
+ end
224
+
225
+ def set_values(data)
226
+ # the values are always stored as hour values
227
+ @v = @unit==:hour ? Vector.new(data) : expand(data)
228
+ end
229
+
230
+
231
+ def expand(data)
232
+ vector = Vector.new
233
+ raise NilStartTimeError if @start_time.nil?
234
+ start_time = @start_time.clone
235
+
236
+ prev_value = start_time.send(@unit)
237
+ data.each do |v|
238
+ while start_time.send(@unit)==prev_value
239
+ vector << v
240
+ start_time+=1.hour
241
+ end
242
+ prev_value = start_time.send(@unit)
243
+ end
244
+ vector
245
+ end
246
+
247
+ def set_start_time(start_time)
248
+ st = read_start_time(start_time)
249
+ @start_time = floor_start_time(st, @unit)
250
+ end
251
+
252
+
253
+
254
+ # start_time must be a Time (or similar) or a String
255
+ # valid start_time "yyyy", "yyyy-m", "yyyy-mm", "yyyy-mm-dd", "yyyy-mm-dd yy"
256
+ def read_start_time(start_time)
257
+ if start_time.is_a?(String)
258
+ start_time.gsub!("/", "-")
259
+ start_time = "20#{r[0]}-01-01" if r = start_time.match(/^\d{2}$/) # "yy"
260
+ start_time = "#{r[0]}-01-01" if r = start_time.match(/^\d{4}$/) # "yyyy"
261
+ start_time = "#{r[0]}-01" if r = start_time.match(/^\d{4}-\d{1,2}$/) # "yyyy-m" or "yyyy-mm"
262
+ start_time = Time.zone.parse(start_time)
263
+ raise ArgumentError, "Start time not valid" if start_time.nil?
264
+ end
265
+ start_time
266
+ end
267
+
268
+
269
+
270
+
271
+
272
+ def floor_start_time(t, unit=:hour)
273
+ return nil if t.nil?
274
+ case @unit
275
+ # when :'15minutes'
276
+ # t = t - t.sec - (60 * (t.min % 15)) # floor to hour
277
+ when :hour
278
+ t = Time.zone.parse("#{t.year}-#{t.month}-#{t.day} #{t.hour}:00:00")
279
+ # t = t - t.sec - (60 * (t.min % 60)) # floor to hour
280
+ when :day
281
+ t = Time.zone.parse("#{t.year}-#{t.month}-#{t.day}")
282
+ when :month
283
+ t = Time.zone.parse("#{t.year}-#{t.month}-01")
284
+ when :year
285
+ t = Time.zone.parse("#{t.year}-01-01")
286
+ end
287
+ t
288
+ end
289
+
290
+
291
+
292
+ def manage_options(options)
293
+ options = options.symbolize_keys.assert_valid_keys(:unit, :zone)
294
+
295
+ # unit
296
+ options = {unit: :hour}.merge(options)
297
+ @unit = options[:unit].to_sym
298
+ Units.validate(@unit)
299
+
300
+ # zone
301
+ Time.zone = options[:zone] || "Rome"
302
+ end
303
+ end
304
+ end
305
+
@@ -0,0 +1,13 @@
1
+ module TimeArray
2
+ module Units
3
+ LIST = [:hour, :day, :month, :year]
4
+
5
+ def self.valid?(u)
6
+ LIST.include?(u.to_sym)
7
+ end
8
+
9
+ def self.validate(u)
10
+ raise ArgumentError, "Time unit is not valid" if !self.valid?(u)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,51 @@
1
+ module TimeArray
2
+ class Vector < Array
3
+ def clone
4
+ Vector.new(self)
5
+ end
6
+
7
+ def sum_all
8
+ inject(0.0){|total, n| total + (n||0.0) }
9
+ end
10
+
11
+ def sum_positive
12
+ inject(0.0){|total, n| total + (n>0.0 ? n : 0.0) }
13
+ end
14
+
15
+ def sum_negative
16
+ inject(0.0){|total, n| total + (n<0.0 ? n : 0.0) }
17
+ end
18
+
19
+ def count_positive
20
+ count{|e| e>0.0}
21
+ end
22
+
23
+ def count_non_positive
24
+ count{|e| e<=0.0}
25
+ end
26
+
27
+ def count_non_negative
28
+ count{|e| e>=0.0}
29
+ end
30
+
31
+ def count_negative
32
+ count{|e| e<0.0}
33
+ end
34
+
35
+ def count_non_zero
36
+ count{|e| e!=0.0}
37
+ end
38
+
39
+ def count_zero
40
+ count{|e| e==0.0}
41
+ end
42
+
43
+ def count_all
44
+ size
45
+ end
46
+
47
+ def +(o)
48
+ Vector.new(super(o)) # recast
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module TimeArray
2
+ VERSION = "0.5.0"
3
+ end
data/lib/time_array.rb ADDED
@@ -0,0 +1,16 @@
1
+ %w(
2
+ version
3
+ vector
4
+ exceptions
5
+ time_array
6
+ hour_array
7
+ array_ext
8
+ units
9
+ group_hash
10
+ ).each { |file| require File.join(File.dirname(__FILE__), 'time_array', file) }
11
+
12
+
13
+ class Array
14
+ include TimeArray::ArrayExt
15
+ end
16
+
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'array' do
4
+ subject(:a1) { [1,2,3].timed("2014") }
5
+
6
+ it 'init hour array' do
7
+ expect(a1).to be_an_instance_of(TimeArray::TimeArray)
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'hour array' do
4
+ # subject(:a1) { HourArray.new }
5
+
6
+ # it 'init hour array' do
7
+ # expect(a1).to be_an_instance_of(HourArray)
8
+ # end
9
+ end
@@ -0,0 +1,5 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require 'pry'
5
+ require 'time_array'
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'operations' do
4
+ subject(:a1) { TimeArray::TimeArray.new("2013", [2.1], unit: :year) }
5
+ subject(:a2) { TimeArray::TimeArray.new("2013", [3.7], unit: :year) }
6
+
7
+ it 'sum time arrays' do
8
+ b = a1+a2
9
+ expect(b.size).to eq(8760)
10
+ expect(b.sum).to be_within(0.001).of(8760*(2.1+3.7))
11
+
12
+ c = a1+2
13
+ expect(c.size).to eq(8760)
14
+ expect(c.sum).to be_within(0.001).of(8760*(2.1+2))
15
+ end
16
+
17
+ it 'subtract time arrays' do
18
+ b = a1-a2
19
+ expect(b.size).to eq(8760)
20
+ expect(b.sum).to be_within(0.001).of(8760*(2.1-3.7))
21
+
22
+ c = a1-2
23
+ expect(c.size).to eq(8760)
24
+ expect(c.sum).to be_within(0.001).of(8760*(2.1-2))
25
+ end
26
+
27
+ it 'multiply time arrays' do
28
+ b = a1*a2
29
+ expect(b.size).to eq(8760)
30
+ expect(b.sum).to be_within(0.001).of(8760*(2.1*3.7))
31
+
32
+ c = a1*2
33
+ expect(c.size).to eq(8760)
34
+ expect(c.sum).to be_within(0.001).of(8760*(2.1*2))
35
+ end
36
+
37
+ it 'divide time arrays' do
38
+ b = a1/a2
39
+ expect(b.size).to eq(8760)
40
+ expect(b.sum).to be_within(0.001).of(8760*(2.1/3.7))
41
+
42
+ c = a1/2
43
+ expect(c.size).to eq(8760)
44
+ expect(c.sum).to be_within(0.001).of(8760*(2.1/2))
45
+ end
46
+
47
+ it 'divide time arrays by zero' do
48
+ a3 = TimeArray::TimeArray.new("2013", [1,0,1,1,1,1,1,1,1,1,1,1], unit: :month)
49
+ c = a1/a3
50
+ expect(c.size).to eq(8760)
51
+ expect(c.sum).to eq(Float::INFINITY)
52
+ end
53
+ end
@@ -0,0 +1,212 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'time array' do
4
+ subject(:a1) { TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome", unit: :hour) }
5
+ values = [1,2,3]
6
+ subject(:v1) { [0,1,2,-3,0,2,-1] }
7
+ subject(:time_arr) { TimeArray::TimeArray.new("2013", v1) }
8
+
9
+
10
+ it 'init' do
11
+ expect(a1).to be_an_instance_of(TimeArray::TimeArray)
12
+ expect(a1.v).to be_an_instance_of(TimeArray::Vector)
13
+
14
+ expect(TimeArray::TimeArray.new("2013", [1], unit: :year).v.size).to eq(8760)
15
+ expect(TimeArray::TimeArray.new("2012", [1], unit: :year).v.size).to eq(8760+24) # lead year
16
+ expect(TimeArray::TimeArray.new("2013", [1], unit: :month).v.size).to eq(31*24)
17
+ expect(TimeArray::TimeArray.new("2013", [1], unit: :day).v.size).to eq(24)
18
+ expect(TimeArray::TimeArray.new("2013", [1], unit: :hour).v.size).to eq(1)
19
+
20
+ expect(TimeArray::TimeArray.new("2013-04-16", [1], unit: :year).v.size).to eq(8760)
21
+ expect(TimeArray::TimeArray.new("2013-04-16", [1], unit: :month).v.size).to eq(30*24)
22
+ expect(TimeArray::TimeArray.new("2013-04-16", [1], unit: :day).v.size).to eq(24)
23
+ expect(TimeArray::TimeArray.new("2013-04-16", [1], unit: :hour).v.size).to eq(1)
24
+ end
25
+
26
+ it 'unit option on initialize' do
27
+ expect(TimeArray::TimeArray.new("2013", [1,2,3], unit: :hour).unit).to eq(:hour)
28
+ expect(TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome", unit: :hour).unit).to eq(:hour)
29
+ expect(TimeArray::TimeArray.new("2013", [1,2,3], unit: 'hour').unit).to eq(:hour)
30
+ expect(TimeArray::TimeArray.new("2013").unit).to eq(:hour)
31
+
32
+ expect(TimeArray::TimeArray.new("2013", [1,2,3], unit: 'month').unit).to eq(:month)
33
+ expect(TimeArray::TimeArray.new("2013", [1,2,3], unit: 'year').unit).to eq(:year)
34
+ expect(TimeArray::TimeArray.new("2013", [1,2,3], unit: 'day').unit).to eq(:day)
35
+
36
+ expect{ TimeArray::TimeArray.new("2013", [1,2,3], unit: 'foo').unit}.to raise_error(ArgumentError)
37
+ end
38
+
39
+ it 'zone opt on initialize' do
40
+ expect(a1.zone).to eq("Rome")
41
+ expect(TimeArray::TimeArray.new("2013", [1,2,3]).zone).to eq("Rome")
42
+ expect(TimeArray::TimeArray.new("2013", [1,2,3], zone: "London").zone).to eq("London")
43
+ expect(a1.time_zone).to be_an_instance_of(ActiveSupport::TimeZone)
44
+ end
45
+
46
+ it 'start_time on initialize' do
47
+ expect(TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome").start_time.to_s).to eq("2013-01-01 00:00:00 +0100")
48
+ expect(TimeArray::TimeArray.new("2013-03", [1,2,3], zone: "Rome").start_time.to_s).to eq("2013-03-01 00:00:00 +0100")
49
+ expect(TimeArray::TimeArray.new("2013-03-04", [1,2,3], zone: "Rome").start_time.to_s).to eq("2013-03-04 00:00:00 +0100")
50
+ expect(TimeArray::TimeArray.new("2013-03-04 13", [1,2,3], zone: "Rome").start_time.to_s).to eq("2013-03-04 13:00:00 +0100")
51
+ expect{TimeArray::TimeArray.new("foobar", [1,2,3], zone: "Rome").start_time.to_s}.to raise_error(ArgumentError)
52
+ end
53
+
54
+ it 'clone' do
55
+ orig = TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome")
56
+ cloned = orig.clone
57
+ expect(orig.start_time).to equal(orig.start_time)
58
+ expect(cloned.start_time).not_to equal(orig.start_time)
59
+ expect(cloned.v).not_to equal(orig.v)
60
+ # expect(cloned.time_zone).not_to equal(orig.time_zone) # why?
61
+
62
+ end
63
+
64
+ it 'set all values to' do
65
+ x = 3.4
66
+ expect(a1.all_to(x).v).to eq(Array.new(a1.size, x))
67
+ end
68
+
69
+ it 'get values size' do
70
+ expect(a1.size).to eq(3)
71
+ expect(TimeArray::TimeArray.new("2013").size).to eq(0)
72
+ end
73
+
74
+ it 'sum of values' do
75
+ expect(time_arr.sum).to eq(1)
76
+ expect(time_arr.sum).to eq(1.0)
77
+ expect(time_arr.sum(values: :all)).to eq(1)
78
+ expect(time_arr.sum(values: 'all')).to eq(1)
79
+ expect(time_arr.sum(values: :non_zero)).to eq(1)
80
+
81
+ expect(time_arr.sum(values: :positive)).to eq(5)
82
+ expect(time_arr.sum(values: :non_positive)).to eq(-4)
83
+ expect(time_arr.sum(values: :negative)).to eq(-4)
84
+ expect(time_arr.sum(values: :non_negative)).to eq(5)
85
+ expect(time_arr.sum(values: :zero)).to eq(0)
86
+ expect{time_arr.sum(values: :invalid_argument)}.to raise_error(ArgumentError)
87
+ end
88
+
89
+ it 'count of values' do
90
+ expect(time_arr.count).to eq(7)
91
+ expect(time_arr.count).to eq(7.0)
92
+ expect(time_arr.count(values: :all)).to eq(7)
93
+ expect(time_arr.count(values: 'all')).to eq(7)
94
+
95
+ expect(time_arr.count(values: :positive)).to eq(3)
96
+ expect(time_arr.count(values: :non_positive)).to eq(4)
97
+ expect(time_arr.count(values: :negative)).to eq(2)
98
+ expect(time_arr.count(values: :non_negative)).to eq(5)
99
+ expect(time_arr.count(values: :zero)).to eq(2)
100
+ expect(time_arr.count(values: :non_zero)).to eq(5)
101
+ expect{time_arr.count(values: :invalid_argument)}.to raise_error(ArgumentError)
102
+ end
103
+
104
+ it 'average of values' do
105
+ expect(time_arr.avg).to eq(1.0/7)
106
+ expect(time_arr.avg(values: :positive)).to eq(5.0/3)
107
+ expect(time_arr.avg(values: :non_positive)).to eq(-1.0)
108
+ expect(time_arr.avg(values: :negative)).to eq(-2.0)
109
+ expect(time_arr.avg(values: :non_negative)).to eq(1.0)
110
+ expect(time_arr.avg(values: :zero)).to eq(0.0)
111
+ expect{time_arr.avg(values: :invalid_argument)}.to raise_error(ArgumentError)
112
+
113
+ expect(TimeArray::TimeArray.new("2013", [0,1,2,3,0,2,1]).avg(values: :negative)).to be_nil
114
+ end
115
+
116
+ it 'minimum and maximum values' do
117
+ expect(time_arr.min).to eq(-3)
118
+ expect(time_arr.max).to eq(2)
119
+ expect(TimeArray::TimeArray.new("2013", []).max).to be_nil
120
+ expect(TimeArray::TimeArray.new("2013", []).min).to be_nil
121
+ end
122
+
123
+ it 'round values' do
124
+ expect(TimeArray::TimeArray.new("2013", [0.0, 1.23456, nil]).round!(2).v).to eq([0.0, 1.23, nil])
125
+ expect(TimeArray::TimeArray.new("2013", [0.0, 1.23456, nil]).round!(2).v).to be_an_instance_of(TimeArray::Vector)
126
+ end
127
+
128
+ it 'empty' do
129
+ expect(time_arr.empty?).to eq(false)
130
+ expect(TimeArray::TimeArray.new("2013", []).empty?).to eq(true)
131
+ end
132
+
133
+ it 'end time' do
134
+ st = time_arr.start_time
135
+ expect(time_arr.end_time).to eq(st+(v1.size-1).hours)
136
+ end
137
+
138
+ it 'clear data' do
139
+ expect(time_arr.clear_data.empty?).to eq(true)
140
+ end
141
+
142
+ it 'aligned with' do
143
+ a2 = TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome")
144
+ expect(a2.aligned_with?(TimeArray::TimeArray.new("2013", [0,3,0], zone: "Rome"))).to eq(true)
145
+ expect(a2.aligned_with?(TimeArray::TimeArray.new("2013", [0,3], zone: "Rome"))).to eq(false)
146
+ expect(a2.aligned_with?(TimeArray::TimeArray.new("2013", [0,3,4], zone: "London"))).to eq(false)
147
+ expect(a2.aligned_with?(TimeArray::TimeArray.new("2012", [0,3,4], zone: "Rome"))).to eq(false)
148
+ end
149
+
150
+ it 'align with' do
151
+ # case 1. Different data size
152
+ a2 = TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome")
153
+ a3 = TimeArray::TimeArray.new("2013", [4,5], zone: "Rome")
154
+ expect(a2.align_with(a3).v).to eq([1,2])
155
+ a3 = TimeArray::TimeArray.new("2013", [], zone: "Rome")
156
+ expect(a2.align_with(a3).v).to eq([])
157
+
158
+ # case 2. Different zone
159
+ a2 = TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome")
160
+ a3 = TimeArray::TimeArray.new("2013", [4,5,6], zone: "London")
161
+ expect(a2.align_with(a3).v).to eq([2,3])
162
+ a2 = TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome")
163
+ expect(a3.align_with(a2).v).to eq([4,5])
164
+
165
+ a2 = TimeArray::TimeArray.new("2013", [1,2,3], zone: "Rome", unit: :day)
166
+ a3 = TimeArray::TimeArray.new("2013", [4,5,6], zone: "London", unit: :day)
167
+ expect(a2.align_with(a3).size).to eq(24*3-1)
168
+
169
+ # case 2. Different start time (and zone and size)
170
+ a2 = TimeArray::TimeArray.new("2013-03-04 13", [1,2,3,4,5], zone: "Rome")
171
+ a3 = TimeArray::TimeArray.new("2013-03-04 14", [4,5], zone: "London")
172
+ expect(a2.align_with(a3).v).to eq([3,4])
173
+ end
174
+
175
+ it 'print values' do
176
+ a2 = TimeArray::TimeArray.new("2013-03-04 13", [1,2,3], zone: "Rome")
177
+ aa = a2.print_values.split("\n")
178
+ expect(aa.first.split("\t")).to eq(["2013-03-04 13:00 Mon", "1"])
179
+ end
180
+
181
+ it 'fill until the end of the year' do
182
+ a2 = TimeArray::TimeArray.new("2013-02", [10,20,30])
183
+ value = 1
184
+ a2.until_the_end_of_the_year(value)
185
+ size = 8760 - 31*24
186
+ sum = size*value -3 + 10+20+30
187
+ expect(a2.size).to eq(size)
188
+ expect(a2.sum).to eq(sum)
189
+ end
190
+
191
+ it 'get value at' do
192
+ expect(a1.value(0)).to eq(1)
193
+ expect(a1.value(1)).to eq(2)
194
+ expect(a1.value(2)).to eq(3)
195
+ expect(a1.value(20)).to be_nil # out of range!
196
+ end
197
+
198
+
199
+ it 'set value at' do
200
+ a1.set_value(0, 100)
201
+ a1.set_value(2, 234)
202
+ expect(a1.v).to eq([100,2,234])
203
+ a1.set_value(20, 3) # out of range!
204
+ expect(a1.v).to eq([100,2,234])
205
+ end
206
+
207
+ it 'get first x values' do
208
+ arr = Array.new(100){|i| rand(1000)}
209
+ a = TimeArray::TimeArray.new("2013", arr, zone: "Rome", unit: :hour)
210
+ expect(a.first_values(23)).to eq(arr[0...23])
211
+ end
212
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'units' do
4
+ include TimeArray::Units
5
+
6
+
7
+ it 'check if unit is valid' do
8
+ expect(TimeArray::Units.valid?(:hour)).to be true
9
+ expect(TimeArray::Units.valid?("hour")).to be true
10
+ expect(TimeArray::Units.valid?(:day)).to be true
11
+ expect(TimeArray::Units.valid?("day")).to be true
12
+ expect(TimeArray::Units.valid?(:month)).to be true
13
+ expect(TimeArray::Units.valid?("month")).to be true
14
+ expect(TimeArray::Units.valid?(:year)).to be true
15
+ expect(TimeArray::Units.valid?("year")).to be true
16
+
17
+ expect(TimeArray::Units.valid?(:years)).to be false
18
+ expect(TimeArray::Units.valid?("years")).to be false
19
+ end
20
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'vector' do
4
+ subject(:v1) { TimeArray::Vector.new([0,1,2,-3,0,2,-1]) }
5
+
6
+ it 'sum all elements' do
7
+ expect(v1.sum_all).to eq(1)
8
+ end
9
+
10
+ it 'sum positive elements' do
11
+ expect(v1.sum_positive).to eq(5)
12
+ end
13
+
14
+ it 'sum negative elements' do
15
+ expect(v1.sum_negative).to eq(-4)
16
+ end
17
+
18
+
19
+ it 'count pos elements' do
20
+ expect(v1.count_positive).to eq(3)
21
+ end
22
+
23
+ it 'count non pos elements' do
24
+ expect(v1.count_non_positive).to eq(4)
25
+ end
26
+
27
+ it 'count neg elements' do
28
+ expect(v1.count_negative).to eq(2)
29
+ end
30
+
31
+ it 'count non neg elements' do
32
+ expect(v1.count_non_negative).to eq(5)
33
+ end
34
+
35
+ it 'count zero elements' do
36
+ expect(v1.count_zero).to eq(2)
37
+ end
38
+
39
+ it 'count non zero elements' do
40
+ expect(v1.count_non_zero).to eq(5)
41
+ end
42
+
43
+ it 'count zero elements' do
44
+ expect(v1.count_all).to eq(7)
45
+ end
46
+
47
+ it 'clone' do
48
+ expect(v1.clone).not_to equal(v1)
49
+ expect(v1.clone).to eq(v1)
50
+ end
51
+
52
+ it 'sum vectors' do
53
+ v2 = TimeArray::Vector.new([0,1,2,-3,0,2,-1])
54
+ expect(v1+v2).to be_an_instance_of(TimeArray::Vector)
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'time_array/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "time_array"
8
+ spec.version = TimeArray::VERSION
9
+ spec.authors = ["Iwan Buetti"]
10
+ spec.email = ["iwan.buetti@gmail.com"]
11
+ spec.summary = %q{Some tools to deal with time based arrays}
12
+ # spec.description = %q{TODO: Write a longer description. Optional.}
13
+ spec.homepage = "https://github.com/iwan/time_array"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "rspec-nc"
26
+ spec.add_development_dependency "guard"
27
+ spec.add_development_dependency "guard-rspec"
28
+ spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "pry-remote"
30
+ spec.add_development_dependency "pry-nav"
31
+
32
+ spec.add_development_dependency "coveralls"
33
+
34
+ spec.add_dependency("activesupport")
35
+
36
+ end
data/usage/usage_01.rb ADDED
@@ -0,0 +1,20 @@
1
+ require_relative '../lib/time_array'
2
+
3
+
4
+ arr = TimeArray::TimeArray.new("2016-03", [1,2,3])
5
+ puts arr.start_time.to_s
6
+ puts arr.start_time.class
7
+ puts arr.start_time.inspect
8
+
9
+ # puts Time.zone.parse("2014")
10
+ # puts Time.zone.parse("2020-01-02")
11
+
12
+ a = [2,3,4].timed("2012", unit: :day)
13
+ puts a.size
14
+ puts a.v.inspect
15
+
16
+
17
+ puts [1,2,3].timed("2014", unit: :day).size
18
+
19
+ puts arr.group_by(:day)
20
+ puts arr.group_by(:hour)
metadata ADDED
@@ -0,0 +1,232 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: time_array
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Iwan Buetti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-nc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry-remote
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-nav
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: coveralls
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: activesupport
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description:
168
+ email:
169
+ - iwan.buetti@gmail.com
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".coveralls.yml"
175
+ - ".gitignore"
176
+ - ".travis.yml"
177
+ - Gemfile
178
+ - Guardfile
179
+ - LICENSE.txt
180
+ - README.md
181
+ - Rakefile
182
+ - lib/time_array.rb
183
+ - lib/time_array/array_ext.rb
184
+ - lib/time_array/exceptions.rb
185
+ - lib/time_array/group_hash.rb
186
+ - lib/time_array/hour_array.rb
187
+ - lib/time_array/time_array.rb
188
+ - lib/time_array/units.rb
189
+ - lib/time_array/vector.rb
190
+ - lib/time_array/version.rb
191
+ - spec/array_spec.rb
192
+ - spec/hour_array_spec.rb
193
+ - spec/spec_helper.rb
194
+ - spec/time_array_operations_spec.rb
195
+ - spec/time_array_spec.rb
196
+ - spec/units_spec.rb
197
+ - spec/vector_spec.rb
198
+ - time_array.gemspec
199
+ - usage/usage_01.rb
200
+ homepage: https://github.com/iwan/time_array
201
+ licenses:
202
+ - MIT
203
+ metadata: {}
204
+ post_install_message:
205
+ rdoc_options: []
206
+ require_paths:
207
+ - lib
208
+ required_ruby_version: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - ">="
211
+ - !ruby/object:Gem::Version
212
+ version: '0'
213
+ required_rubygems_version: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
218
+ requirements: []
219
+ rubyforge_project:
220
+ rubygems_version: 2.0.3
221
+ signing_key:
222
+ specification_version: 4
223
+ summary: Some tools to deal with time based arrays
224
+ test_files:
225
+ - spec/array_spec.rb
226
+ - spec/hour_array_spec.rb
227
+ - spec/spec_helper.rb
228
+ - spec/time_array_operations_spec.rb
229
+ - spec/time_array_spec.rb
230
+ - spec/units_spec.rb
231
+ - spec/vector_spec.rb
232
+ has_rdoc: