time_array 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +22 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/Guardfile +14 -0
- data/LICENSE.txt +22 -0
- data/README.md +102 -0
- data/Rakefile +10 -0
- data/lib/time_array/array_ext.rb +21 -0
- data/lib/time_array/exceptions.rb +9 -0
- data/lib/time_array/group_hash.rb +31 -0
- data/lib/time_array/hour_array.rb +9 -0
- data/lib/time_array/time_array.rb +305 -0
- data/lib/time_array/units.rb +13 -0
- data/lib/time_array/vector.rb +51 -0
- data/lib/time_array/version.rb +3 -0
- data/lib/time_array.rb +16 -0
- data/spec/array_spec.rb +9 -0
- data/spec/hour_array_spec.rb +9 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/time_array_operations_spec.rb +53 -0
- data/spec/time_array_spec.rb +212 -0
- data/spec/units_spec.rb +20 -0
- data/spec/vector_spec.rb +56 -0
- data/time_array.gemspec +36 -0
- data/usage/usage_01.rb +20 -0
- metadata +232 -0
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
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
data/Gemfile
ADDED
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
|
+
[](https://travis-ci.org/iwan/time_array)
|
4
|
+
[](https://coveralls.io/r/iwan/time_array)
|
5
|
+
[](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,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,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,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
|
data/lib/time_array.rb
ADDED
data/spec/array_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -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
|
data/spec/units_spec.rb
ADDED
@@ -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
|
data/spec/vector_spec.rb
ADDED
@@ -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
|
data/time_array.gemspec
ADDED
@@ -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:
|