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.
- data/README.rdoc +51 -9
- data/VERSION.yml +2 -2
- data/bin/barometer +57 -7
- data/lib/barometer.rb +11 -0
- data/lib/barometer/base.rb +3 -0
- data/lib/barometer/data.rb +11 -6
- data/lib/barometer/data/sun.rb +10 -0
- data/lib/barometer/data/zone.rb +79 -188
- data/lib/barometer/formats/coordinates.rb +4 -1
- data/lib/barometer/formats/geocode.rb +9 -7
- data/lib/barometer/formats/icao.rb +2 -2
- data/lib/barometer/formats/weather_id.rb +2 -2
- data/lib/barometer/measurements/common.rb +113 -0
- data/lib/barometer/{data → measurements}/current.rb +17 -42
- data/lib/barometer/measurements/forecast.rb +62 -0
- data/lib/barometer/measurements/forecast_array.rb +72 -0
- data/lib/barometer/{data → measurements}/measurement.rb +57 -45
- data/lib/barometer/measurements/night.rb +27 -0
- data/lib/barometer/query.rb +55 -5
- data/lib/barometer/services.rb +3 -1
- data/lib/barometer/translations/icao_country_codes.yml +274 -1
- data/lib/barometer/translations/weather_country_codes.yml +189 -6
- data/lib/barometer/translations/zone_codes.yml +360 -0
- data/lib/barometer/weather.rb +5 -4
- data/lib/barometer/weather_services/google.rb +19 -35
- data/lib/barometer/weather_services/service.rb +113 -255
- data/lib/barometer/weather_services/weather_bug.rb +291 -2
- data/lib/barometer/weather_services/weather_dot_com.rb +45 -54
- data/lib/barometer/weather_services/wunderground.rb +83 -89
- data/lib/barometer/weather_services/yahoo.rb +44 -91
- data/lib/barometer/web_services/geocode.rb +1 -0
- data/lib/barometer/web_services/timezone.rb +40 -0
- data/lib/barometer/web_services/weather_id.rb +17 -2
- data/lib/demometer/demometer.rb +28 -0
- data/lib/demometer/public/css/master.css +259 -1
- data/lib/demometer/public/css/print.css +94 -0
- data/lib/demometer/public/css/syntax.css +64 -0
- data/lib/demometer/public/images/link-out.gif +0 -0
- data/lib/demometer/views/about.erb +10 -0
- data/lib/demometer/views/index.erb +2 -0
- data/lib/demometer/views/layout.erb +3 -2
- data/lib/demometer/views/measurement.erb +4 -1
- data/lib/demometer/views/readme.erb +116 -88
- data/spec/data/sun_spec.rb +53 -0
- data/spec/data/zone_spec.rb +330 -100
- data/spec/fixtures/formats/weather_id/ksfo.xml +1 -0
- data/spec/fixtures/services/weather_bug/90210_current.xml +1 -0
- data/spec/fixtures/services/weather_bug/90210_forecast.xml +1 -0
- data/spec/formats/weather_id_spec.rb +10 -5
- data/spec/measurements/common_spec.rb +352 -0
- data/spec/{data → measurements}/current_spec.rb +40 -103
- data/spec/measurements/forecast_array_spec.rb +165 -0
- data/spec/measurements/forecast_spec.rb +135 -0
- data/spec/{data → measurements}/measurement_spec.rb +86 -107
- data/spec/measurements/night_measurement_spec.rb +49 -0
- data/spec/query_spec.rb +12 -2
- data/spec/spec_helper.rb +28 -1
- data/spec/weather_services/google_spec.rb +27 -117
- data/spec/weather_services/services_spec.rb +49 -1024
- data/spec/weather_services/weather_bug_spec.rb +274 -0
- data/spec/weather_services/weather_dot_com_spec.rb +45 -125
- data/spec/weather_services/wunderground_spec.rb +42 -136
- data/spec/weather_services/yahoo_spec.rb +26 -116
- data/spec/weather_spec.rb +45 -45
- metadata +27 -11
- data/lib/barometer/data/forecast.rb +0 -84
- data/lib/barometer/data/night.rb +0 -69
- data/lib/barometer/extensions/graticule.rb +0 -51
- data/spec/data/forecast_spec.rb +0 -192
- 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.
|
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
|
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
|
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
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.
|
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
|
296
|
-
"wet?" => s.wet?(@options.
|
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.
|
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
|
data/lib/barometer/base.rb
CHANGED
@@ -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
|
|
data/lib/barometer/data.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__))
|
2
2
|
|
3
|
-
#
|
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'
|
data/lib/barometer/data/sun.rb
CHANGED
@@ -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
|
data/lib/barometer/data/zone.rb
CHANGED
@@ -11,19 +11,49 @@ module Barometer
|
|
11
11
|
#
|
12
12
|
class Data::Zone
|
13
13
|
|
14
|
-
|
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
|
17
|
-
@
|
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
|
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
|
-
|
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
|
-
|
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
|
-
@
|
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
|
-
@
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
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
|
-
#
|
135
|
-
|
136
|
-
|
137
|
-
#
|
138
|
-
|
139
|
-
|
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
|
-
|
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
|