barometer 0.5.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/README.rdoc +51 -9
  2. data/VERSION.yml +2 -2
  3. data/bin/barometer +57 -7
  4. data/lib/barometer.rb +11 -0
  5. data/lib/barometer/base.rb +3 -0
  6. data/lib/barometer/data.rb +11 -6
  7. data/lib/barometer/data/sun.rb +10 -0
  8. data/lib/barometer/data/zone.rb +79 -188
  9. data/lib/barometer/formats/coordinates.rb +4 -1
  10. data/lib/barometer/formats/geocode.rb +9 -7
  11. data/lib/barometer/formats/icao.rb +2 -2
  12. data/lib/barometer/formats/weather_id.rb +2 -2
  13. data/lib/barometer/measurements/common.rb +113 -0
  14. data/lib/barometer/{data → measurements}/current.rb +17 -42
  15. data/lib/barometer/measurements/forecast.rb +62 -0
  16. data/lib/barometer/measurements/forecast_array.rb +72 -0
  17. data/lib/barometer/{data → measurements}/measurement.rb +57 -45
  18. data/lib/barometer/measurements/night.rb +27 -0
  19. data/lib/barometer/query.rb +55 -5
  20. data/lib/barometer/services.rb +3 -1
  21. data/lib/barometer/translations/icao_country_codes.yml +274 -1
  22. data/lib/barometer/translations/weather_country_codes.yml +189 -6
  23. data/lib/barometer/translations/zone_codes.yml +360 -0
  24. data/lib/barometer/weather.rb +5 -4
  25. data/lib/barometer/weather_services/google.rb +19 -35
  26. data/lib/barometer/weather_services/service.rb +113 -255
  27. data/lib/barometer/weather_services/weather_bug.rb +291 -2
  28. data/lib/barometer/weather_services/weather_dot_com.rb +45 -54
  29. data/lib/barometer/weather_services/wunderground.rb +83 -89
  30. data/lib/barometer/weather_services/yahoo.rb +44 -91
  31. data/lib/barometer/web_services/geocode.rb +1 -0
  32. data/lib/barometer/web_services/timezone.rb +40 -0
  33. data/lib/barometer/web_services/weather_id.rb +17 -2
  34. data/lib/demometer/demometer.rb +28 -0
  35. data/lib/demometer/public/css/master.css +259 -1
  36. data/lib/demometer/public/css/print.css +94 -0
  37. data/lib/demometer/public/css/syntax.css +64 -0
  38. data/lib/demometer/public/images/link-out.gif +0 -0
  39. data/lib/demometer/views/about.erb +10 -0
  40. data/lib/demometer/views/index.erb +2 -0
  41. data/lib/demometer/views/layout.erb +3 -2
  42. data/lib/demometer/views/measurement.erb +4 -1
  43. data/lib/demometer/views/readme.erb +116 -88
  44. data/spec/data/sun_spec.rb +53 -0
  45. data/spec/data/zone_spec.rb +330 -100
  46. data/spec/fixtures/formats/weather_id/ksfo.xml +1 -0
  47. data/spec/fixtures/services/weather_bug/90210_current.xml +1 -0
  48. data/spec/fixtures/services/weather_bug/90210_forecast.xml +1 -0
  49. data/spec/formats/weather_id_spec.rb +10 -5
  50. data/spec/measurements/common_spec.rb +352 -0
  51. data/spec/{data → measurements}/current_spec.rb +40 -103
  52. data/spec/measurements/forecast_array_spec.rb +165 -0
  53. data/spec/measurements/forecast_spec.rb +135 -0
  54. data/spec/{data → measurements}/measurement_spec.rb +86 -107
  55. data/spec/measurements/night_measurement_spec.rb +49 -0
  56. data/spec/query_spec.rb +12 -2
  57. data/spec/spec_helper.rb +28 -1
  58. data/spec/weather_services/google_spec.rb +27 -117
  59. data/spec/weather_services/services_spec.rb +49 -1024
  60. data/spec/weather_services/weather_bug_spec.rb +274 -0
  61. data/spec/weather_services/weather_dot_com_spec.rb +45 -125
  62. data/spec/weather_services/wunderground_spec.rb +42 -136
  63. data/spec/weather_services/yahoo_spec.rb +26 -116
  64. data/spec/weather_spec.rb +45 -45
  65. metadata +27 -11
  66. data/lib/barometer/data/forecast.rb +0 -84
  67. data/lib/barometer/data/night.rb +0 -69
  68. data/lib/barometer/extensions/graticule.rb +0 -51
  69. data/spec/data/forecast_spec.rb +0 -192
  70. data/spec/data/night_measurement_spec.rb +0 -136
