barometer 0.8.0 → 0.9.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.
Files changed (321) hide show
  1. data/.gitignore +2 -0
  2. data/.pelusa.yml +7 -0
  3. data/.travis.yml +6 -3
  4. data/Gemfile +11 -1
  5. data/README.md +89 -244
  6. data/Rakefile +1 -1
  7. data/barometer.gemspec +22 -24
  8. data/lib/barometer.rb +14 -65
  9. data/lib/barometer/base.rb +35 -65
  10. data/lib/barometer/data.rb +15 -20
  11. data/lib/barometer/data/attribute.rb +19 -0
  12. data/lib/barometer/data/attributes/distance.rb +11 -0
  13. data/lib/barometer/data/attributes/float.rb +11 -0
  14. data/lib/barometer/data/attributes/integer.rb +11 -0
  15. data/lib/barometer/data/attributes/location.rb +11 -0
  16. data/lib/barometer/data/attributes/pressure.rb +11 -0
  17. data/lib/barometer/data/attributes/sun.rb +15 -0
  18. data/lib/barometer/data/attributes/temperature.rb +11 -0
  19. data/lib/barometer/data/attributes/time.rb +11 -0
  20. data/lib/barometer/data/attributes/vector.rb +11 -0
  21. data/lib/barometer/data/attributes/zone.rb +11 -0
  22. data/lib/barometer/data/convertable_units.rb +145 -0
  23. data/lib/barometer/data/coordinates.rb +16 -0
  24. data/lib/barometer/data/distance.rb +14 -133
  25. data/lib/barometer/data/geo.rb +22 -59
  26. data/lib/barometer/data/location.rb +14 -20
  27. data/lib/barometer/data/pressure.rb +14 -135
  28. data/lib/barometer/data/sun.rb +24 -24
  29. data/lib/barometer/data/temperature.rb +14 -169
  30. data/lib/barometer/data/vector.rb +44 -0
  31. data/lib/barometer/data/zone.rb +109 -112
  32. data/lib/barometer/query.rb +23 -161
  33. data/lib/barometer/query/base.rb +88 -0
  34. data/lib/barometer/query/converter.rb +64 -0
  35. data/lib/barometer/query/converters/from_coordinates_to_noaa_station_id.rb +30 -0
  36. data/lib/barometer/query/converters/from_geocode_to_coordinates.rb +28 -0
  37. data/lib/barometer/query/converters/from_short_zipcode_to_zipcode.rb +28 -0
  38. data/lib/barometer/query/converters/from_weather_id_to_geocode.rb +30 -0
  39. data/lib/barometer/query/converters/from_woe_id_or_ipv4_to_geocode.rb +32 -0
  40. data/lib/barometer/query/converters/to_geocode.rb +30 -0
  41. data/lib/barometer/query/converters/to_weather_id.rb +30 -0
  42. data/lib/barometer/query/converters/to_woe_id.rb +30 -0
  43. data/lib/barometer/query/format.rb +59 -0
  44. data/lib/barometer/query/formats/base.rb +22 -0
  45. data/lib/barometer/query/formats/coordinates.rb +14 -0
  46. data/lib/barometer/query/formats/geocode.rb +15 -0
  47. data/lib/barometer/query/formats/icao.rb +35 -0
  48. data/lib/barometer/query/formats/ipv4_address.rb +19 -0
  49. data/lib/barometer/query/formats/noaa_station_id.rb +15 -0
  50. data/lib/barometer/query/formats/postalcode.rb +20 -0
  51. data/lib/barometer/query/formats/short_zipcode.rb +15 -0
  52. data/lib/barometer/{translations → query/formats/translations}/icao_country_codes.yml +0 -0
  53. data/lib/barometer/{translations → query/formats/translations}/weather_country_codes.yml +0 -0
  54. data/lib/barometer/query/formats/unknown.rb +14 -0
  55. data/lib/barometer/query/formats/weather_id.rb +33 -0
  56. data/lib/barometer/query/formats/woe_id.rb +28 -0
  57. data/lib/barometer/query/formats/zipcode.rb +15 -0
  58. data/lib/barometer/query/service.rb +13 -0
  59. data/lib/barometer/query/services/apis/geonames_timezone.rb +26 -0
  60. data/lib/barometer/query/services/apis/google_geocode.rb +35 -0
  61. data/lib/barometer/query/services/apis/noaa_station.rb +31 -0
  62. data/lib/barometer/query/services/apis/weather_id.rb +35 -0
  63. data/lib/barometer/query/services/apis/wunderground_timezone.rb +26 -0
  64. data/lib/barometer/query/services/apis/yahoo_placefinder.rb +35 -0
  65. data/lib/barometer/query/services/apis/yahoo_weather.rb +31 -0
  66. data/lib/barometer/query/services/from_weather_id.rb +64 -0
  67. data/lib/barometer/query/services/geonames_timezone.rb +18 -0
  68. data/lib/barometer/query/services/google_geocode.rb +106 -0
  69. data/lib/barometer/query/services/noaa_station_id.rb +28 -0
  70. data/lib/barometer/query/services/to_weather_id.rb +25 -0
  71. data/lib/barometer/query/services/to_woe_id.rb +29 -0
  72. data/lib/barometer/query/services/wunderground_timezone.rb +18 -0
  73. data/lib/barometer/query/services/yahoo_geocode.rb +69 -0
  74. data/lib/barometer/response.rb +12 -0
  75. data/lib/barometer/response/base.rb +57 -0
  76. data/lib/barometer/response/current.rb +27 -0
  77. data/lib/barometer/response/prediction.rb +41 -0
  78. data/lib/barometer/response/prediction_collection.rb +48 -0
  79. data/lib/barometer/utils.rb +17 -0
  80. data/lib/barometer/utils/address.rb +33 -0
  81. data/lib/barometer/utils/api.rb +30 -0
  82. data/lib/barometer/utils/config_reader.rb +40 -0
  83. data/lib/barometer/utils/get.rb +17 -0
  84. data/lib/barometer/utils/json_reader.rb +22 -0
  85. data/lib/barometer/utils/payload.rb +100 -0
  86. data/lib/barometer/utils/payload_request.rb +37 -0
  87. data/lib/barometer/utils/post.rb +24 -0
  88. data/lib/barometer/utils/time.rb +78 -0
  89. data/lib/barometer/{translations → utils/translations}/zone_codes.yml +0 -0
  90. data/lib/barometer/utils/versioned_registration.rb +70 -0
  91. data/lib/barometer/utils/xml_reader.rb +27 -0
  92. data/lib/barometer/utils/zone_code_lookup.rb +30 -0
  93. data/lib/barometer/version.rb +1 -1
  94. data/lib/barometer/weather.rb +44 -173
  95. data/lib/barometer/weather_service.rb +41 -0
  96. data/lib/barometer/weather_services/base.rb +50 -0
  97. data/lib/barometer/weather_services/forecast_io.rb +36 -0
  98. data/lib/barometer/weather_services/forecast_io/api.rb +22 -0
  99. data/lib/barometer/weather_services/forecast_io/query.rb +38 -0
  100. data/lib/barometer/weather_services/forecast_io/response.rb +31 -0
  101. data/lib/barometer/weather_services/forecast_io/response/current_weather.rb +78 -0
  102. data/lib/barometer/weather_services/forecast_io/response/forecasted_weather.rb +74 -0
  103. data/lib/barometer/weather_services/forecast_io/response/location.rb +19 -0
  104. data/lib/barometer/weather_services/forecast_io/response/timezone.rb +25 -0
  105. data/lib/barometer/weather_services/noaa.rb +21 -305
  106. data/lib/barometer/weather_services/noaa/current_api.rb +25 -0
  107. data/lib/barometer/weather_services/noaa/current_query.rb +30 -0
  108. data/lib/barometer/weather_services/noaa/current_response.rb +29 -0
  109. data/lib/barometer/weather_services/noaa/forecast_api.rb +25 -0
  110. data/lib/barometer/weather_services/noaa/forecast_query.rb +39 -0
  111. data/lib/barometer/weather_services/noaa/forecast_response.rb +28 -0
  112. data/lib/barometer/weather_services/noaa/response/current_location.rb +42 -0
  113. data/lib/barometer/weather_services/noaa/response/current_station.rb +46 -0
  114. data/lib/barometer/weather_services/noaa/response/current_weather.rb +82 -0
  115. data/lib/barometer/weather_services/noaa/response/forecasted_weather.rb +90 -0
  116. data/lib/barometer/weather_services/noaa/response/location.rb +19 -0
  117. data/lib/barometer/weather_services/noaa/response/timezone.rb +15 -0
  118. data/lib/barometer/weather_services/response.rb +9 -0
  119. data/lib/barometer/weather_services/response/location.rb +42 -0
  120. data/lib/barometer/weather_services/response/time_zone.rb +19 -0
  121. data/lib/barometer/weather_services/weather_bug.rb +24 -280
  122. data/lib/barometer/weather_services/weather_bug/current_api.rb +26 -0
  123. data/lib/barometer/weather_services/weather_bug/current_response.rb +33 -0
  124. data/lib/barometer/weather_services/weather_bug/forecast_api.rb +26 -0
  125. data/lib/barometer/weather_services/weather_bug/forecast_response.rb +29 -0
  126. data/lib/barometer/weather_services/weather_bug/query.rb +42 -0
  127. data/lib/barometer/weather_services/weather_bug/response/current_weather.rb +82 -0
  128. data/lib/barometer/weather_services/weather_bug/response/forecasted_weather.rb +67 -0
  129. data/lib/barometer/weather_services/weather_bug/response/location.rb +23 -0
  130. data/lib/barometer/weather_services/weather_bug/response/station.rb +43 -0
  131. data/lib/barometer/weather_services/weather_bug/response/sun.rb +32 -0
  132. data/lib/barometer/weather_services/weather_bug/response/time_helper.rb +52 -0
  133. data/lib/barometer/weather_services/weather_bug/response/timezone.rb +15 -0
  134. data/lib/barometer/weather_services/wunderground_v1.rb +32 -0
  135. data/lib/barometer/weather_services/wunderground_v1/current_api.rb +21 -0
  136. data/lib/barometer/weather_services/wunderground_v1/current_response.rb +31 -0
  137. data/lib/barometer/weather_services/wunderground_v1/forecast_api.rb +21 -0
  138. data/lib/barometer/weather_services/wunderground_v1/forecast_response.rb +33 -0
  139. data/lib/barometer/weather_services/wunderground_v1/query.rb +30 -0
  140. data/lib/barometer/weather_services/wunderground_v1/response/current_weather.rb +92 -0
  141. data/lib/barometer/weather_services/wunderground_v1/response/forecasted_weather.rb +87 -0
  142. data/lib/barometer/weather_services/wunderground_v1/response/full_timezone.rb +22 -0
  143. data/lib/barometer/weather_services/wunderground_v1/response/location.rb +43 -0
  144. data/lib/barometer/weather_services/wunderground_v1/response/station.rb +39 -0
  145. data/lib/barometer/weather_services/wunderground_v1/response/sun.rb +53 -0
  146. data/lib/barometer/weather_services/wunderground_v1/response/timezone.rb +15 -0
  147. data/lib/barometer/weather_services/yahoo.rb +16 -198
  148. data/lib/barometer/weather_services/yahoo/api.rb +21 -0
  149. data/lib/barometer/weather_services/yahoo/query.rb +42 -0
  150. data/lib/barometer/weather_services/yahoo/response.rb +39 -0
  151. data/lib/barometer/weather_services/yahoo/response/current_weather.rb +86 -0
  152. data/lib/barometer/weather_services/yahoo/response/forecasted_weather.rb +71 -0
  153. data/lib/barometer/weather_services/yahoo/response/location.rb +47 -0
  154. data/lib/barometer/weather_services/yahoo/response/sun.rb +43 -0
  155. data/lib/barometer/weather_services/yahoo/response/timezone.rb +15 -0
  156. data/spec/barometer_spec.rb +18 -120
  157. data/spec/base_spec.rb +114 -0
  158. data/spec/cassettes/Converter_FromCoordinatesToNoaaStationId.json +1 -0
  159. data/spec/cassettes/Converter_FromWeatherIdToGeocode.json +1 -0
  160. data/spec/cassettes/Converter_FromWoeIdOrIpv4ToGeocode.json +1 -0
  161. data/spec/cassettes/Converter_ToGeocode.json +1 -0
  162. data/spec/cassettes/Converter_ToWeatherId.json +1 -0
  163. data/spec/cassettes/Converter_ToWoeId.json +1 -0
  164. data/spec/cassettes/Service_FromWeatherId.json +1 -0
  165. data/spec/cassettes/Service_GoogleGeocode.json +1 -0
  166. data/spec/cassettes/Service_NoaaStation.json +1 -0
  167. data/spec/cassettes/Service_ToWeatherId.json +1 -0
  168. data/spec/cassettes/Service_ToWoeId.json +1 -0
  169. data/spec/cassettes/Service_YahooGeocode.json +1 -0
  170. data/spec/cassettes/WeatherService_ForecastIo.json +1 -0
  171. data/spec/cassettes/WeatherService_Noaa.json +1 -1
  172. data/spec/cassettes/WeatherService_WeatherBug.json +1 -1
  173. data/spec/cassettes/WeatherService_WundergroundV1.json +1 -0
  174. data/spec/cassettes/WeatherService_Yahoo.json +1 -1
  175. data/spec/data/attributes/distance_spec.rb +60 -0
  176. data/spec/data/attributes/location_spec.rb +41 -0
  177. data/spec/data/attributes/pressure_spec.rb +60 -0
  178. data/spec/data/attributes/sun_spec.rb +33 -0
  179. data/spec/data/attributes/temperature_spec.rb +60 -0
  180. data/spec/data/attributes/time_spec.rb +58 -0
  181. data/spec/data/attributes/vector_spec.rb +43 -0
  182. data/spec/data/attributes/zone_spec.rb +34 -0
  183. data/spec/data/convertable_units_spec.rb +299 -0
  184. data/spec/data/coordinates_spec.rb +15 -0
  185. data/spec/data/distance_spec.rb +49 -333
  186. data/spec/data/geo_spec.rb +72 -71
  187. data/spec/data/location_spec.rb +70 -65
  188. data/spec/data/pressure_spec.rb +49 -333
  189. data/spec/data/sun_spec.rb +57 -81
  190. data/spec/data/temperature_spec.rb +49 -393
  191. data/spec/data/vector_spec.rb +100 -0
  192. data/spec/data/zone_spec.rb +199 -266
  193. data/spec/query/base_spec.rb +296 -0
  194. data/spec/query/converter_spec.rb +98 -0
  195. data/spec/query/converters/from_coordinates_to_noaa_station_id_spec.rb +35 -0
  196. data/spec/query/converters/from_geocode_to_coordinates_spec.rb +25 -0
  197. data/spec/query/converters/from_short_zipcode_to_zipcode_spec.rb +31 -0
  198. data/spec/query/converters/from_weather_id_to_geocode_spec.rb +40 -0
  199. data/spec/query/converters/from_woe_id_or_ipv4_to_geocode_spec.rb +51 -0
  200. data/spec/query/converters/to_geocode_spec.rb +99 -0
  201. data/spec/query/converters/to_weather_id_spec.rb +35 -0
  202. data/spec/query/converters/to_woe_id_spec.rb +74 -0
  203. data/spec/query/formats/base_spec.rb +15 -0
  204. data/spec/query/formats/coordinates_spec.rb +13 -0
  205. data/spec/query/formats/geocode_spec.rb +9 -0
  206. data/spec/query/formats/icao_spec.rb +20 -0
  207. data/spec/query/formats/ipv4_address_spec.rb +33 -0
  208. data/spec/query/formats/noaa_station_id_spec.rb +9 -0
  209. data/spec/query/formats/postalcode_spec.rb +18 -0
  210. data/spec/query/formats/short_zipcode_spec.rb +18 -0
  211. data/spec/query/formats/unknown_spec.rb +9 -0
  212. data/spec/query/formats/weather_id_spec.rb +31 -0
  213. data/spec/query/formats/woe_id_spec.rb +45 -0
  214. data/spec/query/formats/zipcode_spec.rb +18 -0
  215. data/spec/query/formats_spec.rb +55 -0
  216. data/spec/query/services/from_weather_id_spec.rb +54 -0
  217. data/spec/query/services/google_geocode_spec.rb +60 -0
  218. data/spec/query/services/noaa_station_id_spec.rb +23 -0
  219. data/spec/query/services/to_weather_id_spec.rb +23 -0
  220. data/spec/query/services/to_woe_id_spec.rb +51 -0
  221. data/spec/query/services/yahoo_geocode_spec.rb +72 -0
  222. data/spec/response/base_spec.rb +103 -0
  223. data/spec/response/current_spec.rb +33 -0
  224. data/spec/response/predicition_spec.rb +65 -0
  225. data/spec/response/prediction_collection_spec.rb +97 -0
  226. data/spec/spec_helper.rb +14 -12
  227. data/spec/support/key_file_parser.rb +22 -0
  228. data/spec/support/matchers/formats.rb +36 -0
  229. data/spec/support/matchers/have_data.rb +46 -0
  230. data/spec/support/matchers/have_field.rb +128 -0
  231. data/spec/support/matchers/have_forecast.rb +46 -0
  232. data/spec/support/matchers/path.rb +23 -0
  233. data/spec/support/query_factory.rb +20 -0
  234. data/spec/utils/address_spec.rb +67 -0
  235. data/spec/utils/config_reader_spec.rb +157 -0
  236. data/spec/utils/get_spec.rb +22 -0
  237. data/spec/utils/payload_request_spec.rb +69 -0
  238. data/spec/utils/payload_spec.rb +168 -0
  239. data/spec/utils/post_spec.rb +20 -0
  240. data/spec/utils/time_spec.rb +93 -0
  241. data/spec/utils/versioned_registration_spec.rb +105 -0
  242. data/spec/weather_services/base_spec.rb +116 -0
  243. data/spec/weather_services/forecast_io_spec.rb +71 -0
  244. data/spec/weather_services/noaa/current_response_spec.rb +22 -0
  245. data/spec/weather_services/noaa/forecast_response_spec.rb +33 -0
  246. data/spec/weather_services/noaa_spec.rb +68 -166
  247. data/spec/weather_services/weather_bug/current_response_spec.rb +64 -0
  248. data/spec/weather_services/weather_bug/forecast_response_spec.rb +23 -0
  249. data/spec/weather_services/weather_bug_spec.rb +62 -202
  250. data/spec/weather_services/wunderground_v1/current_response_spec.rb +19 -0
  251. data/spec/weather_services/wunderground_v1/forecast_response_spec.rb +62 -0
  252. data/spec/weather_services/wunderground_v1_spec.rb +78 -0
  253. data/spec/weather_services/yahoo/response_spec.rb +73 -0
  254. data/spec/weather_services/yahoo_spec.rb +52 -135
  255. data/spec/weather_services_spec.rb +103 -0
  256. data/spec/weather_spec.rb +167 -347
  257. metadata +342 -123
  258. data/.document +0 -5
  259. data/TODO +0 -60
  260. data/bin/barometer +0 -441
  261. data/lib/barometer/data/local_datetime.rb +0 -145
  262. data/lib/barometer/data/local_time.rb +0 -134
  263. data/lib/barometer/data/speed.rb +0 -158
  264. data/lib/barometer/data/units.rb +0 -49
  265. data/lib/barometer/formats.rb +0 -13
  266. data/lib/barometer/formats/coordinates.rb +0 -57
  267. data/lib/barometer/formats/format.rb +0 -64
  268. data/lib/barometer/formats/geocode.rb +0 -60
  269. data/lib/barometer/formats/icao.rb +0 -37
  270. data/lib/barometer/formats/postalcode.rb +0 -22
  271. data/lib/barometer/formats/short_zipcode.rb +0 -17
  272. data/lib/barometer/formats/weather_id.rb +0 -92
  273. data/lib/barometer/formats/woe_id.rb +0 -150
  274. data/lib/barometer/formats/zipcode.rb +0 -31
  275. data/lib/barometer/key_file_parser.rb +0 -20
  276. data/lib/barometer/measurements/measurement.rb +0 -202
  277. data/lib/barometer/measurements/result.rb +0 -207
  278. data/lib/barometer/measurements/result_array.rb +0 -75
  279. data/lib/barometer/services.rb +0 -19
  280. data/lib/barometer/weather_services/service.rb +0 -189
  281. data/lib/barometer/weather_services/wunderground.rb +0 -264
  282. data/lib/barometer/web_services/geocode.rb +0 -34
  283. data/lib/barometer/web_services/noaa_station_id.rb +0 -53
  284. data/lib/barometer/web_services/placemaker.rb +0 -95
  285. data/lib/barometer/web_services/timezone.rb +0 -38
  286. data/lib/barometer/web_services/weather_id.rb +0 -50
  287. data/lib/barometer/web_services/web_service.rb +0 -29
  288. data/spec/cassettes/Barometer.json +0 -1
  289. data/spec/cassettes/Query.json +0 -1
  290. data/spec/cassettes/Query_Format_Coordinates.json +0 -1
  291. data/spec/cassettes/Query_Format_Geocode.json +0 -1
  292. data/spec/cassettes/Query_Format_WeatherID.json +0 -1
  293. data/spec/cassettes/Query_Format_WoeID.json +0 -1
  294. data/spec/cassettes/WeatherService.json +0 -1
  295. data/spec/cassettes/WeatherService_Wunderground.json +0 -1
  296. data/spec/cassettes/WebService_Geocode.json +0 -1
  297. data/spec/cassettes/WebService_NoaaStation.json +0 -1
  298. data/spec/data/local_datetime_spec.rb +0 -274
  299. data/spec/data/local_time_spec.rb +0 -239
  300. data/spec/data/speed_spec.rb +0 -374
  301. data/spec/data/units_spec.rb +0 -101
  302. data/spec/formats/coordinates_spec.rb +0 -166
  303. data/spec/formats/format_spec.rb +0 -74
  304. data/spec/formats/geocode_spec.rb +0 -163
  305. data/spec/formats/icao_spec.rb +0 -55
  306. data/spec/formats/postalcode_spec.rb +0 -53
  307. data/spec/formats/short_zipcode_spec.rb +0 -47
  308. data/spec/formats/weather_id_spec.rb +0 -182
  309. data/spec/formats/woe_id_spec.rb +0 -211
  310. data/spec/formats/zipcode_spec.rb +0 -103
  311. data/spec/key_file_parser_spec.rb +0 -28
  312. data/spec/measurements/measurement_spec.rb +0 -381
  313. data/spec/measurements/result_array_spec.rb +0 -150
  314. data/spec/measurements/result_spec.rb +0 -632
  315. data/spec/query_spec.rb +0 -498
  316. data/spec/weather_services/services_spec.rb +0 -135
  317. data/spec/weather_services/wunderground_spec.rb +0 -179
  318. data/spec/web_services/geocode_spec.rb +0 -31
  319. data/spec/web_services/noaa_station_id_spec.rb +0 -33
  320. data/spec/web_services/placemaker_spec.rb +0 -41
  321. data/spec/web_services/web_services_spec.rb +0 -20
