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
data/README.rdoc CHANGED
@@ -10,25 +10,22 @@ unavailable.
10
10
 
11
11
  Barometer handles all conversions of the supplied query, so that the
12
12
  same query can be used for all (or most) services, even if they don't
13
- support the query directly.
14
-
15
- For example, Yahoo! only accepts US Zip Code or Weather.com ID. With Barometer
16
- you can query Yahoo! with a simple location (ie: Paris) and it will return the
17
- weather.
13
+ support the query directly. See the "Query" section for more information on
14
+ this.
18
15
 
19
16
  == version
20
17
 
21
- Version 0.5.0 is the current release of this gem.
18
+ Version 0.6.0 is the current release of this gem.
22
19
  The gem is available from github (attack-barometer) or rubyforge (barometer).
23
- It is fully functional (for four weather service APIs).
20
+ It is fully functional (for five weather service APIs).
24
21
 
25
22
  == status
26
23
 
27
24
  Currently this project is in development and will only work for a few weather
28
- services (wunderground, google, yahoo, weather.com).
25
+ services (wunderground, google, yahoo, weather.com, weather_bug).
29
26
 
30
27
  Features to be added next:
31
- - even more weather service drivers (noaa, weatherbug)
28
+ - even more weather service drivers (noaa)
32
29
  - icon support
33
30
 
34
31
  = dependencies
@@ -59,6 +56,11 @@ eg. weather.com
59
56
  partner: YOUR_PARTNER_KEY
60
57
  license: YOUR_LICENSE_KEY
61
58
 
59
+ eg. weatherbug.com
60
+
61
+ weather_bug:
62
+ code: YOUR_API_CODE
63
+
62
64
  == HTTParty
63
65
 
64
66
  Why? HTTParty was created and designed specifically for consuming web services.
@@ -74,6 +76,45 @@ This information doesn't mean that much if it can't be converted to times
74
76
  that don't correspond to the applicable timezone.
75
77
  Tzinfo handles this time zone manipulation.
76
78
 
79
+ = queries
80
+
81
+ The query handling is one of the most beneficial and powerful features of
82
+ Barometer. Every weather service accepts a different set of possible
83
+ queries, so it usually the case that the same query can only be used
84
+ for a couple weather services.
85
+
86
+ Barometer will allow the use of all query formats for all services
87
+ (mostly). It does this by first determining the original query format,
88
+ then converting the query to a compatible format for each specific
89
+ weather service.
90
+
91
+ For example, Yahoo! only accepts US Zip Code or Weather.com ID. With Barometer
92
+ you can query Yahoo! with a simple location (ie: Paris) or even an Airport
93
+ code (ICAO) and it will return the weather as expected.
94
+
95
+ == acceptable formats
96
+
97
+ - zipcode
98
+ - icao (international airport code)
99
+ - coordinates (latitude and longitude)
100
+ - postal code
101
+ - weather.com ID
102
+ - location name (ie address, city, state, landmark, etc.)
103
+
104
+ * if the query is of the formats zipcode or postal code it may not
105
+ support conversion to other formats.
106
+
107
+ == conversion caching
108
+
109
+ Barometer has internal conversion caching. No conversion will be
110
+ repeated during a measurement, thus limiting the number of web queries
111
+ needed.
112
+
113
+ Example: If you configure Barometer to use both Yahoo and Weather.com,
114
+ then use a query like "denver", this will require a conversion from
115
+ "denver" to its weather.com weather_id. This conversion is needed for
116
+ both web services but will only happen once and be cached.
117
+
77
118
  = usage
78
119
 
79
120
  You can use barometer right out of the box, as it is configured to use one
@@ -99,6 +140,7 @@ The available sources are:
99
140
  Yahoo! Weather (:yahoo)
100
141
  Google Weather (:google)
101
142
  Weather.com (:weather_dot_com)
143
+ WeatherBug.com (:weather_bug)
102
144
 
103
145
  == source configuration
104
146
 
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 0
2
+ :patch: 1
3
3
  :major: 0
4
- :minor: 5
4
+ :minor: 6
data/bin/barometer CHANGED
@@ -29,12 +29,14 @@
29
29
  # -V, --verbose Verbose output
30
30
  # -t, --timeout seconds until service queries will timeout
31
31
  # -g, --geocode Force Geocoding of query
