quandl_operation 0.1.23 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24dc5a778c39638babaa1bb5640e042a26ffba1c
4
- data.tar.gz: c4f5211b7f4425f872939e7bb08c12a955af4691
3
+ metadata.gz: f793e84f6b1444296a2139214ac181e0a3175db5
4
+ data.tar.gz: 1e07e11fac0532a64bb51a61227b76d33ba20ff6
5
5
  SHA512:
6
- metadata.gz: d12d77624a61d51560f2d214189b826174a8bc291460a2651d8075fe398418925fc4e6fb1bda4155d7f566ce70932edc8858330c477f4c2d8191f420f70e5f85
7
- data.tar.gz: 60f8fdb3179b09437abe62f09dd720d43167ce3bab8ca5ad567c56450aba674c870738f9410f926d63be54bd559e0e042465720b719a080d8cb8bcc3ae1d501e
6
+ metadata.gz: 72f3392d5646b4fac36ac7d83b11c0d53481b1bb4ed12c237b40c7acdb554f35450e9376ff6000fa3cb80fe3dd3c52116011301090bdf4dc7c2273ba0e5ab341
7
+ data.tar.gz: 8bd50d06f6f8b57789694840594b9ff34e3326052cb05d4bc2f881e302c8432819d587e78217c85ade3866f34d417e14e6786a8c3bf2f98744e659bb342399f3
data/UPGRADE.md CHANGED
@@ -1,7 +1,20 @@
1
+ ## 0.2.0
2
+
3
+ * rename Parse methods to be more informative
4
+ * add qdate
5
+ * reject dates that preceed time
6
+ * add Quandl::Operation::Errors
7
+ * add Quandl::Operation::Errors::UnknownDateFormat
8
+ * Quandl::Operation::Parse.perform(data)
9
+ * outputs dates as Date instead of Integer
10
+ * invalid dates raise date_format_error with informative message
11
+
12
+
1
13
  ## 0.1.22
2
14
 
3
15
  * refactor QDFormat to support full yaml. metadata and data are seperated by a
4
16
 
17
+
5
18
  ## 0.1.21
6
19
 
7
20
  * QDFormat should handle new lines in attributes
@@ -2,6 +2,8 @@ require 'quandl/logger'
2
2
 
3
3
  require "quandl/operation/version"
4
4
 
5
+ require 'csv'
6
+
5
7
  require "active_support"
6
8
  require "active_support/inflector"
7
9
  require "active_support/core_ext/hash"
@@ -11,6 +13,8 @@ require 'quandl/operation/core_ext'
11
13
  require 'quandl/operation/collapse'
12
14
  require 'quandl/operation/transform'
13
15
  require 'quandl/operation/parse'
16
+ require 'quandl/operation/errors'
17
+ require 'quandl/operation/qdate'
14
18
 
15
19
  module Quandl
16
20
  module Operation
@@ -12,23 +12,18 @@ class Collapse
12
12
  return data unless data.is_a?(Array) && data.compact.present?
13
13
  # source order
14
14
  order = Parse.sort_order?(data)
15
+ # ensure data is in expected format
16
+ data = Parse.to_jd(data)
15
17
  # operations expect data in ascending order
16
18
  data = Parse.sort( data, :asc )
17
19
  # collapse
18
- data = collapse_and_log(data, frequency)
20
+ data = collapse(data, frequency)
19
21
  # return to original order
20
22
  data = Parse.sort( data, :desc ) if order == :desc
21
23
  # onwards
22
24
  data
23
25
  end
24
26
 
25
- def collapse_and_log(data, frequency)
26
- t1 = Time.now
27
- r = collapse(data, frequency)
28
- Quandl::Logger.debug "#{self.name}.perform(#{data.try(:count)} rows, #{frequency}) (#{t1.elapsed.microseconds}ms)" if t1.elapsed.microseconds > 1
29
- r
30
- end
31
-
32
27
  def valid_collapse?(type)
33
28
  valid?(type)
34
29
  end
