edtf 0.0.2 → 0.0.3

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/lib/edtf/parser.y CHANGED
@@ -4,6 +4,7 @@ class EDTF::Parser
4
4
 
5
5
  token T Z E X PLUS MINUS COLON SLASH D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 LP RP
6
6
  UNCERTAIN APPROXIMATE UNSPECIFIED UNKNOWN OPEN LONGYEAR CARET UNMATCHED
7
+ DOTS COMMA LBRACE RBRACE LSQUARE RSQUARE
7
8
 
8
9
  expect 0
9
10
 
@@ -24,11 +25,11 @@ rule
24
25
  date : positive_date
25
26
  | negative_date
26
27
 
27
- positive_date : year { result = Date.new(val[0]) }
28
- | year_month { result = Date.new(*val.flatten) }
29
- | year_month_day { result = Date.new(*val.flatten) }
28
+ positive_date : year { result = Date.new(val[0]); result.precision = :year }
29
+ | year_month { result = Date.new(*val.flatten); result.precision = :month }
30
+ | year_month_day { result = Date.new(*val.flatten); result.precision = :day }
30
31
 
31
- negative_date : MINUS positive_date { result = Date.new(-1 * val[1].year, val[1].month, val[1].day) }
32
+ negative_date : MINUS positive_date { result = -val[1] }
32
33
 
33
34
 
34
35
  date_time : date T time { result = DateTime.new(val[0].year, val[0].month, val[0].day, *val[2]) }
@@ -90,15 +91,15 @@ rule
90
91
  | UNCERTAIN APPROXIMATE { result = [:uncertain!, :approximate!] }
91
92
 
92
93
 
93
- unspecified : unspecified_year
94
+ unspecified : unspecified_year { result = Date.new(val[0][0]); result.unspecified.year[2,2] = val[0][1]; result.precision = :year }
94
95
  | unspecified_month
95
96
  | unspecified_day
96
97
  | unspecified_day_and_month
97
98
 
98
- unspecified_year : digit digit digit UNSPECIFIED { result = Date.new(val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }); result.unspecified.year[3] = true }
99
- | digit digit UNSPECIFIED UNSPECIFIED { result = Date.new(val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }); result.unspecified.year[2,2] = [true, true] }
99
+ unspecified_year : digit digit digit UNSPECIFIED { result = [val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }, [false,true]] }
100
+ | digit digit UNSPECIFIED UNSPECIFIED { result = [val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }, [true, true]] }
100
101
 
101
- unspecified_month : year MINUS UNSPECIFIED UNSPECIFIED { result = Date.new(val[0]).unspecified!(:month) }
102
+ unspecified_month : year MINUS UNSPECIFIED UNSPECIFIED { result = Date.new(val[0]).unspecified!(:month); result.precision = :month }
102
103
 
103
104
  unspecified_day : year_month MINUS UNSPECIFIED UNSPECIFIED { result = Date.new(*val[0]).unspecified!(:day) }
104
105
 
@@ -115,14 +116,14 @@ rule
115
116
  | OPEN { result = :open }
116
117
 
117
118
 
118
- long_year_simple : LONGYEAR long_year { result = Date.new(val[1]) }
119
- | LONGYEAR MINUS long_year { result = Date.new(-1 * val[2]) }
119
+ long_year_simple : LONGYEAR long_year { result = Date.new(val[1]); result.precision = :year }
120
+ | LONGYEAR MINUS long_year { result = Date.new(-1 * val[2]); result.precision = :year }
120
121
 