32
+ # -z, --timezone Enhance Timezone
32
33
  # -m, --metric measure in metric
33
34
  # -i, --imperial measure in imperial
34
35
  # --wunderground add wunderground as a source
35
36
  # --yahoo add yahoo as a source
36
37
  # --google add google as a source
37
38
  # --weather add weather.com as a source
39
+ # --bug add weather_bug as a source
38
40
  # -p, --pop pop threshold used to determine wet?
39
41
  # -s, --wind wind speed threshold used to determine windy?
40
42
  # -a, --at time/date used to determine when to calculate summary
@@ -64,7 +66,7 @@ require 'yaml'
64
66
 
65
67
  # file where API keys are stored
66
68
  KEY_FILE = File.expand_path(File.join('~', '.barometer'))
67
- BAROMETER_VERSION = '0.5.0'
69
+ BAROMETER_VERSION = '0.6.0'
68
70
 
69
71
  class App
70
72
 
@@ -77,6 +79,7 @@ class App
77
79
  @options = OpenStruct.new
78
80
  @options.timeout = 15
79
81
  @options.geocode = false
82
+ @options.timezone = false
80
83
  @options.metric = true
81
84
  @options.sources = []
82
85
  @options.verbode = false
@@ -120,12 +123,14 @@ class App
120
123
  opt.on('-a n', '--at n') {|n| @options.at = Time.parse(n.to_s) }
121
124
  opt.on('-t n', '--timeout n') {|n| @options.timeout = n }
122
125
  opt.on('-g', '--geocode') { @options.geocode = true }
126
+ opt.on('-z', '--timezone') { @options.timezone = true }
123
127
  opt.on('-m', '--metric') { @options.metric = true }
124
128
  opt.on('-i', '--imperial') { @options.metric = false }
125
129
  opt.on('--wunderground') { @options.sources << :wunderground; @options.default = false }
126
130
  opt.on('--yahoo') { @options.sources << :yahoo; @options.default = false }
127
131
  opt.on('--google') { @options.sources << :google; @options.default = false }
128
132
  opt.on('--weather') { @options.sources << :weather_dot_com; @options.default = false }
133
+ opt.on('--bug') { @options.sources << :weather_bug; @options.default = false }
129
134
  opt.on('-p n', '--pop n') {|n| @options.pop = n.to_i || 50 }
130
135
  opt.on('-s n', '--wind n') {|n| @options.metric ? @options.windy_m = n.to_f || 10 : @options.windy_i = n.to_f || 7 }
131
136
 
@@ -157,16 +162,38 @@ class App
157
162
  end
158
163
  { :weather_dot_com => { :keys => { :partner => partner_key, :license => license_key } } }
159
164
  end
165
+
166
+ def config_weather_bug
167
+ if File.exists?(KEY_FILE)
168
+ keys = YAML.load_file(KEY_FILE)
169
+ if keys["weather_bug"] && keys["weather_bug"]["code"]
170
+ code = keys["weather_bug"]["code"].to_s
171
+ else
172
+ bug_key_message
173
+ exit
174
+ end
175
+ else
176
+ File.open(KEY_FILE, 'w') {|f| f << "\nweather_bug:\n code: API_CODE" }
177
+ bug_key_message
178
+ exit
179
+ end
180
+ { :weather_bug => { :keys => { :code => code } } }
181
+ end
160
182
 
161
183
  # Performs post-parse processing on options
162
184
  def process_options
163
185
  @options.sources << :wunderground if @options.default
164
186
  @options.sources = @options.sources.uniq
165
187
  Barometer.force_geocode = @options.geocode
188
+ Barometer.enhance_timezone = @options.timezone
166
189
  if @options.sources.include?(:weather_dot_com)
167
190
  @options.sources.delete(:weather_dot_com)
168
191
  @options.sources << config_weather_dot_com
169
192
  end
193
+ if @options.sources.include?(:weather_bug)
194
+ @options.sources.delete(:weather_bug)
195
+ @options.sources << config_weather_bug
196
+ end
170
197
  Barometer.config = { 1 => @options.sources }
171
198
  Barometer.timeout = @options.timeout
172
199
  end
@@ -206,12 +233,14 @@ class App
206
233
  puts " -V, --verbose Verbose output"
207
234
  puts " -t, --timeout seconds until service queries will timeout"
