barometer 0.5.0 → 0.6.1

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.
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']