121
122
  long_year : positive_digit digit digit digit digit { result = val.zip([10000,1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b } }
122
123
  | long_year digit { result = 10 * val[0] + val[1] }
123
124
 
124
125
 
125
- season : year MINUS season_number { result = Date.new(val[0]); result.season = val[2] }
126
+ season : year MINUS season_number { result = Date.new(val[0]); result.season = val[2]; result.precision = :year }
126
127
 
127
128
  season_number : D2 D1 { result = 21 }
128
129
  | D2 D2 { result = 22 }
@@ -134,9 +135,9 @@ rule
134
135
 
135
136
  level_2_expression : season_qualified
136
137
  # | internal_uncertain_or_approximate
137
- # | internal_unspecified
138
- # | choice_list
139
- # | inclusive_list
138
+ | internal_unspecified
139
+ | choice_list
140
+ | inclusive_list
140
141
  | masked_precision
141
142
  # | level_2_interval
142
143
  | date_and_calendar
@@ -146,9 +147,9 @@ rule
146
147
  season_qualified : season CARET { result = val[0]; result.qualifier = val[1] }
147
148
 
148
149
 
149
- long_year_scientific : long_year_simple E integer { result = Date.new(val[0].year * 10 ** val[2]) }
150
- | LONGYEAR int1_4 E integer { result = Date.new(val[1] * 10 ** val[3]) }
151
- | LONGYEAR MINUS int1_4 E integer { result = Date.new(-1 * val[2] * 10 ** val[4]) }
150
+ long_year_scientific : long_year_simple E integer { result = Date.new(val[0].year * 10 ** val[2]); result.precision = :year }
151
+ | LONGYEAR int1_4 E integer { result = Date.new(val[1] * 10 ** val[3]); result.precision = :year }
152
+ | LONGYEAR MINUS int1_4 E integer { result = Date.new(-1 * val[2] * 10 ** val[4]); result.precision = :year }
152
153
 
153
154
 
154
155
  date_and_calendar : date CARET { result = val[0]; result.calendar = val[1] }
@@ -157,6 +158,46 @@ rule
157
158
  masked_precision : digit digit digit X { d = val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }; result = Date.new(d) ... Date.new(d+10) }
158
159
  | digit digit X X { d = val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }; result = Date.new(d) ... Date.new(d+100) }
159
160
 
161
+
162
+ choice_list : LSQUARE list RSQUARE { result = val[1] }
163
+
164
+ inclusive_list : LBRACE list RBRACE { result = val[1] }
165
+
166
+ list : earlier { result = [val[0]] }
167
+ | earlier COMMA list_elements COMMA later { result = [val[0]] + val[2] + [val[4]] }
168
+ | earlier COMMA list_elements { result = [val[0]] + val[2] }
169
+ | earlier COMMA later { result = [val[0]] + [val[2]] }
170
+ | list_elements COMMA later { result = val[0] + [val[2]] }
171
+ | list_elements
172
+ | later { result = [val[0]] }
173
+
174
+ list_elements : list_element { result = [val[0]].flatten }
175
+ | list_elements COMMA list_element { result = val[0] + [val[2]].flatten }
176
+
177
+ list_element : date
178
+ # | date_with_internal_uncertainty
179
+ | uncertain_or_approximate_date
180
+ | unspecified
181
+ | consecutives { result = val[0].map { |d| Date.new(*d) } }
182
+
183
+ earlier : DOTS date { result = val[1] }
184
+
185
+ later : year_month_day DOTS { result = Date.new(*val[0]); result.precision = :day }
186
+ | year_month DOTS { result = Date.new(*val[0]); result.precision = :month }
187
+ | year DOTS { result = Date.new(val[0]); result.precision = :year }
188
+
189
+ consecutives : year_month_day DOTS year_month_day
190
+ | year_month DOTS year_month
191
+ | year DOTS year { result = (val[0]..val[2]).to_a.map }
192
+
193
+
194
+ internal_unspecified : unspecified_year MINUS month MINUS d01_31 { result = Date.new(val[0][0], val[2], val[4]); result.unspecified.year[2,2] = val[0][1] }
195
+ | unspecified_year MINUS UNSPECIFIED UNSPECIFIED MINUS d01_31 { result = Date.new(val[0][0], 1, val[5]); result.unspecified.year[2,2] = val[0][1]; result.unspecified!(:month) }
196
+ | unspecified_year MINUS UNSPECIFIED UNSPECIFIED MINUS UNSPECIFIED UNSPECIFIED { result = Date.new(val[0][0], 1, 1); result.unspecified.year[2,2] = val[0][1]; result.unspecified!([:month, :day]) }
197
+ | unspecified_year MINUS month MINUS UNSPECIFIED UNSPECIFIED { result = Date.new(val[0][0], val[2], 1); result.unspecified.year[2,2] = val[0][1]; result.unspecified!(:day) }
198
+ | year MINUS UNSPECIFIED UNSPECIFIED MINUS d01_31 { result = Date.new(val[0], 1, val[5]); result.unspecified!(:month) }
199
+
200
+
160
201
  # ---- Auxiliary Rules ----
161
202
 
162
203
  digit : D0 { result = 0 }
@@ -265,10 +306,20 @@ require 'strscan'
265
306
  def tokenize
266
307
  until @src.eos?
267
308
  case