@@ -1,141 +1,138 @@
1
- require 'rubygems'
2
1
  require 'tzinfo'
2
+ require 'delegate'
3
3
 
4
4
  module Barometer
5
- #
6
- # A simple Zone class
7
- #
8
- # Used for building and converting timezone aware date and times
9
- # Really, these are just wrappers for TZInfo conversions plus
10
- # some extras.
11
- #
12
- class Data::Zone
13
-
14
- @@zone_codes_file = File.expand_path(
15
- File.join(File.dirname(__FILE__), '..', 'translations', 'zone_codes.yml'))
16
- @@zone_codes = nil
17
-
18
- attr_accessor :zone_full, :zone_code, :zone_offset, :tz
19
-
20
- def initialize(zone)
21
- if Data::Zone.is_zone_full?(zone)
22
- @zone_full = zone
23
- @tz = TZInfo::Timezone.get(zone)
24
- elsif Data::Zone.is_zone_offset?(zone)
25
- @zone_offset = zone
26
- elsif Data::Zone.is_zone_code?(zone)
27
- @zone_code = zone
28
- else
29
- raise(ArgumentError, "invalid time zone")
5
+ module Data
6
+ class Zone < SimpleDelegator
7
+ def initialize(zone)
8
+ zone = if ZoneFull.detect?(zone)
9
+ ZoneFull.new(zone)
10
+ elsif ZoneOffset.detect?(zone)
11
+ ZoneOffset.new(zone)
12
+ elsif ZoneCode.detect?(zone)
13
+ ZoneCode.new(zone)
14
+ else
15
+ raise(ArgumentError, "invalid time zone")
16
+ end
17
+ super(zone)
30
18
  end