208
235
  puts " -g, --geocode Force Geocoding of query"
236
+ puts " -z, --timezone Force timezone query"
209
237
  puts " -m, --metric measure in metric"
210
238
  puts " -i, --imperial measure in imperial"
211
239
  puts " --wunderground add wunderground as a source"
212
240
  puts " --yahoo add yahoo as a source"
213
241
  puts " --google add google as a source"
214
242
  puts " --weather add weather.com as a source"
243
+ puts " --bug add weather_bug as a source"
215
244
  puts " -p, --pop pop threshold used to determine wet?"
216
245
  puts " -s, --wind wind speed threshold used to determine windy?"
217
246
  puts " -a, --at time/date used to determine when to calculate summary"
@@ -232,7 +261,14 @@ class App
232
261
  else
233
262
  barometer = Barometer.new(@arguments.join(" "))
234
263
  begin
264
+ if @options.verbose
265
+ Barometer::debug!
266
+ div(char="*")
267
+ puts "DEBUG LOG"
268
+ blank
269
+ end
235
270
  barometer.measure(@options.metric) if barometer
271
+ blank if @options.verbose
236
272
  pretty_output(barometer) if barometer.weather
237
273
  rescue Barometer::OutOfSources
238
274
  puts
@@ -292,8 +328,8 @@ def pretty_summary(s)
292
328
  section("SUMMARY#{ " (@ #{@options.at})" if @options.at }") do
293
329
  pretty_hash({
294
330
  "day?" => s.day?(@options.at), "sunny?" => s.sunny?(@options.at),
295
- "windy?" => s.windy?(@options.metric ? @options.windy_m : @options.windy_i, @options.at),
296
- "wet?" => s.wet?(@options.pop,@options.at) })
331
+ "windy?" => s.windy?(@options.at, @options.metric ? @options.windy_m : @options.windy_i),
332
+ "wet?" => s.wet?(@options.at, @options.pop) })
297
333
  end
298
334
  end
299
335
 
@@ -342,7 +378,8 @@ end
342
378
  def pretty_timezone(t)
343
379
  return unless t
344
380
  section("TIMEZONE", 2) do
345
- pretty_hash({ "Long" => t.timezone, "Code" => t.code,"DST?" => t.dst? })
381
+ pretty_hash({ "Long" => t.full, "Code" => t.code, "DST?" => t.dst?,
382
+ "Now" => t.now(true), "Today" => t.today })
346
383
  end
347
384
  end
348
385
 
@@ -401,7 +438,8 @@ def pretty_measurement(m)
401
438
  pretty_hash({
402
439
  "Measured At" => m.measured_at,
403
440
  "Source" => m.source, "Time Stamp" => m.utc_time_stamp,
404
- "Metric" => m.metric?, "Success" => m.success? })
441
+ "Metric" => m.metric?, "Success" => m.success?,
442
+ "Service Time" => "#{(m.end_at - m.start_at)} s" })
405
443
  end
406
444
  section("MODIFIED QUERY", 2) do
407
445
  pretty_hash({ "Query" => m.query, "Format" => m.format })
@@ -423,10 +461,11 @@ def pretty_measurements(w)
423
461
  end
424
462
  end
425
463
 
426
- def pretty_info
464
+ def pretty_info(w)
427
465
  title("INFO", 1)
428
466
  value("GitHub", "http://github.com/attack/barometer")
429
467
  value("Barometer Version", BAROMETER_VERSION)
468
+ value("Total Time", "#{(w.end_at - w.start_at)} s")
430
469
  end
431
470
 
432
471
  def pretty_output(barometer)
@@ -441,7 +480,7 @@ def pretty_output(barometer)
441
480
  pretty_summary(weather)
442
481
  pretty_query(barometer.query)
443
482
  pretty_measurements(weather)
444
- pretty_info
483
+ pretty_info(weather)
445
484
  div("-")
446
485
  end
447
486
  end
@@ -481,6 +520,17 @@ def weather_key_message
481
520
  puts
482
521
  end
483
522
 
523
+ def bug_key_message
524
+ puts
525
+ puts "MISSING KEYS !!!"
526
+ puts "Please update the key_file '#{KEY_FILE}' with your weather_bug api key"
527
+ puts "Get it here: ???"
528
+ puts "Then, add these lines to the file:"
529
+ puts "weather_bug:"
530
+ puts " code: API_CODE"
531
+ puts
532
+ end
533
+
484
534
  # set API keys