@@ -7,15 +7,12 @@ class Guess
7
7
 
8
8
  def frequency(data)
9
9
  return :annual unless data && data[0] && data[0][0]
10
- t1 = Time.now
11
10
  # find the smallest point of difference between dates
12
11
  gap = find_average_gap(data)
13
12
  # ensure gap is not negative
14
13
  gap = ensure_positive_gap(gap)
15
14
  # determine the freq from the size of the smallest gap
16
- freq = frequency_from_gap(gap)
17
- Quandl::Logger.debug "#{self.name}.perform (#{t1.elapsed.microseconds}ms)" if t1.elapsed.microseconds > 1
18
- freq
15
+ frequency_from_gap(gap)
19
16
  end
20
17
 
21
18
  def find_smallest_gap(data)
@@ -1,6 +1,17 @@
1
1
  class Array
2
2
  def self.forwardable_methods
3
- [:reject, :keep_if, :permutation, :to_a, :cycle, :drop, :take_while, :map, :rotate, :each_slice, :pack, :select!, :combination, :repeated_combination, :shift, :select, :reverse!, :==, :clear, :rotate!, :inspect, :iter_for_each, :sort_by!, :compact!, :|, :copy_data_simple, :nitems, :zip, :take, :rassoc, :flatten!, :join, :compact, :[]=, :frozen?, :slice!, :drop_while, :reverse_each, :shuffle, :slice, :reverse, :insert, :uniq, :first, :count, :fetch, :hash, :to_ary, :find_index, :replace, :-, :product, :iter_for_reverse_each, :pop, :push, :sort, :fill, :uniq!, :length, :&, :flatten, :repeated_permutation, :[], :shuffle!, :sort!, :sample, :include?, :<<, :dimensions, :collect, :+, :rindex, :<=>, :eql?, :indices, :collect!, :iter_for_each_index, :iter_for_each_with_index, :index, :*, :indexes, :copy_data, :delete, :to_s, :assoc, :delete_at, :unshift, :delete_if, :empty?, :reject!, :last, :size, :concat, :map!, :at, :each_index, :transpose, :values_at, :each, :enum_cons, :group_by, :enum_with_index, :entries, :with_object, :chunk, :each_with_index, :min, :inject, :one?, :partition, :enum_slice, :none?, :max_by, :any?, :flat_map, :reduce, :each_entry, :find, :minmax_by, :collect_concat, :each_cons, :member?, :max, :sort_by, :detect, :all?, :minmax, :grep, :each_with_object, :find_all]
3
+ [:reject, :keep_if, :to_a, :cycle, :drop, :map, :rotate, :each_slice, :pack, :select!,
4
+ :combination, :repeated_combination, :shift, :select, :reverse!, :==, :clear, :rotate!, :inspect, :iter_for_each,
5
+ :sort_by!, :compact!, :|, :copy_data_simple, :nitems, :zip, :take, :rassoc, :flatten!, :join, :compact, :[]=,
6
+ :frozen?, :slice!, :drop_while, :reverse_each, :shuffle, :slice, :reverse, :insert, :uniq, :first, :count, :fetch,
7
+ :hash, :to_ary, :find_index, :replace, :-, :product, :iter_for_reverse_each, :pop, :push, :sort, :fill, :uniq!,
8
+ :length, :&, :flatten, :repeated_permutation, :[], :shuffle!, :sort!, :sample, :include?, :<<, :dimensions,
9
+ :collect, :+, :rindex, :<=>, :eql?, :indices, :collect!, :iter_for_each_index, :iter_for_each_with_index, :index,
10
+ :*, :indexes, :copy_data, :delete, :to_s, :assoc, :delete_at, :unshift, :delete_if, :empty?, :reject!, :last,
11
+ :size, :concat, :map!, :at, :each_index, :transpose, :values_at, :each, :enum_cons, :group_by, :enum_with_index,
12
+ :entries, :with_object, :chunk, :each_with_index, :min, :inject, :one?, :partition, :enum_slice, :none?, :max_by,
13
+ :any?, :flat_map, :reduce, :each_entry, :find, :minmax_by, :collect_concat, :each_cons, :member?, :max, :sort_by,
14
+ :detect, :all?, :minmax, :grep, :each_with_object, :find_all]
4
15
  end