31
19
  end
32
20
 
33
- def current
34
- @zone_full || @zone_offset || @zone_code
35
- end
21
+ class ZoneFull
22
+ def self.detect?(zone)
23
+ zone.respond_to?(:match) && !!zone.match(/^[A-Za-z]+\/[A-Za-z_]+$/)
24
+ end
36
25
 
37
- # what is the Timezone Short Code for the current timezone
38
- def code
39
- return @zone_code if @zone_code
40
- return nil unless @tz
41
- @tz.period_for_utc(Time.now.utc).zone_identifier.to_s
42
- end
26
+ def initialize(zone, time_class=::Time)
27
+ @zone = zone
28
+ @time_class = time_class
29
+ @tz = TZInfo::Timezone.get(zone)
30
+ end
43
31
 
44
- def full
45
- @zone_full || nil
46
- end
32
+ def code
33
+ tz.period_for_utc(time_class.now.utc).zone_identifier.to_s
34
+ end
47
35
 
48
- def offset
49
- if @zone_offset
50
- @zone_offset.to_f * 60 * 60
51
- elsif @zone_code
52
- Data::Zone.zone_to_offset(@zone_code)
53
- elsif @zone_full
36
+ def offset
37
+ tz.period_for_utc(time_class.now.utc).utc_total_offset
54
38
  end