485
535
  if File.exists?(KEY_FILE)
486
536
  keys = YAML.load_file(KEY_FILE)
data/lib/barometer.rb CHANGED
@@ -9,6 +9,12 @@ require 'barometer/formats'
9
9
 
10
10
  module Barometer
11
11
 
12
+ @@debug_mode = false
13
+ def self.debug; @@debug_mode; end;
14
+ def self.debug=(value); @@debug_mode = value; end;
15
+ def self.debug!; @@debug_mode = true; end;
16
+ def self.debug?; @@debug_mode; end;
17
+
12
18
  @@google_geocode_key = nil
13
19
  def self.google_geocode_key; @@google_geocode_key; end;
14
20
  def self.google_geocode_key=(key); @@google_geocode_key = key; end;
@@ -25,6 +31,11 @@ module Barometer
25
31
  def self.force_geocode=(value); @@force_geocode = value; end;
26
32
  def self.force_geocode!; @@force_geocode = true; end;
27
33
 
34
+ @@enhance_timezone = false
35
+ def self.enhance_timezone; @@enhance_timezone; end;
36
+ def self.enhance_timezone=(value); @@enhance_timezone = value; end;
37
+ def self.enhance_timezone!; @@enhance_timezone = true; end;
38
+
28
39
  # adjust the timeout used when interactind with external web services
29
40
  #
30
41
  @@timeout = 15
@@ -22,6 +22,7 @@ module Barometer
22
22
  #
23
23
  def measure(metric=nil)
24
24
  return nil unless @query
25
+ @weather.start_at = Time.now.utc
25
26
 
26
27
  level = 1
27
28
  until self.success?
@@ -32,6 +33,8 @@ module Barometer
32
33
  end
33
34
  level += 1
34
35
  end
36
+
37
+ @weather.end_at = Time.now.utc
35
38
  @weather
36
39
  end
37
40
 
@@ -1,11 +1,7 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
 
3
- # measurements and units
3
+ # units
4
4
  #
5
- require 'data/measurement'
6
- require 'data/current'
7
- require 'data/forecast'
8
- require 'data/night'
9
5
  require 'data/zone'
10
6
  require 'data/sun'
11
7
  require 'data/geo'
@@ -16,4 +12,13 @@ require 'data/distance'
16
12
  require 'data/speed'
17
13
  require 'data/pressure'
18
14
  require 'data/local_time'
19
- require 'data/local_datetime'
15
+ require 'data/local_datetime'
16
+
17
+ # measurements
18
+ #
19
+ require 'measurements/measurement'
20
+ require 'measurements/common'
21
+ require 'measurements/current'
22
+ require 'measurements/forecast_array'
23
+ require 'measurements/forecast'
24
+ require 'measurements/night'
@@ -18,6 +18,16 @@ module Barometer
18
18
  def nil?
19
19
  (@rise || @set) ? false : true
20
20
  end
21
+
22
+ def after_rise?(time)
23
+ raise ArgumentError unless time.is_a?(Data::LocalTime)
24
+ time >= @rise
25
+ end
21
26
 
27
+ def before_set?(time)
28
+ raise ArgumentError unless time.is_a?(Data::LocalTime)
29
+ time <= @set
30
+ end
31
+
22
32
  end
23
33
  end
@@ -11,19 +11,49 @@ module Barometer
11
11
  #
12
12
  class Data::Zone
13
13
 
14
- attr_accessor :timezone, :tz
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")
30
+ end
31
+ end
15
32
 
16
- def initialize(timezone)
17
- @timezone = timezone
18
- @tz = TZInfo::Timezone.get(timezone)
33
+ def current
34
+ @zone_full || @zone_offset || @zone_code
19
35
  end
20
36
 
21
37
  # what is the Timezone Short Code for the current timezone
22
38
  def code
23
- return "" unless @tz
39
+ return @zone_code if @zone_code
40
+ return nil unless @tz
24
41
  @tz.period_for_utc(Time.now.utc).zone_identifier.to_s
25
42
  end
26
43
 
44
+ def full
45
+ @zone_full || nil
46
+ end
47
+
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
54
+ end
55
+ end
56
+
27
57
  # is the current timezone in daylights savings mode?
28
58
  def dst?