309
+ # when @src.scan(/\s+/)
310
+ # ignore whitespace
268
311
  when @src.scan(/\(/)
269
312
  @stack << [:LP, @src.matched]
270
313
  when @src.scan(/\)/)
271
314
  @stack << [:RP, @src.matched]
315
+ when @src.scan(/\[/)
316
+ @stack << [:LSQUARE, @src.matched]
317
+ when @src.scan(/\]/)
318
+ @stack << [:RSQUARE, @src.matched]
319
+ when @src.scan(/\{/)
320
+ @stack << [:LBRACE, @src.matched]
321
+ when @src.scan(/\}/)
322
+ @stack << [:RBRACE, @src.matched]
272
323
  when @src.scan(/T/)
273
324
  @stack << [:T, @src.matched]
274
325
  when @src.scan(/Z/)
@@ -297,6 +348,10 @@ require 'strscan'
297
348
  @stack << [:COLON, @src.matched]
298
349
  when @src.scan(/\//)
299
350
  @stack << [:SLASH, @src.matched]
351
+ when @src.scan(/\s*\.\.\s*/)
352
+ @stack << [:DOTS, '..']
353
+ when @src.scan(/\s*,\s*/)
354
+ @stack << [:COMMA, ',']
300
355
  when @src.scan(/\^\w+/)
301
356
  @stack << [:CARET, @src.matched[1..-1]]
302
357
  when @src.scan(/\d/)
data/lib/edtf/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module EDTF
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '0.0.3'.freeze
3
3
  end
data/lib/edtf.rb CHANGED
@@ -39,6 +39,7 @@ require 'edtf/version'
39
39
  require 'edtf/uncertainty'
40
40
  require 'edtf/seasons'
41
41
  require 'edtf/date'
42
+ require 'edtf/date_time'
42
43
  require 'edtf/interval'
43
44
  require 'edtf/parser'
44
45
  require 'edtf/extensions'
@@ -0,0 +1,171 @@
1
+ module EDTF
2
+ describe Parser do
3
+ describe '#parse' do
4
+
5
+ it 'parses simple dates' do
6
+ Parser.new.parse('2001-02-03').to_s.should == '2001-02-03'
7
+ end
8
+
9
+ it 'parses negative years' do
10
+ Parser.new.parse('-2323').to_s.should == '-2323-01-01'
11
+ end
12
+
13
+ it 'parses year zero' do
14
+ Parser.new.parse('0000').to_s.should == '0000-01-01'
15
+ end
16
+
17
+ it 'parses date/time with time zones' do
18
+ Parser.new.parse('2011-08-15T11:19:00+01:00').to_s.should == '2011-08-15T11:19:00+01:00'
19
+ end
20
+
21
+ it 'parses simple intervals like "2007/2008"' do
22
+ Parser.new.parse('2007/2008').should include(Date.new(2007,12,24))
23
+ Parser.new.parse('2007/2008').should_not include(Date.new(2008,1,2))
24
+ end
25
+
26
+ it 'parses uncertain dates' do
27
+ Parser.new.parse('1984?').should be_uncertain
28
+ Parser.new.parse('1984').should be_certain
29
+ end
30
+
31
+ it 'parses approximate dates' do
32
+ Parser.new.parse('1984-01~').should be_approximate
33
+ Parser.new.parse('1984-01').should be_precise
34
+ end
35
+
36
+ it 'parses uncertain approximate dates' do
37
+ Parser.new.parse('1984?~').should be_uncertain
38
+ Parser.new.parse('1984?~').should be_approximate
39
+ end
40
+
41
+ it 'parses unspecified dates' do
42
+ Parser.new.parse('199u').should be_unspecified
43
+ Parser.new.parse('1999-uu-uu').should be_unspecified
44
+ end
45
+
46
+ it 'parses open intervals' do
47
+ Parser.new.parse('2004-01-01/open').should be_open
48
+ end
49
+
50
+ it 'parses unknown intervals' do
51
+ Parser.new.parse('2004-01-01/unknown').should be_unknown_end
52
+ Parser.new.parse('unknown/2004-01-01').should be_unknown_start
53
+ end
54
+
55
+ it 'parses intervals with uncertain or approximate dates' do
56
+ Parser.new.parse('1984-06-02?/2004-08-08~').from.should be_uncertain
57
+ Parser.new.parse('1984-06-02?/2004-08-08~').to.should be_approximate
58
+ end
59
+
60
+ it 'should parse positive long years' do
61
+ Parser.new.parse('y170000002').year.should == 170000002
62
+ end
63
+
64
+ it 'should parse negative long years' do
65
+ Parser.new.parse('y-170000002').year.should == -170000002
66
+ end
67
+
68
+ it 'should parse season codes' do
69
+ Parser.new.parse('2003-23').should be_autumn
70
+ end
71
+
72
+ it 'should parse calendar names' do
73
+ Parser.new.parse('2001-02-03^xyz').calendar.should == 'xyz'
74
+ end
75
+
76
+ it 'should parse season qualifiers' do
77
+ d = Parser.new.parse('2003-23^european')
78
+ d.should be_autumn
79
+ d.should be_qualified
80
+ d.qualifier.should == 'european'
81
+ end
82
+
83
+ it 'should parse positive scientific long years' do
84
+ Parser.new.parse('y17e7').year.should == 170000000
85
+ end
86
+
87
+ it 'should parse negative scientific long years' do
88
+ Parser.new.parse('y-17e7').year.should == -170000000
89
+ end
90
+
91
+ it 'parses masked precision date strings (decades)' do
92
+ d = Parser.new.parse('198x')
93
+ d.should include(Date.new(1983,3,12))
94
+ d.should_not include(Date.new(1990,1,1))
95
+ end
96
+
97
+ it 'parses masked precision date strings (centuries)' do
98
+ d = Parser.new.parse('18xx')
99
+ d.should include(Date.new(1848,1,14))
100
+ d.should_not include(Date.new(1799,12,31))
101
+ end
102
+
103
+ it 'parses multiple dates (years)' do
104
+ d = Parser.new.parse('{1667,1668, 1670..1672}')
105
+ d.map(&:year).should == [1667,1668,1670,1671,1672]
106
+ end
107
+
108
+ it 'parses multiple dates (mixed years and months)' do
109
+ d = Parser.new.parse('{1960, 1961-12}')
110
+ d.map { |x| [x.year,x.month] }.should == [[1960,1],[1961,12]]
111
+ end
112
+
113
+ it 'parses choice lists (One of the years 1667, 1668, 1670, 1671, 1672)' do
114
+ d = Parser.new.parse('[1667,1668, 1670..1672]')
115
+ d.map(&:year).should == [1667,1668,1670,1671,1672]
116
+ end
117
+
118
+ it 'parses choice lists (December 3, 1760 or some earlier date)' do
119
+ d = Parser.new.parse('[..1760-12-03]')
120
+ d.map(&:to_s).should == ['1760-12-03']
121
+ end
122
+
123
+ it 'parses choice lists (December 1760 or some later month)' do
124
+ d = Parser.new.parse('[1760-12..]')
125
+ d.map { |x| [x.year,x.month] }.should == [[1760,12]]
126
+ end
127
+
128
+ it 'parses choice lists (January or February of 1760 or December 1760 or some later month)' do
129
+ d = Parser.new.parse('[1760-01, 1760-02, 1760-12..]')
130
+ d.length.should == 3
131
+ end
132
+
133
+ it 'parses intern unspecified "199u-01-01"' do
134
+ Parser.new.parse('199u-01-01').unspecified.to_s.should == 'sssu-ss-ss'
135
+ end
136
+
137
+ it 'parses intern unspecified "19uu-01-01"' do
138
+ Parser.new.parse('19uu-01-01').unspecified.to_s.should == 'ssuu-ss-ss'
139
+ end
140
+
141
+ it 'parses intern unspecified "199u-uu-01"' do
142
+ Parser.new.parse('199u-uu-01').unspecified.to_s.should == 'sssu-uu-ss'
143
+ end
144
+
145
+ it 'parses intern unspecified "19uu-uu-01"' do
146
+ Parser.new.parse('19uu-uu-01').unspecified.to_s.should == 'ssuu-uu-ss'
147
+ end
148
+
149
+ it 'parses intern unspecified "199u-uu-uu"' do
150
+ Parser.new.parse('199u-uu-uu').unspecified.to_s.should == 'sssu-uu-uu'
151
+ end
152
+
153
+ it 'parses intern unspecified "19uu-uu-uu"' do
154
+ Parser.new.parse('19uu-uu-uu').unspecified.to_s.should == 'ssuu-uu-uu'
155
+ end
156
+
157
+ it 'parses intern unspecified "199u-01-uu"' do
158
+ Parser.new.parse('199u-01-uu').unspecified.to_s.should == 'sssu-ss-uu'
159
+ end
160
+
161
+ it 'parses intern unspecified "19uu-01-uu"' do
162
+ Parser.new.parse('19uu-01-uu').unspecified.to_s.should == 'ssuu-ss-uu'
163
+ end
164
+
165
+ it 'parses intern unspecified "1999-uu-01"' do
166
+ Parser.new.parse('1999-uu-01').unspecified.to_s.should == 'ssss-uu-ss'
167
+ end
168
+
169
+ end
170
+ end
171
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edtf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-08-15 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &2157415200 !ruby/object:Gem::Requirement
16
+ requirement: &2157012300 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0.9'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2157415200
24
+ version_requirements: *2157012300
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: racc
27
- requirement: &2157414020 !ruby/object:Gem::Requirement
27
+ requirement: &2156999280 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1.4'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2157414020
35
+ version_requirements: *2156999280
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: cucumber
38
- requirement: &2157413420 !ruby/object:Gem::Requirement
38
+ requirement: &2156998780 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '1.0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2157413420
46
+ version_requirements: *2156998780
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- requirement: &2157412820 !ruby/object:Gem::Requirement
49
+ requirement: &2156998280 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '2.6'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2157412820
57
+ version_requirements: *2156998280
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: ZenTest
60
- requirement: &2157412220 !ruby/object:Gem::Requirement
60
+ requirement: &2156997760 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '4.6'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2157412220
68
+ version_requirements: *2156997760
69
69
  description: An Extended Date/Time Format (EDTF) Parser for Ruby.
70
70
  email:
71
71
  - http://sylvester.keil.or.at
@@ -75,6 +75,7 @@ extra_rdoc_files:
75
75
  - README.md
76
76
  - LICENSE
77
77
  files:
78
+ - .autotest
78
79
  - .gitignore
79
80
  - .rspec
80
81
  - Gemfile
@@ -92,13 +93,14 @@ files:
92
93
  - lib/edtf.rb
93
94
  - lib/edtf/compatibility.rb
94
95
  - lib/edtf/date.rb
96
+ - lib/edtf/date_time.rb
95
97
  - lib/edtf/extensions.rb
96
98
  - lib/edtf/interval.rb
97
99
  - lib/edtf/parser.y
98
100
  - lib/edtf/seasons.rb
99
101
  - lib/edtf/uncertainty.rb
100
102
  - lib/edtf/version.rb
101
- - spec/edtf/extensions_spec.rb
103
+ - spec/edtf/parser_spec.rb
102
104
  - spec/edtf/seasons_spec.rb
103
105
  - spec/edtf/uncertainty_spec.rb
104
106
  - spec/spec_helper.rb
@@ -143,7 +145,7 @@ test_files:
143
145
  - features/parser/unspecified.feature
144
146
  - features/step_definitions/edtf_steps.rb
145
147
  - features/support/env.rb
146
- - spec/edtf/extensions_spec.rb
148
+ - spec/edtf/parser_spec.rb
147
149
  - spec/edtf/seasons_spec.rb
148
150
  - spec/edtf/uncertainty_spec.rb
149
151
  - spec/spec_helper.rb
@@ -1,44 +0,0 @@
1
- describe DateTime do
2
-
3
- let(:date) { DateTime.new }
4
-
5
- describe 'class methods' do
6
- it 'responds to edtf' do
7
- DateTime.respond_to?(:edtf).should == true
8
- end
9
- end
10
-
11
- describe 'instance methods' do
12
- [:uncertain?, :approximate?, :unspecified?, :uncertain, :approximate, :unspecified].each do |method|
13
- it "responds to #{method}" do
14
- DateTime.new.respond_to?(method).should == true
15
- end
16
- end
17
- end
18
-
19
- describe '#uncertain?' do
20
-
21
- it { should_not be_uncertain }
22
-
23
- [:year, :month, :day].each do |part|
24
- it "should not be uncertain by default (#{part})" do
25
- DateTime.new.uncertain?(part).should == false
26
- end
27
-
28
- it "should be uncertain if set to uncertain (#{part})" do
29
- date.uncertain.send("#{part}=", true)
30
- date.uncertain?(part).should == true
31
- end
32
-
33
- ([:year, :month, :day] - [part]).each do |other|
34
- it "#{other} should not be uncertain if #{part} is uncertain" do
35
- date.uncertain.send("#{part}=", true)
36
- date.uncertain?(other).should == false
37
- end
38
- end
39
-
40
- end
41
-
42
- end
43
-
44
- end