55
- end
56
39
 
57
- # is the current timezone in daylights savings mode?
58
- def dst?
59
- return nil unless @tz
60
- @tz.period_for_utc(Time.now.utc).dst?
61
- end
40
+ def now
41
+ tz.utc_to_local(time_class.now.utc)
42
+ end
62
43
 
63
- # return Time.now.utc for the set timezone
64
- def now(convert=false)
65
- if @zone_full
66
- now = @tz.utc_to_local(Time.now.utc)
67
- elsif @zone_offset || @zone_code
68
- now = Time.now.utc + self.offset
44
+ def to_s
45
+ zone
69
46
  end
70
- convert ? Data::LocalTime.parse(now) : now
71
- end
72
47
 
73
- # return Date.today for the set timezone
74
- def today
75
- now = self.now
76
- Date.new(now.year, now.month, now.day)
77
- end
48
+ def local_to_utc(local_time)
49
+ tz.local_to_utc(local_time)
50
+ end
78
51
 
79
- def local_to_utc(local_time)
80
- if @zone_full
81
- @tz.local_to_utc(local_time)
82
- elsif @zone_offset || @zone_code
83
- local_time -= self.offset
84
- Time.utc(local_time.year,local_time.month,local_time.day,
85
- local_time.hour,local_time.min,local_time.sec)
52
+ def utc_to_local(utc_time)
53
+ tz.utc_to_local(utc_time)
86
54
  end