5
16
  def average
6
17
  self.sum / self.count
@@ -0,0 +1,5 @@
1
+ module Quandl::Operation::Errors
2
+
3
+ class UnknownDateFormat < StandardError; end
4
+
5
+ end
@@ -1,29 +1,25 @@
1
- require 'csv'
2
-
3
1
  module Quandl
4
2
  module Operation
5
-
3
+
6
4
  class Parse
7
5
 
8
6
  class << self
9
7
 
10
8
  def perform(data)
11
9
  return [] if data.blank?
12
- t1 = Time.now
13
- data = hash(data)
14
- data = csv(data)
15
- data = unknown_date_format_to_julian(data)
16
- # data = sort(data)
17
- Quandl::Logger.debug "#{self.name}.perform (#{t1.elapsed.microseconds}ms)" if t1.elapsed.microseconds > 1
18
- data
10
+ data = hash_to_array(data)
11
+ data = csv_to_array(data)
12
+ # data = to_jd(data)
13
+ data = to_date(data)
14
+ data.dup
19
15
  end
20
16
 
21
- def hash(data)
17
+ def hash_to_array(data)
22
18
  data = data.collect{|k,v| [k] + v } if data.kind_of?(Hash)
23
19
  data
24
20
  end
25
21
 
26
- def csv(data)
22
+ def csv_to_array(data)
27
23
  if data.is_a?(String)
28
24
  data = data.gsub('\n', "\n")
29
25
  data = CSV.parse( data )
@@ -54,62 +50,127 @@ class Parse
54
50
  data.sort_by{|r| r[0] }.reverse
55
51
  end
56
52
 
57
- def unknown_date_format_to_julian(data)
53
+ def to_date(data)
58
54
  return data if data_missing_rows?(data)
59
- date = data[0][0]
60
- # formatted like: "2013-06-18"
61
- return date_to_julian(data) if date.is_a?(String) && date =~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/
62
- # formatted like: "2456463"
63
- return julian_string_to_integer(data)
55
+ # guess the current date format
56
+ format = date_format?(data)
57
+ # convert dates to Date
58
+ case format
59
+ when :date then return data
60
+ when :date_string then return date_strings_to_date( data )
61
+ when :jd, :jd_string then return jds_to_date( data )
62
+ when :unknown then raise_date_format_error!( data[0] )
63
+ end
64
+ # return data
65
+ data
64
66
  end
65
67
 
66
- def date_to_julian(data)
68
+ def to_jd(data)
69
+ return data if data_missing_rows?(data)
70
+ # guess the current date format
71
+ format = date_format?(data)
72
+ # convert dates to Date
73
+ case format
74
+ when :jd then return data
75
+ when :jd_string then return jd_strings_to_jd( data )
76
+ when :date then return dates_to_jd( data )
77
+ when :date_string then return date_strings_to_jd( data )
78
+ when :unknown then raise_date_format_error!( data[0] )
79
+ end
80
+ # return data
81
+ data
82
+ end
83
+
84
+ def date_format?(data)
85
+ value = data[0][0]
86
+ # julian date?
87
+ return :date if value.is_a?(Date)
88
+ return :jd if value.is_a?(Integer)
89
+ return :date_string if value.is_a?(String) && value =~ /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/
90
+ return :jd_string if value.kind_of?(String) && value.numeric?
91
+ return :unknown
92
+ end
93
+
94
+ def dates_to_jd(data)
67
95
  return data if data_missing_rows?(data) || data[0][0].is_a?(Integer)
68
96
  # dont alter by reference
69
97
  result = []
70
98
  # for each row
71
99
  data.each_with_index do |row, index|
72
100
  # copy
73
- nrow = row.dup
101
+ row = row.dup
74
102
  # string to date
