diff --git a/lib/barometer/data/zone.rb b/lib/barometer/data/zone.rb index 4b3fe48..097123c 100644 --- a/lib/barometer/data/zone.rb +++ b/lib/barometer/data/zone.rb @@ -59,21 +59,27 @@ def utc_to_local(utc_time) end class ZoneOffset + NUMERIC_OFFSET = /(?:^| )([-+]?[01]?\d)(\d\d)?$/ + def self.detect?(zone) + zone.respond_to?(:match) && zone.match(NUMERIC_OFFSET) { |m| zone = m[1].to_i } zone.respond_to?(:abs) && zone.abs <= 14 end def initialize(zone, time_class=::Time) @zone = zone + @offset = case zone + when Integer + zone * 60 * 60 + when NUMERIC_OFFSET + h = $1.to_i * 60 * 60 + m = $2.to_i * 60 + h < 0 ? h - m : h + m + end @time_class = time_class end - def code - end - - def offset - zone.to_f * 60 * 60 - end + attr_reader :code, :offset def now time_class.now.utc + offset diff --git a/lib/barometer/weather_services/wunderground_v1/response/current_weather.rb b/lib/barometer/weather_services/wunderground_v1/response/current_weather.rb index 69f6363..7cddf8c 100644 --- a/lib/barometer/weather_services/wunderground_v1/response/current_weather.rb +++ b/lib/barometer/weather_services/wunderground_v1/response/current_weather.rb @@ -9,7 +9,7 @@ def initialize(payload) end def parse - current.observed_at = observed_at, '%B %e, %l:%M %p %Z' + current.observed_at = observed_at current.stale_at = stale_at current.humidity = humidity current.condition = condition diff --git a/spec/data/zone_spec.rb b/spec/data/zone_spec.rb index cdb9877..71d196c 100644 --- a/spec/data/zone_spec.rb +++ b/spec/data/zone_spec.rb @@ -154,12 +154,42 @@ def stub_time(utc_now) expect( ZoneOffset.detect?('PST') ).to be false end - it 'returns true when given an offset' do + it 'returns true when given a numeric offset' do expect( ZoneOffset.detect?(10) ).to be true end + it 'returns true when given a one-digit hour offset' do + expect( ZoneOffset.detect?('1') ).to be true + expect( ZoneOffset.detect?('+1') ).to be true + expect( ZoneOffset.detect?('-1') ).to be true + end + + it 'returns true when given a two-digit hour offset' do + expect( ZoneOffset.detect?('09') ).to be true + expect( ZoneOffset.detect?('+09') ).to be true + expect( ZoneOffset.detect?('-09') ).to be true + end + + it 'returns true when given a four-digit offset' do + expect( ZoneOffset.detect?('0100') ).to be true + expect( ZoneOffset.detect?('+0100') ).to be true + expect( ZoneOffset.detect?('-1200') ).to be true + end + + it 'returns true when preceded by a space' do + expect( ZoneOffset.detect?('August 9, 6:56 AM -10') ).to be true + end + + it 'returns false when only given a year' do + expect( ZoneOffset.detect?('August 9, 6:56 AM 2017') ).to be false + end + + it 'returns false when part of a date' do + expect( ZoneOffset.detect?('2017-10-10') ).to be false + end + it 'returns false when given an offset out of range' do - expect( ZoneOffset.detect?(15) ).to be false + expect( ZoneOffset.detect?('15') ).to be false end it 'returns false when given nothing' do @@ -178,6 +208,11 @@ def stub_time(utc_now) it 'converts the input from hours to seconds' do expect( ZoneOffset.new(5).offset ).to eq(5 * 60 * 60) end + + it 'converts 4-digit input from HHMM to seconds' do + expect( ZoneOffset.new('+0130').offset ).to eq(90 * 60) + expect( ZoneOffset.new('-0130').offset ).to eq(-90 * 60) + end end describe '#now' do diff --git a/spec/utils/time_spec.rb b/spec/utils/time_spec.rb index 74c2154..c1f91b4 100644 --- a/spec/utils/time_spec.rb +++ b/spec/utils/time_spec.rb @@ -35,13 +35,21 @@ module Barometer assert_times_are_equal(time, start_of_local_day) end - it "parses a String (with no format), assumes UTC" do + it "parses a String with year (with no format), assumes UTC" do t = "March 15, 10:36 AM 2013" time = Utils::Time.parse(t) assert_times_are_equal(time, ::Time.utc(2013, 3, 15, 10, 36, 0)) end + it "parses a String without year (with no format), assumes UTC" do + t = "August 17, 1:16 AM" + + time = Utils::Time.parse(t) + current_year = Time.now.year + assert_times_are_equal(time, ::Time.utc(current_year, 8, 17, 1, 16, 0)) + end + it "parses a String (with optional format), assumes UTC" do format = "%B %e, %l:%M %p %Y" t = "March 15, 10:36 AM 2013" @@ -58,6 +66,13 @@ module Barometer assert_times_are_equal(time, ::Time.utc(2013, 3, 15, 18, 36, 0)) end + it "parses a timezoned String (with no format)" do + t = "March 15, 10:36 AM -0800 2013" + + time = Utils::Time.parse(t) + assert_times_are_equal(time, ::Time.utc(2013, 3, 15, 18, 36, 0)) + end + it "accepts an array of values, creating a UTC time" do time = Utils::Time.parse(2013, 3, 15, 18, 36, 0) assert_times_are_equal(time, ::Time.utc(2013, 3, 15, 18, 36, 0))