55
+
56
+ private
57
+
58
+ attr_reader :zone, :tz, :time_class
87
59
  end
88
60
 
89
- def utc_to_local(utc_time)
90
- if @zone_full
91
- @tz.utc_to_local(utc_time)
92
- elsif @zone_offset || @zone_code
93
- utc_time + self.offset
61
+ class ZoneOffset
62
+ def self.detect?(zone)
63
+ zone.respond_to?(:abs) && zone.abs <= 14
94
64
  end
95
- end
96
65
 
97
- #
98
- # Class Methods
99
- #
66
+ def initialize(zone, time_class=::Time)
67
+ @zone = zone
68
+ @time_class = time_class
69
+ end
100
70
 
101
- def self.is_zone_code?(zone)
102
- return false unless (zone && zone.is_a?(String))
103
- _load_zone_codes unless @@zone_codes
104
- Time.zone_offset(zone) || (@@zone_codes && @@zone_codes.has_key?(zone))
105
- end
71
+ def code
72
+ end
106
73
 
107
- def self.is_zone_full?(zone)
108
- return false unless (zone && zone.is_a?(String))
109
- zone.match(/[A-Za-z]+\/[A-Za-z]+/) ? true : false
110
- end
74
+ def offset
75
+ zone.to_f * 60 * 60
76
+ end
111
77
 