75
- date = nrow[0]
76
- date = Date.parse(nrow[0]) if nrow[0].is_a?(String)
103
+ date = row[0]
104
+ date = Date.parse(row[0]) if row[0].is_a?(String)
77
105
  # date to julian
78
- nrow[0] = date.jd if date.respond_to?(:jd)
106
+ row[0] = date.jd if date.respond_to?(:jd)
79
107
  # save result
80
- result[index] = nrow
108
+ result[index] = row
81
109
  end
82
110
  # all done
83
111
  result
84
112
  end
85
-
86
- def julian_to_date(data)
113
+
114
+
115
+ ###################
116
+ # DATES TO JULIAN #
117
+ ###################
118
+
119
+ def jd_strings_to_jd(data)
120
+ # skip when already formatted correctly
121
+ return data if data_missing_rows?(data) || data[0][0].is_a?(Integer)
122
+ # otherwise cast string jds to int
123
+ output = []
124
+ data.each_with_index do |row, index|
125
+ output << parse_jd_string(row) rescue raise_date_format_error!( row, index, :jd_strings_to_jd )
126
+ end
127
+ output
128
+ end
129
+
130
+ def date_strings_to_jd(data)
131
+ # skip when already formatted correctly
87
132
  return data if data_missing_rows?(data) || data[0][0].is_a?(Date)
88
- # dont alter by reference
89
- result = []
90
- # for each row
133
+ # otherwise cast string jds to int
134
+ output = []
91
135
  data.each_with_index do |row, index|
92
- # copy
93
- nrow = row.dup
94
- # parse date
95
- nrow[0] = Date.jd( nrow[0].to_i ) unless nrow[0].is_a?(Date)
96
- # save result
97
- result[index] = nrow
136
+ output << parse_date_string(row).jd rescue raise_date_format_error!( row, index, :date_strings_to_jd )
98
137
  end
99
- # all done
100
- result
138
+ output
139
+ end
140
+
141
+
142
+ #################
143
+ # DATES TO DATE #
144
+ #################
145
+
146
+ def jds_to_date(data)
147
+ return data if data_missing_rows?(data) || data[0][0].is_a?(Date)
148
+ output = []
149
+ data.each_with_index do |row, index|
150
+ output << parse_jd(row) rescue raise_date_format_error!( row, index, :jds_to_date )
151
+ end
152
+ output
101
153
  end
102
154
 
103
- def julian_string_to_integer(data)
155
+ def date_strings_to_date(data)
104
156
  # skip when already formatted correctly
105
- return data if data_missing_rows?(data) || data[0][0].is_a?(Integer) || data[0][0].is_a?(Date)
157
+ return data if data_missing_rows?(data) || data[0][0].is_a?(Date)
106
158
  # otherwise cast string jds to int
107
- data.collect{|r| r[0] = r[0].to_i; r }
159
+ output = []
160
+ data.each_with_index do |row, index|
161
+ output << parse_date_string(row) rescue raise_date_format_error!( row, index, :date_strings_to_date )
162
+ end
163
+ output
108
164
  end
109
165
 
166
+
167
+ ###################
168
+ # VALUES TO FLOAT #
169
+ ###################
170
+
110
171
  def values_to_float(data)
111
172
  # skip unless value is a string
112
- return data if data_missing_rows?(data) || !data[0][1].is_a?(String)
173
+ return data if data_missing_rows?(data) || data[0][1].is_a?(Float)
113
174
  # cast values to float
114
175
  data.collect do |row|
115
176
  new_row = [row[0]]
@@ -121,6 +182,7 @@ class Parse
121
182
  end
122
183
  end
123
184
 
185
+
124
186
  def data_missing_rows?(data)
125
187
  !data_has_rows?(data)
126
188
  end
@@ -129,6 +191,47 @@ class Parse
129
191
  data.is_a?(Array) && data[0].is_a?(Array) && data[0][0].present?
130
192
  end
131
193
 