29
59
  return nil unless @tz
@@ -31,98 +61,59 @@ module Barometer
31
61
  end
32
62
 
33
63
  # return Time.now.utc for the set timezone
34
- def now
35
- Data::Zone.now(@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
69
+ end
70
+ convert ? Data::LocalTime.parse(now) : now
36
71
  end
37
72
 
38
73
  # return Date.today for the set timezone
39
74
  def today
40
- Data::Zone.today(@timezone)
75
+ now = self.now
76
+ Date.new(now.year, now.month, now.day)
41
77
  end
42
78
 
43
79
  def local_to_utc(local_time)
44
- @tz.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)
86
+ end
45
87
  end
46
88
 
47
89
  def utc_to_local(utc_time)
48
- @tz.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
94
+ end
49
95
  end
50
96
 
51
97
  #
52
98
  # Class Methods
53
99
  #
54
100
 
55
- # return the local current time, providing a timezone
56
- # (ie 'Europe/Paris') will give the local time for the
57
- # timezone, otherwise it will be Time.now
58
- def self.now(timezone=nil)
59
- if timezone
60
- utc = Time.now.utc
61
- tz = TZInfo::Timezone.get(timezone)
62
- tz.utc_to_local(utc)
63
- else
64
- Time.now
65
- end
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))
66
105
  end
67
106
 
68
- # return the local current date, providing a timezone
69
- # (ie 'Europe/Paris') will give the local date for the
70
- # timezone, otherwise it will be Date.today
71
- def self.today(timezone=nil)
72
- if timezone
73
- utc = Time.now.utc
74
- tz = TZInfo::Timezone.get(timezone)
75
- now = tz.utc_to_local(utc)
76
- Date.new(now.year, now.month, now.day)
77
- else
78
- Date.today
79
- end
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
80
110
  end
81
111
 
82
- # takes a time (any timezone), and a TimeZone Short Code (ie PST) or
83
- # the number of hours offset from UTC time and
84
- # converts the time to UTC according to that time_zone
85
- # NOTE: No Tests
86
- def self.code_to_utc(time, timezone)
87
- raise ArgumentError unless time.is_a?(Time)
88
-
89
- offset = self.zone_to_offset(timezone)
90
-
91
- Time.utc(
92
- time.year, time.month, time.day,
93
- time.hour, time.min, time.sec, time.usec
94
- ) - offset
95
- end
96
-
97
- # takes a string with TIME only information and merges it with a string that
98
- # has DATE only information and creates a UTC TIME object with time and date
99
- # info. if you supply the timezone code (ie PST), it will apply the timezone
100
- # offset to the final time
101
- def self.merge(time, date, timezone_code=nil)
102
- raise ArgumentError unless (time.is_a?(Time) || time.is_a?(String))
103
- raise ArgumentError unless (date.is_a?(Time) || date.is_a?(Date) || date.is_a?(String))
104
-
105
- if time.is_a?(String)
106
- reference_time = Time.parse(time)
107
- elsif time.is_a?(Time)
108
- reference_time = time
109
- end
110
-
111
- if date.is_a?(String)
112
- reference_date = Date.parse(date)
113
- elsif date.is_a?(Time)
114
- reference_date = Date.new(date.year, date.month, date.day)
115
- elsif date.is_a?(Date)
116
- reference_date = date
117
- end
118
-
119
- new_time = Time.utc(
120
- reference_date.year, reference_date.month, reference_date.day,
121
- reference_time.hour, reference_time.min, reference_time.sec
122
- )
123
- timezone_code ? Data::Zone.code_to_utc(new_time,timezone_code) : new_time
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
124
115
  end
125
-
116
+
126
117
  #
127
118
  # Known conflicts
128
119
  # IRT (ireland and india)
@@ -131,119 +122,19 @@ module Barometer
131
122
  def self.zone_to_offset(timezone)
132
123
  offset = 0
133
124
  seconds_in_hour = 60*60
