metar-parser 1.1.8 → 1.2.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.
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