@@ -43,9 +43,6 @@ module Barometer
43
43
  @@partner_key = nil
44
44
  @@license_key = nil
45
45
 
46
- def self.source_name; :weather_dot_com; end
47
- def self.accepted_formats; [:short_zipcode, :weather_id]; end
48
-
49
46
  def self.keys=(keys)
50
47
  raise ArgumentError unless keys.is_a?(Hash)
51
48
  keys.each do |key, value|
@@ -54,64 +51,56 @@ module Barometer
54
51
  end
55
52
  end
56
53
 
57
- def self.has_keys?; !@@partner_key.nil? && !@@license_key.nil?; end
58
- def self.requires_keys?; true; end
54
+ #########################################################################
55
+ # PRIVATE
56
+ # If class methods could be private, the remaining methods would be.
57
+ #
58
+
59
+ def self._source_name; :weather_dot_com; end
60
+ def self._accepted_formats; [:short_zipcode, :weather_id]; end
59
61
 
60
- def self.wet_icon_codes
62
+ def self._has_keys?; !@@partner_key.nil? && !@@license_key.nil?; end
63
+ def self._requires_keys?; true; end
64
+
65
+ def self._wet_icon_codes
61
66
  codes = (0..18).to_a + [35] + (37..43).to_a + (45..47).to_a
62
67
  codes.collect {|c| c.to_s}
63
68
  end
64
- def self.sunny_icon_codes
69
+ def self._sunny_icon_codes
65
70
  codes = [19, 22, 28, 30, 32, 34, 36]
66
71
  codes.collect {|c| c.to_s}
67
72
  end
68
73
 
69
- def self._measure(measurement, query, metric=true)
70
- raise ArgumentError unless measurement.is_a?(Data::Measurement)
71
- raise ArgumentError unless query.is_a?(Barometer::Query)
72
- measurement.source = self.source_name
73
-
74
- begin
75
- result = self.fetch(query.q, metric)
76
- rescue Timeout::Error => e
77
- return measurement
78
- end
79
-
80
- measurement.current = self.build_current(result, metric)
81
- measurement.forecast = self.build_forecast(result, metric)
82
- measurement.location = self.build_location(result, query.geo)
83
- measurement.current.sun = self.build_sun(result)
84
-
85
- # add links
86
- if result && result['lnks'] && result['lnks']['link']
87
- result['lnks']['link'].each do |link_hash|
88
- measurement.links[link_hash['t']] = link_hash['l']
74
+ # first try to match the zone code, otherwise use the zone offset
75
+ #
76
+ def self._build_timezone(data)
77
+ if data
78
+ if data['cc'] && data['cc']['lsup'] &&
79
+ (zone_match = data['cc']['lsup'].match(/ ([A-Z]{1,4})$/))
80
+ Data::Zone.new(zone_match[1])
81
+ elsif data['loc'] && data['loc']['zone']
82
+ Data::Zone.new(data['loc']['zone'].to_f)
89
83
  end
90
84
  end
91
-
92
- # set local time of measurement
93
- local_time = self.build_local_time(result)
94
- measurement.measured_at = local_time
95
- measurement.current.current_at = local_time
96
-
97
- measurement
98
85
  end
99
86
 
100
- # WARNING
101
- # this is a best guess method. the data provided for time conversions
102
- # leaves a lot to be desired. some time zones, offsets, local times are
103
- # out to lunch. eg. Tahiti (all times seem to be 30 min off), but there
104
- # is no way to determine this
105
- #
106
- # regardless of the above, this method will trust the data given to it
107
- #
108
- def self.build_local_time(data)
87
+ def self._parse_local_time(data)
109
88
  (data && data['loc']) ? Data::LocalTime.parse(data['loc']['tm']) : nil
110
89
  end
