metar-parser 1.1.8 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5f2c3aa5a4cae4d28cfa2ac65827416eae8ea706
4
+ data.tar.gz: 2edc10a772b9142531f3e3a942b5c913d043c98b
5
+ SHA512:
6
+ metadata.gz: aa27381ba8e8bca2a90df135f4d1d3d9558d8c063f119e575a51e76577b4bb97164412204d0cffd49d4557e6ea99654ddd44b48c3781dfd4826bb3a4e18c93dd
7
+ data.tar.gz: 18eb8ba4319e3864b129dce58fffc9231623e63da8f8c737445c53693e5eaef669c9d4da3c87377d2b3dffcdaac00787a848c51fcd679cecd31d47396a2e08e5
data/README.md CHANGED
@@ -15,19 +15,15 @@ metar-parser [![Build Status](https://secure.travis-ci.org/joeyates/metar-parser
15
15
 
16
16
  The information comes from the National Oceanic and Atmospheric Association's raw data source.
17
17
 
18
- Usage
19
- =====
18
+ # Installation
20
19
 
21
20
  ```ruby
22
- require 'rubygems' if RUBY_VERSION < '1.9'
23
21
  require 'metar'
24
22
  ```
25
23
 
26
- Examples
27
- ========
24
+ # Examples
28
25
 
29
- Hello World
30
- -----------
26
+ ## Hello World
31
27
 
32
28
  This prints the latest weather report for Portland International Airport:
33
29
 
@@ -36,39 +32,59 @@ station = Metar::Station.find_by_cccc('KPDX')
36
32
  puts station.report.to_s
37
33
  ```
38
34
 
39
- Countries
40
- ---------
35
+ ## Using Your Own Raw Data
41
36
 
42
- List countries:
37
+ The parser needs to know the full date when the reading was taken. Unfortunately,
38
+ the METAR string itself only contains the day of the month.
39
+
40
+ ### When you know the date of the reading
41
+
42
+ Use `Metar::Raw::Data` and supply the date as the second parameter:
43
43
 
44
44
  ```ruby
45
- puts Metar::Station.countries
45
+ metar_string = "KHWD 280554Z AUTO 29007KT 10SM OVC008 14/12 A3002 RMK AO2 SLP176 T01390117 10211\n"
46
+ raw = Metar::Raw::Data.new(metar_string, reading_date)
47
+ parser = Metar::Parser.new(raw)
46
48
  ```
47
49
 
48
- Find a country's weather stations:
50
+ ### When you do not know the date
51
+
52
+ Use `Metar::Raw::Metar` - the library will choose the date as the most recent
53
+ day with the day of the month indicated in the METAR string:
54
+
55
+ I.e. on 11th April 2016:
49
56
 
50
57
  ```ruby
51
- spanish = Metar::Station.find_all_by_country('Spain')
58
+ metar_string = "KHWD 280554Z AUTO 29007KT 10SM OVC008 14/12 A3002 RMK AO2 SLP176 T01390117 10211\n"
59
+ raw = Metar::Raw::Metar.new(metar_string)
60
+ raw.time.to_s # => "2016-03-28"
61
+ parser = Metar::Parser.new(raw)
52
62
  ```
53
63
 
54
- Get The Data
55
- ------------
64
+ ## Access Specific Data
65
+
56
66
  ```ruby
57
67
  station = Metar::Station.find_by_cccc('KPDX')
58
68
  parser = station.parser
59
69
  puts parser.temperature.value
60
70
  ```
61
71
 
62
- Use Your Own Raw Data
63
- ---------------------
72
+ # Countries
73
+
74
+ List countries:
75
+
64
76
  ```ruby
65
- metar_string = "KHWD 280554Z AUTO 29007KT 10SM OVC008 14/12 A3002 RMK AO2 SLP176 T01390117 10211\n"
66
- raw = Metar::Raw::Data.new(metar_string)
67
- parser = Metar::Parser.new(raw)
77
+ puts Metar::Station.countries
68
78
  ```
69
79
 
70
- Translations
71
- ------------
80
+ Find a country's weather stations:
81
+
82
+ ```ruby
83
+ spanish = Metar::Station.find_all_by_country('Spain')
84
+ ```
85
+
86
+ # Translations
87
+
72
88
  Translations are available for the following languages (and region):
73
89
  * :de
74
90
  * :en
@@ -84,8 +100,7 @@ I18n.locale = :'en-US'
84
100
  I18n.t('metar.station_code.title') # station code
85
101
  ```
86
102
 
87
- Compliance
88
- ==========
103
+ # Compliance
89
104
 
90
105
  By default, the parser runs in 'loose' compliance mode. That means that it tries to
91
106
  accept non-standard input.
data/Rakefile CHANGED
@@ -8,14 +8,3 @@ task :default => :spec
8
8
  RSpec::Core::RakeTask.new do | t |
9
9
  t.pattern = 'spec/**/*_spec.rb'
10
10
  end
11
-
12
- if RUBY_VERSION < '1.9'
13
-
14
- RSpec::Core::RakeTask.new( 'spec:rcov' ) do |t|
15
- t.pattern = 'spec/**/*_spec.rb'
16
- t.rcov = true
17
- t.rcov_opts = [ '--exclude', 'spec/,/gems/' ]
18
- end
19
-
20
- end
21
-
data/bin/parse_raw.rb CHANGED
@@ -6,7 +6,6 @@ Use the data downloaded by 'download_raw.rb' to bulk test the Report
6
6
 
7
7
  =end
8
8
 
9
- require 'rubygems' if RUBY_VERSION < '1.9'
10
9
  require 'yaml'
11
10
  require File.join(File.expand_path(File.dirname(__FILE__) + '/../lib'), 'metar')
12
11
 
data/lib/metar/raw.rb CHANGED
@@ -1,26 +1,70 @@
1
+ require 'date'
1
2
  require 'net/ftp'
2
3
  require 'time'
3
4
 
4
5
  module Metar
5
-
6
6
  module Raw
7
-
8
7
  class Base
9
- attr_reader :cccc
10
8
  attr_reader :metar
11
9
  attr_reader :time
12
10
  alias :to_s :metar
13
-
14
- def parse
15
- @cccc = @metar[/\w+/]
16
- end
17
11
  end
18
12
 
13
+ ##
14
+ # Use this class when you have a METAR string and the date of reading
19
15
  class Data < Base
20
- def initialize(metar, time = Time.now)
16
+ def initialize(metar, time = nil)
17
+ if time == nil
18
+ warn <<-EOT
19
+ Using Metar::Raw::Data without a time parameter is deprecated.
20
+ Please supply the reading time as the second parameter.
21
+ EOT
22
+ time = Time.now
23
+ end
21
24
  @metar, @time = metar, time
25
+ end
26
+ end
22
27
 
23
- parse
28
+ ##
29
+ # Use this class when you only have a METAR string.
30
+ # The date of the reading is decided as follows:
31
+ # * the day of the month is extracted from the METAR,
32
+ # * the most recent day with that day of the month is taken as the
33
+ # date of the reading.
34
+ class Metar < Base
35
+ def initialize(metar)
36
+ @metar = metar
37
+ @time = nil
38
+ end
39
+
40
+ def time
41
+ return @time if @time
42
+ dom = day_of_month
43
+ date = Date.today
44
+ loop do
45
+ if date.day >= dom
46
+ @time = Date.new(date.year, date.month, dom)
47
+ break
48
+ end
49
+ # skip to the last day of the previous month
50
+ date = Date.new(date.year, date.month, 1).prev_day
51
+ end
52
+ @time
53
+ end
54
+
55
+ private
56
+
57
+ def datetime
58
+ datetime = metar[/^\w{4} (\d{6})Z/, 1]
59
+ raise "The METAR string must have a 6 digit datetime" if datetime.nil?
60
+ datetime
61
+ end
62
+
63
+ def day_of_month
64
+ dom = datetime[0..1].to_i
65
+ raise "Day of month must be at most 31" if dom > 31
66
+ raise "Day of month must be greater than 0" if dom == 0
67
+ dom
24
68
  end
25
69
  end
26
70
 
@@ -44,9 +88,9 @@ module Metar
44
88
  end
45
89
 
46
90
  def disconnect
47
- return if @connection.nil
48
- @connection.close
49
- @cconnection = nil
91
+ return if @@connection.nil
92
+ @@connection.close
93
+ @@connection = nil
50
94
  end
51
95
 
52
96
  def fetch(cccc)
@@ -101,13 +145,8 @@ module Metar
101
145
 
102
146
  def parse
103
147
  raw_time, @metar = @data.split("\n")
104
- @time = Time.parse(raw_time)
105
- super
148
+ @time = Time.parse(raw_time + " UTC")
106
149
  end
107
-
108
150
  end
109
-
110
151
  end
111
-
112
152
  end
113
-
data/lib/metar/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Metar
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 1
5
- TINY = 8
4
+ MINOR = 2
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'rspec'
2
- require 'rspec/autorun'
3
2
 
4
3
  if RUBY_VERSION > '1.9'
5
4
  require 'simplecov'
@@ -1,86 +1,76 @@
1
1
  # encoding: utf-8
2
- load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
2
+ require "spec_helper"
3
3
 
4
4
  describe Metar::Distance do
5
+ let(:value) { 12345.6789 }
5
6
 
6
- context '#value' do
7
-
8
- it 'should treat the parameter as meters' do
9
- @distance = Metar::Distance.new( 12345.67 )
7
+ subject { described_class.new(value) }
10
8
 
11
- @distance.units. should == :meters
12
- @distance.value. should == 12345.67
9
+ context '#value' do
10
+ it 'treats the parameter as meters' do
11
+ expect(subject.units).to eq(:meters)
12
+ expect(subject.value).to eq(12345.6789)
13
13
  end
14
-
15
14
  end
16
15
 
17
16
  context '#to_s' do
18
-
19
17
  it 'should default to meters' do
20
- @distance = Metar::Distance.new( rand * 1000.0 )
21
-
22
- @distance.to_s. should =~ %r(^\d+m)
18
+ expect(subject.to_s).to match(%r(^\d+m))
23
19
  end
24
20
 
25
- it 'should round down to the nearest meter' do
26
- @distance = Metar::Distance.new( 12.345 )
21
+ context 'when <= 0.5' do
22
+ let(:value) { 12.345678 }
27
23
 
28
- @distance.to_s. should == '12m'
24
+ it 'should round down to the nearest meter' do
25
+ expect(subject.to_s).to eq('12m')
26
+ end
29
27
  end
30
28
 
31
- it 'should round up to meters' do
32
- @distance = Metar::Distance.new( 8.750 )
29
+ context 'when > 0.5' do
30
+ let(:value) { 8.750 }
33
31
 
34
- @distance.to_s. should == '9m'
32
+ it 'should round up to meters' do
33
+ expect(subject.to_s).to eq('9m')
34
+ end
35
35
  end
36
36
 
37
- it 'should allow units overrides' do
38
- @distance = Metar::Distance.new( 12345.67 )
39
-
40
- @distance.to_s( :units => :kilometers ).
41
- should == '12km'
37
+ it 'allows units overrides' do
38
+ expect(subject.to_s(units: :kilometers)).to eq('12km')
42
39
  end
43
40
 
44
- it 'should allow precision overrides' do
45
- @distance = Metar::Distance.new( 12.34567 )
46
-
47
- @distance.to_s( :precision => 1 ).
48
- should == '12.3m'
41
+ it 'allows precision overrides' do
42
+ expect(subject.to_s(precision: 1)).to eq('12345.7m')
49
43
  end
50
44
 
51
- it 'should handle nil' do
52
- @distance = Metar::Distance.new( nil )
45
+ context 'when value is nil' do
46
+ let(:value) { nil }
53
47
 
54
- @distance.to_s. should == 'unknown'
48
+ it 'is unknown' do
49
+ expect(subject.to_s).to eq('unknown')
50
+ end
55
51
  end
56
52
 
57
53
  context 'translated' do
58
-
59
- before :each do
54
+ before do
60
55
  @locale = I18n.locale
61
56
  I18n.locale = :it
62
57
  end
63
58
 
64
- after :each do
59
+ after do
65
60
  I18n.locale = @locale
66
61
  end
67
62
 
68
- it 'should allow precision overrides' do
69
- @distance = Metar::Distance.new( 12.34567 )
70
-
71
- @distance.to_s( :precision => 1 ).
72
- should == '12,3m'
63
+ it 'localizes the decimal separator' do
64
+ expect(subject.to_s(precision: 1)).to eq('12345,7m')
73
65
  end
74
66
 
75
- it 'should handle nil' do
76
- @distance = Metar::Distance.new( nil )
67
+ context 'when value is nil' do
68
+ let(:value) { nil }
77
69
 
78
- @distance.to_s. should == 'sconosciuto'
70
+ it 'translates' do
71
+ expect(subject.to_s).to eq('sconosciuto')
72
+ end
79
73
  end
80
-
81
74
  end
82
-
83
75
  end
84
-
85
76
  end
86
-
@@ -1,19 +1,25 @@
1
1
  # encoding: utf-8
2
2
  require 'spec_helper'
3
3
 
4
+ require 'timecop'
5
+
4
6
  describe Metar::Parser do
5
7
  after do
6
8
  Metar::Parser.compliance = :loose
7
9
  end
8
10
 
9
11
  context '.for_cccc' do
10
- it 'returns a loaded parser' do
11
- station = stub('station')
12
- raw = stub('raw', :metar => "XXXX 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000",
13
- :time => '2010/02/06 16:10')
14
- Metar::Station.stub!(:new => station)
15
- Metar::Raw::Noaa.stub!(:new => raw)
12
+ let(:station) { double(Metar::Station) }
13
+ let(:raw) { double(Metar::Raw::Noaa, metar: metar, time: time) }
14
+ let(:metar) { "XXXX 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000" }
15
+ let(:time) { '2010/02/06 16:10' }
16
16
 
17
+ before do
18
+ allow(Metar::Station).to receive(:new) { station }
19
+ allow(Metar::Raw::Noaa).to receive(:new) { raw }
20
+ end
21
+
22
+ it 'returns a loaded parser' do
17
23
  parser = Metar::Parser.for_cccc('XXXX')
18
24
 
19
25
  expect(parser).to be_a(Metar::Parser)
@@ -22,10 +28,10 @@ describe Metar::Parser do
22
28
  end
23
29
 
24
30
  context 'attributes' do
25
- before do
26
- @call_time = Time.parse('2011-05-06 16:35')
27
- Time.stub!(:now).and_return(@call_time)
28
- end
31
+ let(:call_time) { Time.parse('2011-05-06 16:35') }
32
+
33
+ before { Timecop.freeze(call_time) }
34
+ after { Timecop.return }
29
35
 
30
36
  it '.location missing' do
31
37
  expect do
@@ -46,6 +52,21 @@ describe Metar::Parser do
46
52
  end.to raise_error(Metar::ParseError, /Expecting datetime/)
47
53
  end
48
54
 
55
+ context 'across a month rollover' do
56
+ let(:time) { Time.gm(2016, 3, 31, 23, 59) }
57
+ let(:metar) { "OPPS 312359Z 23006KT 4000 HZ SCT040 SCT100 17/12 Q1011" }
58
+ let(:raw) { double(Metar::Raw, metar: metar, time: time) }
59
+ let(:call_time) { Time.parse("2016/04/01 00:02:11 PDT") }
60
+
61
+ subject { described_class.new(raw) }
62
+
63
+ it 'has the correct date' do
64
+ expect(subject.time.year).to eq(2016)
65
+ expect(subject.time.month).to eq(3)
66
+ expect(subject.time.day).to eq(31)
67
+ end
68
+ end
69
+
49
70
  context 'in strict mode' do
50
71
  before do
51
72
  Metar::Parser.compliance = :strict
@@ -295,7 +316,7 @@ describe Metar::Parser do
295
316
  end
296
317
 
297
318
  def setup_parser(metar)
298
- raw = Metar::Raw::Data.new(metar)
319
+ raw = Metar::Raw::Data.new(metar, Time.now)
299
320
  Metar::Parser.new(raw)
300
321
  end
301
322
  end