134
- # do we have a short_timezone code, or an offset?
135
- if timezone.is_a?(Fixnum) ||
136
- (timezone.is_a?(String) && timezone.to_i.to_s == timezone)
137
- # we have an offset, convert to second
138
- offset = timezone.to_i * seconds_in_hour
139
- else
140
- # try to use Time
141
- unless offset = Time.zone_offset(timezone)
142
- # that would have been too easy, do it manually
143
- # http://www.timeanddate.com/library/abbreviations/timezones/
144
- # http://www.worldtimezone.com/wtz-names/timezonenames.html
145
- zone_offsets = {
146
- :A => 1, :ACDT => 10.5, :ACST => 9.5, :ADT => -3, :AEDT => 11,
147
- :AEST => 10, :AFT => 4.5, :AHDT => -9, :AHST => -10, :AKDT => -8,
148
- :AKST => -9, :AMST => 5, :AMT => 4, :ANAST => 13, :ANAT => 12,
149
- :ART => -3, :AST => -4, :AT => -1, :AWDT => 9, :AWST => 8,
150
- :AZOST => 0, :AZOT => -1, :AZST => 5, :AZT => 4,
151
-
152
- :B => 2, :BADT => 4, :BAT => 6, :BDST => 2, :BDT => 6, :BET => -11,
153
- :BNT => 8, :BORT => 8, :BOT => -4, :BRA => -3, :BST => 1, :BT => 6,
154
- :BTT => 6,
155
-
156
- :C => 3, :CAT => 2, :CCT => 8, :CEST => 2, :CET => 1, :CHADT => 13.75,
157
- :CHAST => 12.75, :CHST => 10, :CKT => -10, :CLST => -3, :CLT => -4,
158
- :COT => -5, :CUT => 0, :CVT => -1, :CWT => 8.75, :CXT => 7, :CEDT => 2,
159
-
160
- :D => 4, :DAVT => 7, :DDUT => 10, :DNT => 1, :DST => 2,
161
-
162
- :E => 5, :EASST => -5, :EAST => -6, :EAT => 3, :ECT => -5, :EEST => 3,
163
- :EET => 2, :EGST => 0, :EGT => -1, :EMT => 1, :EEDT => 3,
164
-
165
- :F => 6, :FDT => -1, :FJST => 13, :FJT => 12, :FKST => -3, :FKT => -4,
166
- :FST => 2, :FWT => 1,
167
-
168
- :G => 7, :GALT => -6, :GAMT => -9, :GEST => 5, :GET => 4, :GFT => -3,
169
- :GILT => 12, :GST => 4, :GT => 0, :GYT => -4, :GZ => 0,
170
-
171
- :H => 8, :HAA => -3, :HAC => -5, :HADT => -9, :HAE => -4, :HAP => -7,
172
- :HAR => -6, :HAST => -10, :HAT => -2.5, :HAY => -8, :HDT => -9.5,
173
- :HFE => 2, :HFH => 1, :HG => 0, :HKT => 8, :HNA => -4, :HNC => -6,
174
- :HNE => -5, :HNP => -8, :HNR => -7, :HNT => -3.5, :HNY => -9,
175
- :HOE => 1, :HST => -10,
176
-
177
- :I => 9, :ICT => 4, :IDLE => 12, :IDLW => -12, :IDT => 1, :IOT => 5,
178
- :IRDT => 4.5, :IRKST => 9, :IRKT => 8, :IRST => 3.5, :IRT => 3.5,
179
- :IST => 1, :IT => 3.5, :ITA => 1,
180
-
181
- :JAVT => 7, :JAYT => 9, :JFDT => -3, :JFST => -4, :JST => 9, :JT => 7,
182
-
183
- :K => 10, :KDT => 10, :KGST => 6, :KGT => 5, :KOST => 12, :KOVT => 7,
184
- :KOVST => 8, :KRAST => 8, :KRAT => 7, :KST => 9,
185
-
186
- :L => 11, :LHDT => 11, :LHST => 10.5, :LIGT => 10, :LINT => 14, :LKT => 6,
187
- :LST => 1,
188
-
189
- :M => 12, :MAGST => 12, :MAGT => 11, :MAL => 8, :MART => -9.5, :MAT => 3,
190
- :MAWT => 6, :MBT => 8, :MED => 2, :MEDST => 2, :MEST => 2, :MESZ => 2,
191
- :MET => 1, :MEWT => 1, :MEX => -6, :MEZ => 1, :MHT => 12, :MIT => 9.5,
192
- :MMT => 6.5, :MNT => 8, :MNST => 9, :MPT => 10, :MSD => 4, :MSK => 3,
193
- :MSKS => 4, :MT => 8.5, :MUT => 4, :MUST => 5, :MVT => 5, :MYT => 8,
194
- :MFPT => -10,
195
-
196
- :N => -1, :NCT => 11, :NDT => -2.5, :NFT => 11.5, :NOR => 1, :NOVST => 7,
197
- :NOVT => 6, :NPT => 5.75, :NRT => 12, :NST => -3.5, :NSUT => 6.5,
198
- :NT => -11, :NUT => -11, :NZDT => 13, :NZST => 12, :NZT => 12,
199
-
200
- :O => -2, :OESZ => 3, :OEZ => 2, :OMSK => 7, :OMSST => 7, :OMST => 6,
201
-
202
- :P => -3, :PET => -5, :PETST => 13, :PETT => 12, :PGT => 10, :PHOT => 13,
203
- :PHT => 8, :PIT => 8, :PKT => 5, :PKST => 6, :PMDT => -2, :PMST => -3,
204
- :PMT => -3, :PNT => -8.5, :PONT => 11, :PYST => -3, :PYT => -4, :PWT => 9,
205
-
206
- :Q => -4,
207
-
208
- :R => -5, :R1T => 2, :R2T => 3, :RET => 4, :ROK => 9, :ROTT => -3,
209
-
210
- :S => -6, :SADT => 10.5, :SAMST => 5, :SAMT => 4, :SAST => 2, :SBT => 11,
211
- :SCT => 4, :SCDT => 13, :SCST => 12, :SET => 1, :SGT => 8, :SIT => 8,
212
- :SLT => -4, :SLST => -3, :SRT => -3, :SST => -11, :SYST => 3, :SWT => 1,
213
- :SYT => 2,
214
-
215
- :T => -7, :TAHT => -10, :TFT => 5, :THA => 7, :THAT => -10, :TJT => 5,
216
- :TKT => -10, :TMT => 5, :TOT => 13, :TRUK => 10, :TPT => 9, :TRUT => 10,
217
- :TST => 3, :TUC => 0, :TVT => 12, :TWT => 8,
218
-
219
- :U => -8, :ULAST => 9, :ULAT => 8, :USZ1 => 2, :USZ1S => 3, :USZ3 => 4,
220
- :USZ3S => 5, :USZ4 => 5, :USZ4S => 6, :USZ5 => 6, :USZ5S => 7, :USZ6 => 7,
221
- :USZ6S => 8, :USZ7 => 8, :USZ7S => 9, :USZ8 => 9, :USZ8S => 10, :USZ9 => 10,
222
- :USZ9S => 11, :UTZ => -3, :UYT => -3, :UYST => -2, :UZ10 => 11, :UZ10S => 12,
223
- :UZ11 => 12, :UZ11S => 13, :UZ12 => 12, :UZ12S => 13, :UZT => 5,
224
-
225
- :V => -9, :VET => -4.5, :VLAST => 11, :VLAT => 10, :VOST => 6, :VST => -4.5,
226
- :VTZ => -2, :VUT => 11,
227
-
228
- :W => -10, :WAKT => 12, :WAST => 2, :WAT => 1, :WCT => 8.75, :WEST => 1,
229
- :WESZ => 1, :WET => 0, :WEZ => 0, :WFT => 12, :WGST => -2, :WGT => -3,
230
- :WIB => 7, :WITA => 8, :WIT => 9, :WST => 8, :WKST => 5, :WTZ => -1,
231
- :WUT => 1, :WEDT => 1, :WDT => 9,
232
-
233
- :X => -11,
234
-
235
- :Y => -12, :YAKST => 10, :YAKT => 9, :YAPT => 10, :YDT => -8, :YEKST => 6,
236
- :YEKT => 5, :YST => -9,
237
-
238
- :Z => 0
239
- }
240
- # unknown
241
- # :HL => X, :LST => X, :LT => X, :OZ => X :SZ => X :TAI => X :UT => X :WZ => X
242
-
243
- offset = (zone_offsets[timezone.to_s.upcase.to_sym] || 0) * seconds_in_hour
244
- end
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
245
131
  end
246
- return offset
132
+ offset
133
+ end
134
+
135
+ def self._load_zone_codes
136
+ $:.unshift(File.dirname(__FILE__))
137
+ @@zone_codes ||= YAML.load_file(@@zone_codes_file)
247
138
  end
248
139
 
249
140
  end