112
- def self.is_zone_offset?(zone)
113
- return false unless (zone && (zone.is_a?(Fixnum) || zone.is_a?(Float)))
114
- zone.to_f.abs <= 14
115
- end
78
+ def now
79
+ time_class.now.utc + offset
80
+ end
116
81
 
117
- #
118
- # Known conflicts
119
- # IRT (ireland and india)
120
- # CST (central standard time, china standard time)
121
- #
122
- def self.zone_to_offset(timezone)
123
- offset = 0
124
- seconds_in_hour = 60*60
125
- # try to use Time
126
- unless offset = Time.zone_offset(timezone)
127
- # that would have been too easy, do it manually
128
- # http://www.timeanddate.com/library/abbreviations/timezones/
129
- # http://www.worldtimezone.com/wtz-names/timezonenames.html
130
- offset = (@@zone_codes[timezone.to_s.upcase] || 0) * seconds_in_hour
131
- end
132
- offset
133
- end
82
+ def to_s
83
+ zone.to_s
84
+ end
85
+
86
+ def local_to_utc(local_time)
87
+ local_time - offset
88
+ end
89
+
90
+ def utc_to_local(utc_time)
91
+ utc_time + offset
92
+ end
93
+
94
+ private
134
95
 
135
- def self._load_zone_codes
136
- $:.unshift(File.dirname(__FILE__))
137
- @@zone_codes ||= YAML.load_file(@@zone_codes_file)
96
+ attr_reader :zone, :time_class
138
97
  end
139
98
 
99
+ class ZoneCode
100
+ def self.detect?(zone)
101
+ zone.respond_to?(:to_s) && Utils::ZoneCodeLookup.exists?(zone.to_s)
102
+ end
103
+
104
+ def initialize(zone, time_class=::Time)
105
+ @zone = zone
106
+ @time_class = time_class
107
+ end
108
+
109
+ def code
110
+ zone
111
+ end
112
+
113
+ def offset
114
+ Utils::ZoneCodeLookup.offset(zone)
115
+ end
116
+
117
+ def now
118
+ time_class.now.utc + offset
119
+ end
120
+
121
+ def to_s
122
+ zone
123
+ end
124
+
125
+ def local_to_utc(local_time)
126
+ local_time - offset
127
+ end
128
+
129
+ def utc_to_local(utc_time)
130
+ utc_time + offset
131
+ end
132
+
133
+ private
134
+
135
+ attr_reader :zone, :time_class
136
+ end
140
137
  end