111
-
112
- def self.build_current(data, metric=true)
90
+
91
+ def self._build_links(data)
92
+ links = {}
93
+ if data && data['lnks'] && data['lnks']['link']
94
+ data['lnks']['link'].each do |link_hash|
95
+ links[link_hash['t']] = link_hash['l']
96
+ end
97
+ end
98
+ links
99
+ end
100
+
101
+ def self._build_current(data, metric=true)
113
102
  raise ArgumentError unless data.is_a?(Hash)
114
- current = Data::CurrentMeasurement.new
103
+ current = Measurement::Current.new
115
104
  if data
116
105
  if data['cc']
117
106
  current.updated_at = Data::LocalDateTime.parse(data['cc']['lsup'])
@@ -141,14 +130,14 @@ module Barometer
141
130
  current
142
131
  end
143
132
 
144
- def self.build_forecast(data, metric=true)
133
+ def self._build_forecast(data, metric=true)
145
134
  raise ArgumentError unless data.is_a?(Hash)
146
- forecasts = []
135
+ forecasts = Measurement::ForecastArray.new
147
136
 
148
137
  if data && data['dayf'] && data['dayf']['day']
149
138
  local_date = data['dayf']['lsup']
150
139
  data['dayf']['day'].each do |forecast|
151
- forecast_measurement = Data::ForecastMeasurement.new
140
+ forecast_measurement = Measurement::Forecast.new
152
141
  forecast_measurement.date = Date.parse(forecast['dt'])
153
142
 
154
143
  forecast_measurement.high = Data::Temperature.new(metric)
@@ -180,7 +169,7 @@ module Barometer
180
169
 
181
170
  elsif part['p'] == 'n'
182
171
  # add this to the NightMeasurement
183
- forecast_measurement.night = Data::NightMeasurement.new
172
+ forecast_measurement.night = Measurement::ForecastNight.new
184
173
  forecast_measurement.night.condition = part['t']
185
174
  forecast_measurement.night.icon = part['icon']
186
175
  forecast_measurement.night.pop = part['ppcp'].to_i
@@ -202,7 +191,7 @@ module Barometer
202
191
  forecasts
203
192
  end
204
193
 
205
- def self.build_location(data, geo=nil)
194
+ def self._build_location(data, geo=nil)
206
195
  raise ArgumentError unless data.is_a?(Hash)
207
196
  raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
208
197
  location = Data::Location.new
@@ -224,7 +213,7 @@ module Barometer
224
213
  location
225
214
  end
226
215
 
227
- def self.build_sun(data)
216
+ def self._build_sun(data)
228
217
  raise ArgumentError unless data.is_a?(Hash)
229
218
  sun = nil
230
219
  if data
@@ -239,9 +228,11 @@ module Barometer
239
228
 
240
229
  # use HTTParty to get the current weather
241
230
  #