194
+
195
+ protected
196
+
197
+ def parse_jd(row)
198
+ # parse jd_string
199
+ row = parse_jd_string(row)
200
+ # jd to date
201
+ row[0] = Date.jd( row[0] )
202
+ # onwards
203
+ row
204
+ end
205
+
206
+ def parse_jd_string(row)
207
+ row = row.dup
208
+ row[0] = row[0].to_i
209
+ # dont allow dates that are before 0000
210
+ raise Errors::UnknownDateFormat if row[0] <= 1721058
211
+ row
212
+ end
213
+
214
+ def parse_date_string(row)
215
+ row = row.dup
216
+ # extract date
217
+ date = row[0]
218
+ # split date into parts
219
+ date_values = date.split('-').collect(&:to_i)
220
+ # ensure date is valid
221
+ raise Errors::UnknownDateFormat unless date_values.count == 3
222
+ # add to row
223
+ row[0] = Date.new( *date_values )
224
+ row
225
+ end
226
+
227
+
228
+ private
229
+
230
+ def raise_date_format_error!(row, index = 0, type = :none)
231
+ message = "UnknownDateFormat: '#{row[0]}', index: data[#{index}][0], strategy: '#{type}', row: #{row}"
232
+ raise Errors::UnknownDateFormat, message
233
+ end
234
+
132
235
  end
133
236
 
134
237
  end
@@ -0,0 +1,22 @@
1
+ module Quandl
2
+ module Operation
3
+
4
+ class QDate
5
+
6
+ class << self
7
+ def parse(value)
8
+ date = Date.jd(value.to_i) if value.kind_of?(String) && value.numeric?
9
+ date = Date.jd(value) if value.is_a?(Integer)
10
+ date = Date.parse(value) if value.is_a?(String) && value =~ /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/
11
+ date = value if value.is_a?(Date)
12
+ date = value.to_date if value.respond_to?(:to_date)
13
+ date
14
+ rescue
15
+ nil
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
@@ -1,9 +1,10 @@
1
1
  module Quandl
2
2
  module Operation
3
-
3
+
4
4
  class Transform
5
+
5
6
  class << self
6
-
7
+
7
8
  def perform( data, type )
8
9
  return data unless data.is_a?(Array) && data.compact.present?
9
10
  # original order
@@ -13,20 +14,13 @@ class Transform
13
14
  # operations expect float values
14
15
  data = Parse.values_to_float(data)
15
16
  # transform
16
- data = transform_and_log( data, type )
17
+ data = transform( data, type)
17
18
  # return to original order
18
19
  data = Parse.sort( data, :desc ) if order == :desc
19
20
  # onwards
20
21
  data
21
22
  end
22
23
 
23
- def transform_and_log( data, type)
24
- t1 = Time.now
25
- r = transform( data, type)
26
- Quandl::Logger.debug "#{self.name}.perform(#{data.try(:count)} rows, #{type}) (#{t1.elapsed.microseconds}ms)" if t1.elapsed.microseconds > 1
27
- r
28
- end
29
-
30
24
  def valid_transformation?(type)
31
25
  valid?(type)
32
26
  end
@@ -164,6 +158,7 @@ class Transform
164
158
  end
165
159
 
166
160
  end
161
+
167
162
  end
168
163
  end
169
164
  end
@@ -1,5 +1,5 @@
1
1
  module Quandl
2
2
  module Operation
3
- VERSION = "0.1.23"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -4,39 +4,66 @@ require 'spec_helper'
4
4
  describe Quandl::Operation::Parse do
5
5
  subject{ Quandl::Operation::Parse }
6
6
  let(:escaped_csv){ '2444628,0.00385,0.001,0.123,0.00631,0.534\n2444627,0.00384,0.00159507,0.0056,0.00628948,0.009896' }