141
138
  end
@@ -1,172 +1,34 @@
1
- module Barometer
2
- #
3
- # This class represents a query and can answer the
4
- # questions that a Barometer will need to measure the weather
5
- #
6
- # Summary:
7
- # When you create a new Query, you set the query string
8
- # ie: "New York, NY" or "90210"
9
- # The class will then determine the query string format
10
- # ie: :zipcode, :postalcode, :geocode, :coordinates
11
- # Now, when a Weather API driver asks for the query, it will prefer
12
- # certain formats, and only permit certain formats. The Query class
13
- # will attempt to either return the query string as-is if acceptable,
14
- # or it will attempt to convert it to a format that is acceptable
15
- # (most likely this conversion will use Googles geocoding service using
16
- # the Graticule gem). Worst case scenario is that the Weather API will
17
- # not accept the query string.
18
- #
19
- class Query
20
-
21
- # This array defines the order to check a query for the format
22
- #
23
- FORMATS = %w(
24
- ShortZipcode Zipcode Postalcode WeatherID Coordinates Icao WoeID Geocode
25
- )
26
- FORMAT_MAP = {
27
- :short_zipcode => "ShortZipcode", :zipcode => "Zipcode",
28
- :postalcode => "Postalcode", :weather_id => "WeatherID",
29
- :coordinates => "Coordinates", :icao => "Icao",
30
- :woe_id => "WoeID", :geocode => "Geocode"
31
- }
32
-
33
- attr_writer :q
34
- attr_accessor :format, :country_code
35
- attr_accessor :geo, :timezone, :conversions
1
+ require_relative 'query/base'
2
+ require_relative 'query/format'
3
+ require_relative 'query/converter'
4
+ require_relative 'query/service'
36
5
 
37
- def initialize(query=nil)
38
- return unless query
39
- @q = query
40
- self.analyze!
41
- @conversions = {}
6
+ module Barometer
7
+ class ConvertedQuery
8
+ attr_reader :q, :format, :units, :geo
9
+
10
+ def initialize(q, format, units=:metric, geo=nil)
11
+ @q = q
12
+ @format = format
13
+ @units = units
14
+ @geo = geo
42
15
  end
43
16
 
44
- def q
45
- format ? Barometer::Query::Format.const_get(FORMAT_MAP[format.to_sym].to_s).convert_query(@q) : @q
17
+ def metric?
18
+ units == :metric
46
19
  end
47
20
 
48
- # analyze the saved query to determine the format.
49
- # this delegates the detection to each formats class
50
- # until th right one is found
51
- #
52
- def analyze!
53
- return unless @q
54
- FORMATS.each do |format|
55
- if Query::Format.const_get(format.to_s).is?(@q)
56
- @format = Query::Format.const_get(format.to_s).format
57
- @country_code = Query::Format.const_get(format.to_s).country_code(@q)
58
- break
59
- end
60
- end
21
+ def to_s
22
+ @q
61
23
  end