242
- def self.fetch(query, metric=true)
231
+ def self._fetch(query, metric=true)
232
+ return unless query
233
+ puts "fetch weather.com: #{query.q}" if Barometer::debug?
243
234
  self.get(
244
- "http://xoap.weather.com/weather/local/#{query}",
235
+ "http://xoap.weather.com/weather/local/#{query.q}",
245
236
  :query => { :par => @@partner_key, :key => @@license_key,
246
237
  :prod => "xoap", :link => "xoap", :cc => "*",
247
238
  :dayf => "5", :unit => (metric ? 'm' : 's')
@@ -46,72 +46,63 @@ module Barometer
46
46
  #
47
47
  class WeatherService::Wunderground < WeatherService
48
48
 
49
- def self.source_name; :wunderground; end
50
- def self.accepted_formats
49
+ #########################################################################
50
+ # PRIVATE
51
+ # If class methods could be private, the remaining methods would be.
52
+ #
53
+
54
+ def self._source_name; :wunderground; end
55
+ def self._accepted_formats
51
56
  [:zipcode, :postalcode, :icao, :coordinates, :geocode]
52
57
  end
53
58
 
54
59
  # these are the icon codes that indicate "wet", used by wet? function
55
- def self.wet_icon_codes
60
+ def self._wet_icon_codes
56
61
  %w(flurries rain sleet snow tstorms nt_flurries nt_rain nt_sleet nt_snow nt_tstorms chancerain chancetstorms)
57
62
  end
58
63
  # these are the icon codes that indicate "sun", used by sunny? function
59
- def self.sunny_icon_codes
64
+ def self._sunny_icon_codes
60
65
  %w(clear mostlysunny partlysunny sunny partlycloudy)
61
66
  end
62
67
 
63
- def self._measure(measurement, query, metric=true)
64
- raise ArgumentError unless measurement.is_a?(Data::Measurement)
65
- raise ArgumentError unless query.is_a?(Barometer::Query)
66
- measurement.source = self.source_name
67
-
68
- begin
69
- current_result = self.get_current(query.q)
70
- measurement.current = self.build_current(current_result, metric)
71
- rescue Timeout::Error => e
72
- return measurement
73
- end
74
-
75
- begin
76
- forecast_result = self.get_forecast(query.q)
77
- measurement.forecast = self.build_forecast(forecast_result, metric)
78
- rescue Timeout::Error => e
79
- return measurement
80
- end
81
-
82
- measurement.location = self.build_location(current_result)
83
- measurement.station = self.build_station(current_result)
84
- measurement.timezone = self.build_timezone(forecast_result)
85
-
86
- if current_result["credit"] && current_result["credit_URL"]
87
- measurement.links[current_result["credit"]] = current_result["credit_URL"]
88
- end
89
-
90
- sun = nil
91
- if measurement.current
92
- sun = self.build_sun(forecast_result, measurement.timezone)
93
- measurement.current.sun = sun
94
- end
68
+ def self._build_extra(measurement, result, metric=true)
69
+ #raise ArgumentError unless measurement.is_a?(Data::Measurement)
70
+ #raise ArgumentError unless query.is_a?(Barometer::Query)
71
+
95
72
  # use todays sun data for all future days
96
- if measurement.forecast && sun
73
+ if measurement.forecast && measurement.current.sun
97
74
  measurement.forecast.each do |forecast|
98
- forecast.sun = sun
75
+ forecast.sun = measurement.current.sun
99
76
  end
100
77
  end
101
78
 
102
- local_time = measurement.timezone ? Data::LocalTime.parse(
103
- measurement.timezone.utc_to_local(Time.now.utc)
104
- ) : nil
105
- measurement.measured_at = local_time
106
- measurement.current.current_at = local_time
107
-
108
79
  measurement
109
80
  end
81
+
82
+ def self._parse_full_timezone(data)
83
+ raise ArgumentError unless data.is_a?(Hash)
84
+ if data && data['simpleforecast'] &&
85
+ data['simpleforecast']['forecastday'] &&
86
+ data['simpleforecast']['forecastday'].first &&
87
+ data['simpleforecast']['forecastday'].first['date']
88
+ Data::Zone.new(
89
+ data['simpleforecast']['forecastday'].first['date']['tz_long']
90
+ )
91
+ end
92
+ end
110
93
 
111
- def self.build_current(data, metric=true)
94
+ def self._build_links(data)
95
+ links = {}
96
+ if data["credit"] && data["credit_URL"]
97
+ links[data["credit"]] = data["credit_URL"]
98
+ end
99
+ links
100
+ end
101
+
102
+ def self._build_current(data, metric=true)
112
103
  raise ArgumentError unless data.is_a?(Hash)
113
104
 
114
- current = Data::CurrentMeasurement.new
105
+ current = Measurement::Current.new
115
106
  current.updated_at = Data::LocalDateTime.parse(data['observation_time']) if data['observation_time']
116
107
  current.humidity = data['relative_humidity'].to_i
117
108
  current.icon = data['icon'] if data['icon']
@@ -142,15 +133,15 @@ module Barometer
142
133
  current
143
134
  end
144
135
 
145
- def self.build_forecast(data, metric=true)
136
+ def self._build_forecast(data, metric=true)
146
137
  raise ArgumentError unless data.is_a?(Hash)
147
- forecasts = []
138
+ forecasts = Measurement::ForecastArray.new
148
139
  # go through each forecast and create an instance
149
140
  if data && data['simpleforecast'] &&
150
141
  data['simpleforecast']['forecastday']
151
142
 
152
143
  data['simpleforecast']['forecastday'].each do |forecast|
153
- forecast_measurement = Data::ForecastMeasurement.new
144
+ forecast_measurement = Measurement::Forecast.new
154
145
  forecast_measurement.icon = forecast['icon']
155
146
  forecast_measurement.date = Date.parse(forecast['date']['pretty'])
156
147
  forecast_measurement.pop = forecast['pop'].to_i
@@ -166,8 +157,8 @@ module Barometer
166
157
  end
167
158
  forecasts
168
159
  end
169
-
170
- def self.build_location(data)
160
+
161
+ def self._build_location(data, geo=nil)
171
162
  raise ArgumentError unless data.is_a?(Hash)
172
163
  location = Data::Location.new
173
164
  if data['display_location']
@@ -183,7 +174,7 @@ module Barometer
183
174
  location
184
175
  end
185
176
 
186
- def self.build_station(data)
177
+ def self._build_station(data)
187
178
  raise ArgumentError unless data.is_a?(Hash)
188
179
  station = Data::Location.new
189
180
  station.id = data['station_id']
@@ -200,69 +191,72 @@ module Barometer
200
191
  station
201
192
  end
202
193
 
203
- def self.build_timezone(data)
204
- raise ArgumentError unless data.is_a?(Hash)
205
- timezone = nil
206
- if data && data['simpleforecast'] &&
207
- data['simpleforecast']['forecastday'] &&
208
- data['simpleforecast']['forecastday'].first &&
209
- data['simpleforecast']['forecastday'].first['date']
210
- timezone = Data::Zone.new(
211
- data['simpleforecast']['forecastday'].first['date']['tz_long']
212
- )
213
- end
214
- timezone || Data::Zone.new(nil)
215
- end
216
-
217
- def self.build_sun(data, timezone)
194
+ def self._build_sun(data)
218
195
  raise ArgumentError unless data.is_a?(Hash)
219
- raise ArgumentError unless timezone.is_a?(Data::Zone)
220
196
  sun = nil
221
197
  if data
222
198
  if data['moon_phase']
223
- if data['moon_phase']['sunrise']
224
- rise = Data::LocalTime.new(
225
- data['moon_phase']['sunrise']['hour'].to_i,
226
- data['moon_phase']['sunrise']['minute'].to_i
227
- )
228
- end
229
- if data['moon_phase']['sunset']
230
- set = Data::LocalTime.new(
231
- data['moon_phase']['sunset']['hour'].to_i,
232
- data['moon_phase']['sunset']['minute'].to_i
233
- )
234
- end
235
-
236
- sun = Data::Sun.new(
237
- rise,
238
- set
239
- )
199
+ rise = Data::LocalTime.new(
200
+ data['moon_phase']['sunrise']['hour'].to_i,
201
+ data['moon_phase']['sunrise']['minute'].to_i
202
+ ) if data['moon_phase']['sunrise']
203
+ set = Data::LocalTime.new(
204
+ data['moon_phase']['sunset']['hour'].to_i,
205
+ data['moon_phase']['sunset']['minute'].to_i
206
+ ) if data['moon_phase']['sunset']
207
+ sun = Data::Sun.new(rise,set)
240
208
  end
241
209
  end
242
210
  sun || Data::Sun.new
243
211
  end
244
212
 
213
+ # override default _fetch behavior
214
+ # this service requires TWO seperate http requests (one for current
215
+ # and one for forecasted weather) ... combine the results
216
+ #
217
+ def self._fetch(query, metric=true)
218
+ result = []
219
+ result << _fetch_current(query)
220
+ result << _fetch_forecast(query)
221
+ result
222
+ end
223
+
245
224
  # use HTTParty to get the current weather
246
- def self.get_current(query)
225
+ #
226
+ def self._fetch_current(query)
247
227
  return unless query
228
+ puts "fetch wunderground current: #{query.q}" if Barometer::debug?
248
229
  self.get(
249
230
  "http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml",
250
- :query => {:query => query},
231
+ :query => {:query => query.q},
251
232
  :format => :xml,
252
233
  :timeout => Barometer.timeout
253
234
  )['current_observation']
254
235
  end
255
236
 
256
237
  # use HTTParty to get the forecasted weather
257
- def self.get_forecast(query)
238
+ #
239
+ def self._fetch_forecast(query)
258
240
  return unless query
241
+ puts "fetch wunderground forecast: #{query.q}" if Barometer::debug?
259
242
  self.get(
260
243
  "http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml",
261
- :query => {:query => query},
244
+ :query => {:query => query.q},
262
245
  :format => :xml,
263
246
  :timeout => Barometer.timeout
264
247
  )['forecast']
265
248
  end
266
249
 
250
+ # since we have two sets of data, override these calls to choose the
251
+ # right set of data
252
+ #
253
+ def self._current_result(data); data[0]; end
254
+ def self._forecast_result(data=nil); data[1]; end
255
+ def self._location_result(data=nil); data[0]; end
256
+ def self._station_result(data=nil); data[0]; end
257
+ def self._links_result(data=nil); data[0]; end
258
+ def self._sun_result(data=nil); data[1]; end
259
+ def self._timezone_result(data=nil); data[1]; end
260
+
267
261
  end
268
262
  end
@@ -45,103 +45,54 @@ module Barometer
45
45
  #
46
46
  class WeatherService::Yahoo < WeatherService
47
47
 
48
- def self.source_name; :yahoo; end
49
- def self.accepted_formats; [:zipcode, :weather_id]; end
48
+ #########################################################################
49
+ # PRIVATE
50
+ # If class methods could be private, the remaining methods would be.
51
+ #
50
52
 
51
- # these are the icon codes that indicate "wet", used by wet? function
52
- def self.wet_icon_codes
53
+ def self._source_name; :yahoo; end
54
+ def self._accepted_formats; [:zipcode, :weather_id]; end
55
+
56
+ def self._wet_icon_codes
53
57
  codes = [1] + (3..18).to_a + [35] + (37..43).to_a + (45..47).to_a
54
58
  codes.collect {|c| c.to_s}
55
59
  end
56
- def self.sunny_icon_codes
60
+ def self._sunny_icon_codes
57
61
  codes = (29..34).to_a + [36]
58
62
  codes.collect {|c| c.to_s}
59
63
  end
60
-
61
- def self._measure(measurement, query, metric=true)
62
- raise ArgumentError unless measurement.is_a?(Data::Measurement)
63
- raise ArgumentError unless query.is_a?(Barometer::Query)
64
- measurement.source = self.source_name
65
-
66
- begin
67
- result = self.fetch(query.q, metric)
68
- rescue Timeout::Error => e
69
- return measurement
70
- end
71
-
72
- measurement.current = self.build_current(result, metric)
73
- measurement.forecast = self.build_forecast(result, metric)
74
- measurement.location = self.build_location(result, query.geo)
75
-
76
- if result["title"] && result["link"]
77
- measurement.links[result["title"]] = result["link"]
78
- end
79
-
80
- sun = nil
81
- if measurement.current
82
- sun = self.build_sun(result)
83
- measurement.current.sun = sun
84
- end
85
- # use todays sun data for all future days
86
- if measurement.forecast && sun
87
- measurement.forecast.each do |forecast|
88
- forecast.sun = sun
89
- end
90
- end
91
-
92
- local_time = self.build_local_time(result)
93
- if local_time
94
- measurement.measured_at = local_time
95
- measurement.current.current_at = local_time
64
+
65
+ def self._build_extra(measurement, result, metric=true)
66
+ #raise ArgumentError unless measurement.is_a?(Data::Measurement)
67
+ #raise ArgumentError unless query.is_a?(Barometer::Query)
68
+
69
+ # use todays sun data for all future days
70
+ if measurement.forecast && measurement.current.sun
71
+ measurement.forecast.each do |forecast|
72
+ forecast.sun = measurement.current.sun
73
+ end
74
+ end
75
+ measurement
76
+ end
77
+
78
+ def self._build_timezone(data)
79
+ if data && data['item'] && data['item']['pubDate']
80
+ zone_match = data['item']['pubDate'].match(/ ([A-Z]*)$/)
81
+ Data::Zone.new(zone_match[1]) if zone_match
96
82
  end
97
-
98
- measurement
99
83
  end
100
84
 
101
- def self.build_local_time(data)
102
- if data
103
- if data['item']
104
- # what time is it now?
105
- now_utc = Time.now.utc
106
-
107
- # get published date
108
- pub_date = data['item']['pubDate']
109
-
110
- # get the TIME ZONE CODE
111
- zone_match = pub_date.match(/ ([A-Z]*)$/) if pub_date
112
-
113
- if zone_match
114
- zone = zone_match[1]
115
-
116
- # try converting pub_date to utc
117
- # pub_date_utc = Data::Zone.code_to_utc(Time.parse(pub_date), zone) if zone
118
-
119
- # how far back was this?
120
- # data_age_in_seconds = now_utc - pub_date_utc
121
-
122
- # is this older then 2 hours
123
- # if (data_age_in_seconds < 0) || (data_age_in_seconds > (60 * 60 * 2))
124
- # we may have converted the time wrong.
125
- # if pub_date in the future, then?
126
- # if pub_date too far back, then?
127
-
128
- # for now do nothing ... don't set measured_time
129
- # return nil
130
- # else
131
- # everything seems fine
132
- # convert now to the local time
133
- offset = Data::Zone.zone_to_offset(zone)
134
- return Data::LocalTime.parse(now_utc + offset)
135
- # end
85
+ def self._build_links(data)
86
+ links = {}
87
+ if data["title"] && data["link"]
88
+ links[data["title"]] = data["link"]
136
89
  end
137
- nil
90
+ links
138
91
  end
139
- end
140
- end
141
92
 
142
- def self.build_current(data, metric=true)
93
+ def self._build_current(data, metric=true)
143
94
  raise ArgumentError unless data.is_a?(Hash)
144
- current = Data::CurrentMeasurement.new
95
+ current = Measurement::Current.new(metric)
145
96
  if data
146
97
  if data['item'] && data['item']['yweather:condition']
147
98
  condition_result = data['item']['yweather:condition']
@@ -171,15 +122,15 @@ end
171
122
  current
172
123
  end
173
124
 
174
- def self.build_forecast(data, metric=true)
125
+ def self._build_forecast(data, metric=true)
175
126
  raise ArgumentError unless data.is_a?(Hash)
176
- forecasts = []
127
+ forecasts = Measurement::ForecastArray.new
177
128
 
178
129
  if data && data['item'] && data['item']['yweather:forecast']
179
130
  forecast_result = data['item']['yweather:forecast']
180
131
 
181
132
  forecast_result.each do |forecast|
182
- forecast_measurement = Data::ForecastMeasurement.new
133
+ forecast_measurement = Measurement::Forecast.new
183
134
  forecast_measurement.icon = forecast['code']
184
135
  forecast_measurement.date = Date.parse(forecast['date'])
185
136
  forecast_measurement.condition = forecast['text']
@@ -193,7 +144,7 @@ end
193
144
  forecasts
194
145
  end
195
146
 
196
- def self.build_location(data, geo=nil)
147
+ def self._build_location(data, geo=nil)
197
148
  raise ArgumentError unless data.is_a?(Hash)
198
149
  raise ArgumentError unless (geo.nil? || geo.is_a?(Data::Geo))
199
150
  location = Data::Location.new
@@ -219,7 +170,7 @@ end
219
170
  location
220
171
  end
221
172
 
222
- def self.build_sun(data)
173
+ def self._build_sun(data)
223
174
  raise ArgumentError unless data.is_a?(Hash)
224
175
  sun = nil
225
176
  if data && data['yweather:astronomy'] && data['item']
@@ -229,12 +180,14 @@ end
229
180
  end
230
181
  sun || Data::Sun.new
231
182
  end
232
-
183
+
233
184
  # use HTTParty to get the current weather
234
- def self.fetch(query, metric=true)
185
+ def self._fetch(query, metric=true)
186
+ return unless query
187
+ puts "fetch yahoo: #{query.q}" if Barometer::debug?
235
188
  self.get(
236
189
  "http://weather.yahooapis.com/forecastrss",
237
- :query => {:p => query, :u => (metric ? 'c' : 'f')},
190
+ :query => {:p => query.q, :u => (metric ? 'c' : 'f')},
238
191
  :format => :xml,
239
192
  :timeout => Barometer.timeout
240
193
  )['rss']['channel']