7
- let(:data_array){ [[ 2444628,0.00385,0.001,0.123,0.00631,0.534], [ 2444627,0.00384,0.00159507,0.0056,0.00628948,0.009896 ]] }
8
-
7
+ let(:data_array){ [[ Date.jd(2444628),0.00385,0.001,0.123,0.00631,0.534], [ Date.jd(2444627),0.00384,0.00159507,0.0056,0.00628948,0.009896 ]] }
8
+
9
9
  let(:csv_data){ "#{Date.today}, 1.0, 2.0" }
10
10
  let(:hash_data){ { Date.today.to_s => [ 1.0, 2.0 ] } }
11
11
  let(:array_data){ [[ Date.today.to_s, 1.0, 2.0 ]] }
12
12
  let(:julian_data){ [[ Date.today.jd, 1.0, 2.0 ]] }
13
+ let(:date_data){ [[ Date.today, 1.0, 2.0 ]] }
13
14
 
14
15
  it "#hash outputs array" do
15
- subject.hash( hash_data ).should eq array_data
16
+ subject.hash_to_array( hash_data ).should eq array_data
16
17
  end
17
18
 
18
19
  it "#csv outputs array" do
19
- subject.csv( csv_data ).should eq array_data
20
+ subject.csv_to_array( csv_data ).should eq array_data
20
21
  end
21
22
 
22
23
  describe "#perform" do
23
- it "should handle csv_data" do
24
- subject.perform( csv_data ).should eq julian_data
25
- end
26
- it "should handle julian_data" do
27
- subject.perform( julian_data ).should eq julian_data
28
- end
29
- it "should handle hash_data" do
30
- subject.perform( hash_data ).should eq julian_data
24
+
25
+ [:csv, :hash, :array, :julian, :date].each do |type|
26
+ context "#{type} data" do
27
+ it "should eq date_data" do
28
+ subject.perform( self.send("#{type}_data") ).should eq date_data
29
+ end
30
+ it "values should be_a Float" do
31
+ subject.perform( self.send("#{type}_data") ).each{|r| r[1..-1].each{|v| v.should be_a Float } }
32
+ end
33
+ end
31
34
  end