62
-
63
- # take a list of acceptable (and ordered by preference) formats and convert
64
- # the current query (q) into the most preferred and acceptable format. a
65
- # side effect of the conversions may reveal the country_code, if so save it
66
- #
67
- def convert!(preferred_formats=nil)
68
- raise ArgumentError unless (preferred_formats && preferred_formats.size > 0)
69
-
70
- # why convert if we are already there?
71
- # (except in the case that the serivce excepts coordinates and we have a
72
- # a geocode ... the google geocode results are superior)
73
- #
74
- skip_conversion = false
75
- unless (@format.to_sym == Query::Format::Geocode.format) &&
76
- preferred_formats.include?(Query::Format::Coordinates.format)
77
- if preferred_formats.include?(@format.to_sym)
78
- skip_conversion = true
79
- converted_query = self.dup
80
- end
81
- end
82
-
83
- unless skip_conversion
84
- # go through each acceptable format and try to convert to that
85
- converted = false
86
- converted_query = Barometer::Query.new
87
- preferred_formats.each do |preferred_format|
88
- klass = FORMAT_MAP[preferred_format.to_sym]
89
- # if we discover that the format we have is the preferred format, return it
90
- if preferred_format == @format
91
- converted = true
92
- converted_query = Barometer::Query.new(@q)
93
- end
94
- unless converted
95
- unless converted_query = get_conversion(preferred_format)
96
- converted_query = Query::Format.const_get(klass.to_s).to(self)
97
- end
98
- converted = true if converted_query
99
- end
100
- if converted
101
- converted_query.country_code ||= Query::Format.const_get(klass.to_s).country_code(converted_query.q)
102
- post_conversion(converted_query)
103
- break
104
- end
105
- end
106
- end
107
-
108
- # force geocode?, unless we already did
109
- #
110
- if Barometer.force_geocode && !@geo
111
- if converted_query && converted_query.geo
112
- @geo = converted_query.geo
113
- elsif converted_query
114
- puts "enhance geocode: #{converted_query.q}" if Barometer::debug?
115
- geo_query = Query::Format::Coordinates.to(converted_query)
116
- @geo = geo_query.geo if (geo_query && geo_query.geo)
117
- converted_query.geo = @geo.dup
118
- end
119
- end
120
-
121
- # enhance timezone?, unless we already did
122
- #
123
- if Barometer.enhance_timezone && !@timezone
124
- if converted_query && converted_query.timezone
125
- @geo = converted_query.timezone
126
- elsif @geo && @geo.latitude && @geo.longitude
127
- puts "enhance timezone: #{@geo.latitude}, #{@geo.longitude}" if Barometer::debug?
128
- @timezone = WebService::Timezone.fetch(@geo.latitude,@geo.longitude)
129
- converted_query.timezone = @timezone.dup
130
- end
131
- end
132
-
133
- converted_query
134
- end
135
-
136
- # save the important parts of the conversion ... by saving conversion we
137
- # can avoid doing the same conversion multiple times
138
- #
139
- def post_conversion(converted_query)
140
- return unless (converted_query && converted_query.q && converted_query.format)
141
- @conversions = {} unless @conversions
142
- return if @conversions.has_key?(converted_query.format.to_sym)
143
- puts "store: #{self.format} -> #{converted_query.format.to_sym} = #{self.q} -> #{converted_query.q}" if Barometer::debug?
144
- @conversions[converted_query.format.to_sym] = converted_query.q
145
- end
146
-
147
- def get_conversion(format)
148
- return nil unless format && @conversions
149
- puts "found: #{self.format} -> #{format.to_sym} = #{self.q} -> #{@conversions[format.to_sym]}" if Barometer::debug? && @conversions.has_key?(format.to_sym)
150
- # re-constuct converted query
151
- if q = @conversions[format.to_sym]
152
- converted_query = self.dup
153
- converted_query.q = q
154
- converted_query.format = format
155
- converted_query
156
- else
157
- nil
158
24
  end
159
- end
160
25
 
161
- def latitude
162
- return nil unless self.format == Query::Format::Coordinates.format
163
- Query::Format::Coordinates.parse_latitude(self.q)
164
- end
165
-
166
- def longitude
167
- return nil unless self.format == Query::Format::Coordinates.format
168
- Query::Format::Coordinates.parse_longitude(self.q)
169
- end
26
+ module Query
27
+ class ConversionNotPossible < StandardError; end
28
+ class UnsupportedRegion < StandardError; end
170
29
 
30
+ def self.new(*args)
31
+ Barometer::Query::Base.new(*args)
32
+ end
171
33
  end
172
34
  end
@@ -0,0 +1,88 @@
1
+ module Barometer
2
+ module Query
3
+ class Base
4
+ attr_reader :format, :geo, :units
5
+
6
+ def initialize(query, units=:metric)
7
+ @q = query.dup
8
+ @units = units
9
+ @geo = Data::Geo.new
10
+ detect_format
11
+ freeze_query
12
+ @conversions = {}
13
+ end
14
+
15
+ def q
16
+ @format_klass.convert_query(@q)
17
+ end
18
+
19
+ def add_conversion(format, q)
20
+ return unless q
21
+
22
+ @conversions[format] = q
23
+ converted_query(q, format)
24
+ end
25
+
26
+ def get_conversion(*formats)
27
+ converted_format = formats.detect{|f| format == f || @conversions.has_key?(f)}
28
+ return unless converted_format
29
+
30
+ if converted_format == format
31
+ self
32
+ else
33
+ converted_query(@conversions[converted_format], converted_format)
34
+ end
35
+ end
36
+
37
+ def convert!(*preferred_formats)
38
+ return self if preferred_formats.include?(format)
39
+
40
+ get_conversion(*preferred_formats) ||
41
+ do_conversion(format, preferred_formats) ||
42
+ raise(ConversionNotPossible)
43
+ end
44
+
45
+ def metric?
46
+ units == :metric
47
+ end
48
+
49
+ def to_s
50
+ q.to_s
51
+ end
52
+
53
+ def geo=(geo)
54
+ @geo = @geo.merge(geo)
55
+ end
56
+
57
+ private
58
+
59
+ def converted_query(q, format)
60
+ ConvertedQuery.new(q, format, units, geo)
61
+ end
62
+
63
+ def detect_format
64
+ Format.match?(@q) do |key, klass|
65
+ @format = key
66
+ @geo = Data::Geo.new(country_code: klass.country_code(@q))
67
+ @format_klass = klass
68
+ end
69
+ end
70
+
71
+ def freeze_query
72
+ @q.freeze
73
+ @format.freeze
74
+ @units.freeze
75
+ end
76
+
77
+ def do_conversion(format, preferred_formats)
78
+ converters = Converter.find_all(format, preferred_formats)
79
+ result = converters.map do |converter|
80
+ to_format = converter.keys.first
81
+ converter_klass = converter.values.first
82
+ get_conversion(to_format) || converter_klass.new(self).call
83
+ end.last
84
+ get_conversion(*preferred_formats) || result
85
+ end
86
+ end
87
+ end
88
+ end