32
- it "should handle array_data" do
33
- subject.perform( array_data ).should eq julian_data
35
+
36
+
37
+ let(:csv1){ "2012-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,27.5,25.0,18.0,33.99,0.0,25.0,0.0,10.0,22.0,34.0,10.0,20.0,26.0,0.0,18.5,25.0,33.0,30.0,20.0,27.5,10.0,19.0,25.0,29.0,23.0,25.0,21.0,30.0,28.0,24.5,33.33,0.0,29.48,10.0,20.0,31.0,0.0,35.0,16.5,19.0,20.0,32.45,25.0,12.5,0.0,25.0,31.4,33.33,38.01,0.0,14.0,20.0,30.0,24.2,15.0,15.0,20.0,12.5,15.0,28.8,12.0,10.0,30.0,25.0,35.0,15.0,30.0,9.0,32.0,34.0,25.0,28.0,30.0,28.0,12.0,35.0,25.0,30.0,10.0,30.0,30.0,19.0,25.0,10.0,16.0,20.0,0.0,27.0,20.0,10.0,17.0,19.0,18.0,34.55,30.0,28.0,0.0,34.5,35.0,26.3,21.17,28.0,17.0,30.0,23.0,25.0,30.0,20.0,30.0,21.0,55.0,24.0,40.0,25.0,0.0,34.0,25.0,20.0,35.0,25.75,29.02,33.0,22.89,20.5,28.3,28.6,22.6,25.25,24.43\n2011-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,27.5,25.0,24.0,33.99,0.0,0.0,0.0,10.0,22.0,34.0,10.0,20.0,28.0,0.0,20.0,25.0,33.0,30.0,20.0,34.5,10.0,19.0,25.0,29.0,24.0,20.0,21.0,0.0,28.0,26.0,33.33,0.0,29.37,10.0,20.0,31.0,0.0,35.0,16.5,19.0,20.0,32.44,25.0,12.5,0.0,24.0,31.4,33.33,40.69,0.0,14.0,20.0,0.0,22.0,15.0,15.0,20.0,12.5,15.0,28.8,12.0,10.0,0.0,25.0,35.0,15.0,30.0,9.0,32.0,34.0,25.0,28.0,30.0,28.0,12.0,35.0,25.0,30.0,10.0,30.0,30.0,19.0,25.0,10.0,16.0,20.0,0.0,27.0,20.0,10.0,17.0,19.0,20.0,34.55,30.0,28.0,0.0,34.5,35.0,26.3,21.17,28.0,17.0,30.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,26.0,40.0,25.0,0.0,34.0,25.0,20.0,35.0,25.75,28.55,34.0,23.1,20.88,29.02,28.6,22.8,25.5,24.52\n2010-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,27.5,25.0,24.0,33.99,0.0,25.0,0.0,10.0,25.0,34.0,10.0,20.0,31.0,0.0,17.0,25.0,33.0,30.0,20.0,0.0,10.0,19.0,25.0,25.0,25.0,20.0,21.0,0.0,28.0,26.0,33.33,0.0,29.41,22.0,24.0,31.0,0.0,25.0,16.5,19.0,18.0,33.99,25.0,12.5,0.0,25.0,31.4,33.33,40.69,0.0,14.0,20.0,0.0,24.2,15.0,15.0,40.0,0.0,15.0,28.59,12.0,10.0,0.0,25.0,35.0,15.0,30.0,9.0,32.0,0.0,25.5,30.0,30.0,28.0,12.0,35.0,27.5,30.0,10.0,30.0,30.0,19.0,25.0,10.0,16.0,20.0,0.0,27.0,20.0,10.0,17.0,19.0,20.0,34.55,30.0,35.0,0.0,0.0,15.0,26.3,21.17,28.0,17.0,30.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,28.0,40.0,25.0,0.0,34.0,25.0,35.0,35.0,25.75,28.38,35.5,23.96,21.52,27.52,29.0,23.04,25.79,24.71\n2009-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,27.5,25.0,24.0,33.99,0.0,0.0,0.0,10.0,25.0,34.0,10.0,0.0,33.0,0.0,17.0,25.0,33.0,30.0,20.0,0.0,10.0,20.0,25.0,25.0,25.0,20.0,21.0,0.0,29.0,26.0,33.33,0.0,29.44,27.0,25.0,31.0,0.0,30.0,16.5,16.0,15.0,33.99,28.0,12.5,0.0,26.0,31.4,33.33,40.69,0.0,25.0,20.0,0.0,24.2,15.0,15.0,40.0,0.0,20.0,28.59,12.0,10.0,0.0,25.0,35.0,15.0,28.0,9.0,32.0,0.0,25.5,30.0,30.0,28.0,12.0,35.0,30.0,30.0,10.0,30.0,30.0,19.0,25.0,35.0,16.0,20.0,0.0,27.0,20.0,10.0,18.0,19.0,21.0,34.55,30.0,35.0,0.0,0.0,15.0,26.3,21.17,28.0,25.0,30.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,28.0,40.0,25.0,0.0,34.0,25.0,35.0,35.0,30.9,28.75,36.5,25.73,21.7,27.96,29.2,23.22,25.73,25.4\n2008-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,30.0,25.0,24.0,33.99,0.0,0.0,0.0,10.0,25.0,34.0,10.0,0.0,33.5,0.0,17.0,25.0,33.0,30.0,20.0,0.0,10.0,21.0,25.0,25.0,25.0,20.0,21.0,0.0,31.0,26.0,33.33,0.0,29.51,33.0,25.0,31.0,0.0,30.0,16.5,16.0,15.0,33.99,30.0,12.5,0.0,27.0,31.4,33.33,40.69,0.0,25.0,30.0,0.0,27.5,55.0,15.0,40.0,0.0,15.0,29.63,12.0,10.0,0.0,26.0,35.0,15.0,28.0,9.0,32.0,0.0,25.5,30.0,30.0,28.0,12.0,35.0,30.0,30.0,10.0,30.0,35.0,19.0,25.0,35.0,16.0,24.0,0.0,27.0,20.0,10.0,18.0,19.0,22.0,34.55,30.0,35.0,0.0,0.0,15.0,28.0,21.17,28.0,25.0,0.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,30.0,40.0,25.0,0.0,34.0,28.0,35.0,35.0,30.9,28.65,36.75,27.99,22.0,27.96,29.6,23.29,26.08,26.12\n2007-12-31,20.0,20.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,30.0,25.0,24.0,33.99,0.0,0.0,0.0,10.0,25.0,34.0,10.0,0.0,36.1,0.0,17.0,33.0,34.0,30.0,20.0,0.0,10.0,24.0,25.0,25.0,25.0,20.0,22.0,0.0,31.0,26.0,33.33,0.0,38.36,35.0,25.0,31.0,0.0,30.0,17.5,16.0,18.0,33.99,30.0,12.5,0.0,29.0,37.25,33.33,40.69,0.0,25.0,30.0,0.0,27.5,55.0,15.0,40.0,0.0,15.0,29.63,12.0,12.0,0.0,27.0,35.0,22.5,28.0,9.0,32.0,0.0,25.5,33.0,30.0,28.0,12.0,35.0,30.0,30.0,10.0,30.0,35.0,19.0,25.0,35.0,16.0,24.0,0.0,27.0,20.0,10.0,20.0,19.0,23.0,36.89,32.5,35.0,0.0,0.0,30.0,28.0,21.32,28.0,25.0,0.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,30.0,40.0,30.0,0.0,34.0,28.0,35.0,35.0,30.9,30.56,38.05,28.46,23.01,28.3,30.2,24.11,27.08,26.96\n"}
38
+ let(:csv2){ "2012-03-07,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-06,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-05,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-04,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-29,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-28,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n" }
39
+
40
+ [:csv1, :csv2].each do |type|
41
+ context "#{type} data" do
42
+ it "dates should be_a Date" do
43
+ subject.perform( self.send(type) ).each{|r| r[0].should be_a Date }
44
+ end
45
+
46
+ it "values should be_a Float" do
47
+ subject.perform( self.send(type) ).each do |row|
48
+ row[1..-1].each do |value|
49
+ next if value.nil?
50
+ value.should be_a Float
51
+ end
52
+ end
53
+ end
54
+
55
+ end
34
56
  end
35
- it "handles escaped csv_data" do
36
- subject.perform( escaped_csv ).should eq data_array
57
+
58
+ let(:invalid1){ "Date, Column 1, Column 2, C3, C4, C5, C6, C7\n 2012-03-07,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-06,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-05,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-04,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-29,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-28,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n" }
59
+ let(:invalid2){ "2012-03-07,,69.75,69.75,69.75,0.0,0.0,0.0\nDate, Column 1, Column 2, C3, C4, C5, C6, C7\n2012-03-06,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-05,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-04,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-29,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-28,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n" }
60
+
61
+ [:invalid1, :invalid2].each do |type|
62
+ it "#{type} should raise Quandl::Operation::Errors::UnknownDateFormat" do
63
+ expect { Quandl::Operation::Parse.perform( self.send(type) ) }.to raise_error Quandl::Operation::Errors::UnknownDateFormat
64
+ end
37
65
  end
66
+
38
67
  end
39
68
 
40
- end
41
-
42
-
69
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quandl_operation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.23
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Hilscher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-26 00:00:00.000000000 Z
11
+ date: 2013-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -147,7 +147,9 @@ files:
147
147
  - lib/quandl/operation/core_ext/float.rb
148
148
  - lib/quandl/operation/core_ext/string.rb
149
149
  - lib/quandl/operation/core_ext/time.rb
150
+ - lib/quandl/operation/errors.rb
150
151
  - lib/quandl/operation/parse.rb
152
+ - lib/quandl/operation/qdate.rb
151
153
  - lib/quandl/operation/transform.rb
152
154
  - lib/quandl/operation/version.rb
153
155
  - quandl_operation.gemspec