edtf 0.0.7 → 0.0.8

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.md CHANGED
@@ -8,13 +8,18 @@ Specification](http://www.loc.gov/standards/datetime/spec.html).
8
8
  Compatibility
9
9
  -------------
10
10
 
11
- EDTF-Ruby parser implements all levels and features of the EDTF Specification
11
+ EDTF-Ruby parser implements all levels and features of the EDTF specification
12
12
  (version September 16, 2011). With the following known caveats:
13
13
 
14
14
  * Uncertain/approximate seasons will be parsed, but the Season class does
15
15
  not implement attributes.
16
- * Some complex L2 partial uncertain/approximate date strings may currently
17
- fail to parse.
16
+ * In the latest revision of the EDTF specification alternative versions of
17
+ partial uncertain/approximate strings were introduced (with or without nested
18
+ parentheses); EDTF-Ruby currently uses the version that tries to reduce
19
+ parentheses for printing as we find that one easier to read; the
20
+ parser accepts all valid dates using this approach, plus some dates using
21
+ nested expressions (the parser will not accept some of the more complex
22
+ examples, though).
18
23
 
19
24
  The level 2 list extensions (203 and 204) currently return simple Ruby arrays;
20
25
  therefore, advanced behavior (such as 'earlier' or 'later') is parsed correctly
@@ -79,6 +84,8 @@ a Date, you can print the corresponding EDTF string using the `#edtf` method.
79
84
  => true
80
85
  > Date.edtf('2004/open').cover?(Date.today)
81
86
  => true # an open ended interval covers today
87
+ > Date.edtf("(1999-(02)~-23)?").edtf
88
+ => "1999?-(02)?~-23?" # when printing, EDTF-Ruby reduces nested parentheses
82
89
 
83
90
  For additional features take a look at the documentation or the extensive
84
91
  list of rspec examples.
@@ -0,0 +1,129 @@
1
+ Feature: Parse partial uncertain or approximate dates
2
+ As a Ruby programmer
3
+ I want to convert Date/Time objects to EDTF strings
4
+
5
+ @201 @level2
6
+ Scenario Outline: Prints uncertain or approximate dates
7
+ When I parse the string "<string>"
8
+ Then the year should be uncertain? "<?-year>"
9
+ And the month should be uncertain? "<?-month>"
10
+ And the day should be uncertain? "<?-day>"
11
+ And the year should be approximate? "<~-year>"
12
+ And the month should be approximate? "<~-month>"
13
+ And the day should be approximate? "<~-day>"
14
+
15
+ Scenarios: Uncertain or approximate dates, day precision
16
+ | date | precision | string | ?-year | ?-month | ?-day | ~-year | ~-month | ~-day |
17
+ | 2004-06-01 | day | 2004-06-01?~ | yes | yes | yes | yes | yes | yes |
18
+ | 2004-06-01 | day | 2004-06~-01? | yes | yes | yes | yes | yes | no |
19
+ | 2004-06-01 | day | (2004~-06-(01)~)? | yes | yes | yes | yes | no | yes |
20
+ | 2004-06-01 | day | 2004~-06?-(01)?~ | yes | yes | yes | yes | no | yes |
21
+ | 2004-06-01 | day | 2004~-06-01? | yes | yes | yes | yes | no | no |
22
+ | 2004-06-01 | day | (2004-(06-01)~)? | yes | yes | yes | no | yes | yes |
23
+ | 2004-06-01 | day | 2004?-(06-01)?~ | yes | yes | yes | no | yes | yes |
24
+ | 2004-06-01 | day | (2004-(06)~-01)? | yes | yes | yes | no | yes | no |
25
+ | 2004-06-01 | day | 2004?-(06)?~-01? | yes | yes | yes | no | yes | no |
26
+ | 2004-06-01 | day | (2004-06-(01)~)? | yes | yes | yes | no | no | yes |
27
+ | 2004-06-01 | day | 2004-06?-(01)?~ | yes | yes | yes | no | no | yes |
28
+ | 2004-06-01 | day | 2004-06-01? | yes | yes | yes | no | no | no |
29
+ | 2004-06-01 | day | 2004-06?-01~ | yes | yes | no | yes | yes | yes |
30
+ | 2004-06-01 | day | 2004-06?~-01 | yes | yes | no | yes | yes | no |
31
+ | 2004-06-01 | day | 2004~-06?-(01)~ | yes | yes | no | yes | no | yes |
32
+ | 2004-06-01 | day | 2004~-06?-01 | yes | yes | no | yes | no | no |
33
+ # | 2004-06-01 | day | 2004-(06?-01)~ | yes | yes | no | no | yes | yes | is this correct?
34
+ # | 2004-06-01 | day | 2004?-((06)?-01)~ | yes | yes | no | no | yes | yes |
35
+ | 2004-06-01 | day | 2004?-(06)?~-01~ | yes | yes | no | no | yes | yes |
36
+ # | 2004-06-01 | day | (2004-(06)~)?-01 | yes | yes | no | no | yes | no |
37
+ | 2004-06-01 | day | 2004?-(06)?~-01 | yes | yes | no | no | yes | no |
38
+ | 2004-06-01 | day | 2004-06?-(01)~ | yes | yes | no | no | no | yes |
39
+ | 2004-06-01 | day | 2004-06?-01 | yes | yes | no | no | no | no |
40
+ | 2004-06-01 | day | (2004?-06-(01)?)~ | yes | no | yes | yes | yes | yes |
41
+ | 2004-06-01 | day | 2004?-06~-(01)?~ | yes | no | yes | yes | yes | yes |
42
+ | 2004-06-01 | day | 2004?-06~-(01)? | yes | no | yes | yes | yes | no |
43
+ | 2004-06-01 | day | 2004?~-06-(01)?~ | yes | no | yes | yes | no | yes |
44
+ | 2004-06-01 | day | 2004?~-06-(01)? | yes | no | yes | yes | no | no |
45
+ | 2004-06-01 | day | 2004?-(06-(01)?)~ | yes | no | yes | no | yes | yes |
46
+ | 2004-06-01 | day | 2004?-(06)~-01?~ | yes | no | yes | no | yes | yes |
47
+ | 2004-06-01 | day | 2004?-(06)~-01? | yes | no | yes | no | yes | no |
48
+ | 2004-06-01 | day | 2004?-06-(01)?~ | yes | no | yes | no | no | yes |
49
+ | 2004-06-01 | day | 2004?-06-(01)? | yes | no | yes | no | no | no |
50
+ | 2004-06-01 | day | 2004?-06-01~ | yes | no | no | yes | yes | yes |
51
+ | 2004-06-01 | day | 2004?-06~-01 | yes | no | no | yes | yes | no |
52
+ | 2004-06-01 | day | 2004?~-06-(01)~ | yes | no | no | yes | no | yes |
53
+ | 2004-06-01 | day | 2004?~-06-01 | yes | no | no | yes | no | no |
54
+ | 2004-06-01 | day | 2004?-(06-01)~ | yes | no | no | no | yes | yes |
55
+ | 2004-06-01 | day | 2004?-(06)~-01 | yes | no | no | no | yes | no |
56
+ | 2004-06-01 | day | 2004?-06-(01)~ | yes | no | no | no | no | yes |
57
+ | 2004-06-01 | day | 2004?-06-01 | yes | no | no | no | no | no |
58
+ | 2004-06-01 | day | (2004-(06-01)?)~ | no | yes | yes | yes | yes | yes |
59
+ | 2004-06-01 | day | 2004~-(06-01)?~ | no | yes | yes | yes | yes | yes |
60
+ # | 2004-06-01 | day | 2004-(06~-01)? | no | yes | yes | yes | yes | no | is this correct?
61
+ # | 2004-06-01 | day | 2004~-((06)~-01)? | no | yes | yes | yes | yes | no |
62
+ | 2004-06-01 | day | 2004~-(06)?~-01? | no | yes | yes | yes | yes | no |
63
+ | 2004-06-01 | day | 2004~-(06-(01)~)? | no | yes | yes | yes | no | yes |
64
+ | 2004-06-01 | day | 2004~-(06)?-01?~ | no | yes | yes | yes | no | yes |
65
+ | 2004-06-01 | day | 2004~-(06-01)? | no | yes | yes | yes | no | no |
66
+ | 2004-06-01 | day | 2004-(06-01)?~ | no | yes | yes | no | yes | yes |
67
+ # | 2004-06-01 | day | 2004-((06)~-01)? | no | yes | yes | no | yes | no |
68
+ | 2004-06-01 | day | 2004-(06)?~-01? | no | yes | yes | no | yes | no |
69
+ | 2004-06-01 | day | 2004-(06-(01)~)? | no | yes | yes | no | no | yes |
70
+ | 2004-06-01 | day | 2004-(06)?-01?~ | no | yes | yes | no | no | yes |
71
+ | 2004-06-01 | day | 2004-(06-01)? | no | yes | yes | no | no | no |
72
+ | 2004-06-01 | day | (2004-(06)?-01)~ | no | yes | no | yes | yes | yes |
73
+ | 2004-06-01 | day | 2004~-(06)?~-01~ | no | yes | no | yes | yes | yes |
74
+ # | 2004-06-01 | day | (2004-(06)?)~-01 | no | yes | no | yes | yes | no |
75
+ | 2004-06-01 | day | 2004~-(06)?~-01 | no | yes | no | yes | yes | no |
76
+ | 2004-06-01 | day | 2004~-(06)?-01~ | no | yes | no | yes | no | yes |
77
+ | 2004-06-01 | day | 2004~-(06)?-01 | no | yes | no | yes | no | no |
78
+ # | 2004-06-01 | day | 2004-((06)?-01)~ | no | yes | no | no | yes | yes |
79
+ | 2004-06-01 | day | 2004-(06)?~-01~ | no | yes | no | no | yes | yes |
80
+ | 2004-06-01 | day | 2004-(06)?~-01 | no | yes | no | no | yes | no |
81
+ | 2004-06-01 | day | 2004-(06)?-01~ | no | yes | no | no | no | yes |
82
+ | 2004-06-01 | day | 2004-(06)?-01 | no | yes | no | no | no | no |
83
+ | 2004-06-01 | day | (2004-06-(01)?)~ | no | no | yes | yes | yes | yes |
84
+ | 2004-06-01 | day | 2004-06~-(01)?~ | no | no | yes | yes | yes | yes |
85
+ | 2004-06-01 | day | 2004-06~-(01)? | no | no | yes | yes | yes | no |
86
+ | 2004-06-01 | day | 2004~-06-(01)?~ | no | no | yes | yes | no | yes |
87
+ | 2004-06-01 | day | 2004~-06-(01)? | no | no | yes | yes | no | no |
88
+ | 2004-06-01 | day | 2004-(06-(01)?)~ | no | no | yes | no | yes | yes |
89
+ | 2004-06-01 | day | 2004-(06)~-01?~ | no | no | yes | no | yes | yes |
90
+ | 2004-06-01 | day | 2004-(06)~-01? | no | no | yes | no | yes | no |
91
+ | 2004-06-01 | day | 2004-06-(01)?~ | no | no | yes | no | no | yes |
92
+ | 2004-06-01 | day | 2004-06-(01)? | no | no | yes | no | no | no |
93
+ | 2004-06-01 | day | 2004-06-01~ | no | no | no | yes | yes | yes |
94
+ | 2004-06-01 | day | 2004-06~-01 | no | no | no | yes | yes | no |
95
+ | 2004-06-01 | day | 2004~-06-(01)~ | no | no | no | yes | no | yes |
96
+ | 2004-06-01 | day | 2004~-06-01 | no | no | no | yes | no | no |
97
+ | 2004-06-01 | day | 2004-(06-01)~ | no | no | no | no | yes | yes |
98
+ | 2004-06-01 | day | 2004-(06)~-01 | no | no | no | no | yes | no |
99
+ | 2004-06-01 | day | 2004-06-(01)~ | no | no | no | no | no | yes |
100
+ | 2004-06-01 | day | 2004-06-01 | no | no | no | no | no | no |
101
+
102
+ Scenarios: Uncertain or approximate dates, month precision
103
+ | date | precision | string | ?-year | ?-month | ?-day | ~-year | ~-month | ~-day |
104
+ | 2004-06-01 | month | 2004-06?~ | yes | yes | no | yes | yes | no |
105
+ | 2004-06-01 | month | 2004~-06? | yes | yes | no | yes | no | no |
106
+ | 2004-06-01 | month | (2004-(06)~)? | yes | yes | no | no | yes | no |
107
+ | 2004-06-01 | month | 2004?-(06)?~ | yes | yes | no | no | yes | no |
108
+ | 2004-06-01 | month | 2004-06? | yes | yes | no | no | no | no |
109
+ | 2004-06-01 | month | 2004?-06~ | yes | no | no | yes | yes | no |
110
+ | 2004-06-01 | month | 2004?~-06 | yes | no | no | yes | no | no |
111
+ | 2004-06-01 | month | 2004?-(06)~ | yes | no | no | no | yes | no |
112
+ | 2004-06-01 | month | 2004?-06 | yes | no | no | no | no | no |
113
+ | 2004-06-01 | month | (2004-(06)?)~ | no | yes | no | yes | yes | no |
114
+ | 2004-06-01 | month | 2004~-(06)?~ | no | yes | no | yes | yes | no |
115
+ | 2004-06-01 | month | 2004~-(06)? | no | yes | no | yes | no | no |
116
+ | 2004-06-01 | month | 2004-(06)?~ | no | yes | no | no | yes | no |
117
+ | 2004-06-01 | month | 2004-(06)? | no | yes | no | no | no | no |
118
+ | 2004-06-01 | month | 2004-06~ | no | no | no | yes | yes | no |
119
+ | 2004-06-01 | month | 2004~-06 | no | no | no | yes | no | no |
120
+ | 2004-06-01 | month | 2004-(06)~ | no | no | no | no | yes | no |
121
+ | 2004-06-01 | month | 2004-06 | no | no | no | no | no | no |
122
+
123
+
124
+ Scenarios: Uncertain or approximate dates, year precision
125
+ | date | precision | string | ?-year | ?-month | ?-day | ~-year | ~-month | ~-day |
126
+ | 2004-06-01 | year | 2004?~ | yes | no | no | yes | no | no |
127
+ | 2004-06-01 | year | 2004? | yes | no | no | no | no | no |
128
+ | 2004-06-01 | year | 2004~ | no | no | no | yes | no | no |
129
+ | 2004-06-01 | year | 2004 | no | no | no | no | no | no |
@@ -14,7 +14,6 @@ Feature: Print uncertain or approximate dates
14
14
  When I convert the date
15
15
  Then the EDTF string should be "<string>"
16
16
 
17
- @wip
18
17
  Scenarios: Uncertain or approximate dates, day precision
19
18
  | date | precision | string | ?-year | ?-month | ?-day | ~-year | ~-month | ~-day |
20
19
  | 2004-06-01 | day | 2004-06-01?~ | yes | yes | yes | yes | yes | yes |
@@ -102,7 +101,6 @@ Feature: Print uncertain or approximate dates
102
101
  | 2004-06-01 | day | 2004-06-(01)~ | no | no | no | no | no | yes |
103
102
  | 2004-06-01 | day | 2004-06-01 | no | no | no | no | no | no |
104
103
 
105
- @wip
106
104
  Scenarios: Uncertain or approximate dates, month precision
107
105
  | date | precision | string | ?-year | ?-month | ?-day | ~-year | ~-month | ~-day |
108
106
  | 2004-06-01 | month | 2004-06?~ | yes | yes | no | yes | yes | no |
@@ -125,7 +123,6 @@ Feature: Print uncertain or approximate dates
125
123
  | 2004-06-01 | month | 2004-06 | no | no | no | no | no | no |
126
124
 
127
125
 
128
- @wip
129
126
  Scenarios: Uncertain or approximate dates, year precision
130
127
  | date | precision | string | ?-year | ?-month | ?-day | ~-year | ~-month | ~-day |
131
128
  | 2004-06-01 | year | 2004?~ | yes | no | no | yes | no | no |
@@ -266,9 +266,10 @@ class Date
266
266
 
267
267
  # Returns true if this Date/Time has year precision and the year exceeds four digits.
268
268
  def long_year?
269
- precision == :year && year.abs > 9999
269
+ year_precision? && year.abs > 9999
270
270
  end
271
271
 
272
+
272
273
  private
273
274
 
274
275
  def ua_hash
@@ -2,7 +2,7 @@
2
2
 
3
3
  class EDTF::Parser
4
4
 
5
- token T Z E X U UNKNOWN OPEN LONGYEAR UNMATCHED DOTS PUA
5
+ token T Z E X U UNKNOWN OPEN LONGYEAR UNMATCHED DOTS UA PUA
6
6
 
7
7
  expect 0
8
8
 
@@ -25,9 +25,9 @@ rule
25
25
  ;
26
26
 
27
27
  positive_date :
28
- 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 }
28
+ year { result = Date.new(val[0]).year_precision! }
29
+ | year_month { result = Date.new(*val.flatten).month_precision! }
30
+ | year_month_day { result = Date.new(*val.flatten).day_precision! }
31
31
  ;
32
32
 
33
33
  negative_date : '-' positive_date { result = -val[1] }
@@ -65,6 +65,7 @@ rule
65
65
  }
66
66
 
67
67
  month : d01_12
68
+ day : d01_31
68
69
 
69
70
  year_month : year '-' month { result = [val[0], val[2]] }
70
71
 
@@ -72,7 +73,7 @@ rule
72
73
  # do not consider leap years, as the EDTF BNF did not either.
73
74
  # NB: an exception will be raised regardless, because the Ruby Date
74
75
  # implementation calculates leap years.
75
- year_month_day : year_month '-' d01_31 {
76
+ year_month_day : year_month '-' day {
76
77
  result = val[0] << val[2]
77
78
  if result[2] > 31 || (result[2] > 30 && [2,4,6,9,11].include?(result[1])) || (result[2] > 29 && result[1] == 2)
78
79
  raise ArgumentError, "invalid date (invalid days #{result[2]} for month #{result[1]})"
@@ -92,13 +93,12 @@ rule
92
93
  # NB: Uncertain/approximate Dates are covered by the Level 2 rules
93
94
  level_1_expression : unspecified | level_1_interval | long_year_simple | season
94
95
 
95
- # uncertain_or_approximate_date : date ua { result = uoa(val[0], val[1]) }
96
+ # uncertain_or_approximate_date : date UA { result = uoa(val[0], val[1]) }
96
97
 
97
98
  unspecified : unspecified_year
98
99
  {
99
- result = Date.new(val[0][0])
100
+ result = Date.new(val[0][0]).year_precision!
100
101
  result.unspecified.year[2,2] = val[0][1]
101
- result.precision = :year
102
102
  }
103
103
  | unspecified_month
104
104
  | unspecified_day
@@ -159,7 +159,8 @@ rule
159
159
  ;
160
160
 
161
161
 
162
- season : year '-' season_number opt_ua { result = Season.new(val[0], val[2]) }
162
+ # TODO uncertain/approximate seasons
163
+ season : year '-' season_number ua { result = Season.new(val[0], val[2]) }
163
164
 
164
165
  season_number : '2' '1' { result = 21 }
165
166
  | '2' '2' { result = 22 }
@@ -186,39 +187,36 @@ rule
186
187
 
187
188
 
188
189
  long_year_scientific :
189
- long_year_simple E integer
190
- {
191
- result = Date.new(val[0].year * 10 ** val[2])
192
- result.precision = :year
193
- }
194
- | LONGYEAR int1_4 E integer
195
- {
196
- result = Date.new(val[1] * 10 ** val[3])
197
- result.precision = :year
198
- }
190
+ long_year_simple E integer
191
+ {
192
+ result = Date.new(val[0].year * 10 ** val[2]).year_precision!
193
+ }
194
+ | LONGYEAR int1_4 E integer
195
+ {
196
+ result = Date.new(val[1] * 10 ** val[3]).year_precision!
197
+ }
199
198
  | LONGYEAR '-' int1_4 E integer
200
- {
201
- result = Date.new(-1 * val[2] * 10 ** val[4])
202
- result.precision = :year
203
- }
204
- ;
199
+ {
200
+ result = Date.new(-1 * val[2] * 10 ** val[4]).year_precision!
201
+ }
202
+ ;
205
203
 
206
204
 
207
205
  date_and_calendar : date '^' { result = val[0]; result.calendar = val[1] }
208
206
 
209
207
 
210
208
  masked_precision :
211
- digit digit digit X
212
- {
213
- d = val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }
214
- result = Date.new(d) ... Date.new(d+10)
215
- }
209
+ digit digit digit X
210
+ {
211
+ d = val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }
212
+ result = Date.new(d) ... Date.new(d+10)
213
+ }
216
214
  | digit digit X X
217
- {
218
- d = val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }
219
- result = Date.new(d) ... Date.new(d+100)
220
- }
221
- ;
215
+ {
216
+ d = val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }
217
+ result = Date.new(d) ... Date.new(d+100)
218
+ }
219
+ ;
222
220
 
223
221
 
224
222
  choice_list : '[' list ']' { result = val[1] }
@@ -232,37 +230,37 @@ rule
232
230
  | list_elements ',' later { result = val[0] + [val[2]] }
233
231
  | list_elements
234
232
  | later { result = val }
235
- ;
233
+ ;
236
234
 
237
235
  list_elements : list_element { result = [val[0]].flatten }
238
236
  | list_elements ',' list_element { result = val[0] + [val[2]].flatten }
239
- ;
237
+ ;
240
238
 
241
239
  list_element : date
242
240
  | partial_uncertain_or_approximate
243
241
  | unspecified
244
242
  | consecutives { result = val[0].map { |d| Date.new(*d) } }
245
- ;
243
+ ;
246
244
 
247
245
  earlier : DOTS date { result = val[1] }
248
246
 
249
- later : year_month_day DOTS { result = Date.new(*val[0]); result.precision = :day }
250
- | year_month DOTS { result = Date.new(*val[0]); result.precision = :month }
251
- | year DOTS { result = Date.new(val[0]); result.precision = :year }
252
- ;
247
+ later : year_month_day DOTS { result = Date.new(*val[0]).year_precision! }
248
+ | year_month DOTS { result = Date.new(*val[0]).month_precision! }
249
+ | year DOTS { result = Date.new(val[0]).year_precision! }
250
+ ;
253
251
 
254
252
  consecutives : year_month_day DOTS year_month_day
255
253
  | year_month DOTS year_month
256
254
  | year DOTS year { result = (val[0]..val[2]).to_a.map }
257
- ;
255
+ ;
258
256
 
259
257
  partial_unspecified :
260
- unspecified_year '-' month '-' d01_31
258
+ unspecified_year '-' month '-' day
261
259
  {
262
260
  result = Date.new(val[0][0], val[2], val[4])
263
261
  result.unspecified.year[2,2] = val[0][1]
264
262
  }
265
- | unspecified_year '-' U U '-' d01_31
263
+ | unspecified_year '-' U U '-' day
266
264
  {
267
265
  result = Date.new(val[0][0], 1, val[5])
268
266
  result.unspecified.year[2,2] = val[0][1]
@@ -280,7 +278,7 @@ rule
280
278
  result.unspecified.year[2,2] = val[0][1]
281
279
  result.unspecified!(:day)
282
280
  }
283
- | year '-' U U '-' d01_31
281
+ | year '-' U U '-' day
284
282
  {
285
283
  result = Date.new(val[0], 1, val[5])
286
284
  result.unspecified!(:month)
@@ -289,71 +287,71 @@ rule
289
287
 
290
288
 
291
289
  partial_uncertain_or_approximate : pua_base
292
- | '(' pua_base ')' ua { result = uoa(val[1], val[3]) }
290
+ | '(' pua_base ')' UA { result = uoa(val[1], val[3]) }
293
291
 
294
292
  pua_base :
295
- pua_year { result = val[0]; result.precision = :year }
296
- | pua_year_month { result = val[0]; result.precision = :month }
297
- | pua_year_month_day
293
+ pua_year { result = val[0].year_precision! }
294
+ | pua_year_month { result = val[0][0].month_precision! }
295
+ | pua_year_month_day { result = val[0].day_precision! }
298
296
 
299
- pua_year : year ua { result = uoa(Date.new(val[0]), val[1], :year) }
297
+ pua_year : year UA { result = uoa(Date.new(val[0]), val[1], :year) }
300
298
 
301
299
  pua_year_month :
302
- pua_year '-' month opt_ua
303
- {
304
- result = uoa(val[0].change(:month => val[2]), val[3], [:month, :year])
300
+ pua_year '-' month ua {
301
+ result = [uoa(val[0].change(:month => val[2]), val[3], [:month, :year])]
305
302
  }
306
- | '(' pua_year PUA month opt_ua
307
- {
308
- result = uoa(uoa(val[1], val[2], :year).change(:month => val[3]), val[4], :month)
303
+ | year '-' month UA {
304
+ result = [uoa(Date.new(val[0], val[2]), val[3], [:year, :month])]
309
305
  }
310
- | year '-' month ua
311
- {
312
- result = uoa(Date.new(val[0], val[2]), val[3], [:year, :month])
306
+ | year '-(' month ')' UA {
307
+ result = [uoa(Date.new(val[0], val[2]), val[4], [:month]), true]
313
308
  }
314
- | year '-' '(' month ')' ua
315
- {
316
- result = uoa(Date.new(val[0], val[3]), val[5], [:month])
309
+ | pua_year '-(' month ')' UA {
310
+ result = [uoa(val[0].change(:month => val[2]), val[4], [:month]), true]
317
311
  }
318
312
  ;
319
313
 
320
314
  pua_year_month_day :
321
- pua_year_month '-' d01_31 opt_ua
322
- {
323
- result = uoa(val[0].change(:day => val[2]), val[3])
315
+ pua_year_month '-' day ua {
316
+ result = uoa(val[0][0].change(:day => val[2]), val[3], val[0][1] ? [:day] : nil)
324
317
  }
325
- | pua_year_month '-' '(' d01_31 ')' ua
326
- {
327
- result = uoa(val[0].change(:day => val[3]), val[5], [:day])
318
+ | pua_year_month '-(' day ')' UA {
319
+ result = uoa(val[0][0].change(:day => val[2]), val[4], [:day])
328
320
  }
329
- | '(' pua_year_month PUA d01_31 opt_ua
330
- {
331
- result = uoa(uoa(val[1], val[2], [:year, :month]).change(:day => val[3]), val[4], :day)
321
+ | year '-(' month ')' UA day ua {
322
+ result = uoa(uoa(Date.new(val[0], val[2], val[5]), val[4], :month), val[6], :day)
332
323
  }
333
- | year '-' '(' month PUA d01_31 opt_ua
334
- {
335
- result = uoa(uoa(Date.new(val[0], val[3], val[5]), val[4], :month), val[6], :day)
324
+ | year_month '-' day UA {
325
+ result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[3])
336
326
  }
337
- | year_month '-' d01_31 ua
338
- {
339
- result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[3])
327
+ | year_month '-(' day ')' UA {
328
+ result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[4], [:day])
340
329
  }
341
- | year_month '-' '(' d01_31 ')' ua
342
- {
343
- result = uoa(Date.new(val[0][0], val[0][1], val[3]), val[5], [:day])
330
+ | year '-(' month '-' day ')' UA {
331
+ result = uoa(Date.new(val[0], val[2], val[4]), val[6], [:month, :day])
344
332
  }
345
- | year '-' '(' month '-' d01_31 ')' ua
346
- {
347
- result = uoa(Date.new(val[0], val[3], val[5]), val[7], [:month, :day])
333
+ | year '-(' month '-(' day ')' UA ')' UA {
334
+ result = Date.new(val[0], val[2], val[4])
335
+ result = uoa(result, val[6], [:day])
336
+ result = uoa(result, val[8], [:month, :day])
348
337
  }
338
+ | pua_year '-(' month '-' day ')' UA {
339
+ result = val[0].change(:month => val[2], :day => val[4])
340
+ result = uoa(result, val[6], [:month, :day])
341
+ }
342
+ | pua_year '-(' month '-(' day ')' UA ')' UA {
343
+ result = val[0].change(:month => val[2], :day => val[4])
344
+ result = uoa(result, val[6], [:day])
345
+ result = uoa(result, val[8], [:month, :day])
346
+ }
347
+ # | '(' pua_year '-(' month ')' UA ')' UA '-' day ua {
348
+ # result = val[1].change(:month => val[3], :day => val[9])
349
+ # result = uoa(result, val[5], [:month])
350
+ # result = [uoa(result, val[7], [:year]), true]
351
+ # }
349
352
  ;
350
353
 
351
- opt_ua : { result = [] } | ua
352
-
353
- ua : '?'
354
- | '~'
355
- | '?' '~' { result = val.flatten }
356
- ;
354
+ ua : { result = [] } | UA
357
355
 
358
356
  # ---- Auxiliary Rules ----
359
357
 
@@ -438,7 +436,7 @@ require 'strscan'
438
436
  @defaults = {
439
437
  :level => 2,
440
438
  :debug => false
441
- }
439
+ }.freeze
442
440
 
443
441
  class << self; attr_reader :defaults; end
444
442
 
@@ -448,22 +446,26 @@ require 'strscan'
448
446
  @options = Parser.defaults.merge(options)
449
447
  end
450
448
 
451
- def parse(input)
452
- parse!(input)
453
- rescue => e
454
- warn e.message if options[:debug]
455
- nil
456
- end
457
-
449
+ def debug?
450
+ !!(options[:debug] || ENV['DEBUG'])
451
+ end
452
+
453
+ def parse(input)
454
+ parse!(input)
455
+ rescue => e
456
+ warn e.message if debug?
457
+ nil
458
+ end
459
+
458
460
  def parse!(input)
459
- @yydebug = @options[:debug] || ENV['DEBUG']
461
+ @yydebug = debug?
460
462
  @src = StringScanner.new(input)
461
463
  do_parse
462
464
  end
463
465
 
464
- def on_error(tid, val, vstack)
466
+ def on_error(tid, value, stack)
465
467
  raise ArgumentError,
466
- "failed to parse extended date time %s [%s]: %s" % [val.inspect, token_to_str(tid) || '?', vstack.inspect]
468
+ "failed to parse date: unexpected '#{value}' at #{stack.inspect}"
467
469
  end
468
470
 
469
471
  def apply_uncertainty(date, uncertainty, scope = nil)
@@ -483,12 +485,12 @@ require 'strscan'
483
485
  # ignore whitespace
484
486
  when @src.scan(/\(/)
485
487
  ['(', @src.matched]
486
- when @src.scan(/\)\?~-/)
487
- [:PUA, [:uncertain!, :approximate!]]
488
- when @src.scan(/\)\?-/)
489
- [:PUA, [:uncertain!]]
490
- when @src.scan(/\)~-/)
491
- [:PUA, [:approximate!]]
488
+ # when @src.scan(/\)\?~-/)
489
+ # [:PUA, [:uncertain!, :approximate!]]
490
+ # when @src.scan(/\)\?-/)
491
+ # [:PUA, [:uncertain!]]
492
+ # when @src.scan(/\)~-/)
493
+ # [:PUA, [:approximate!]]
492
494
  when @src.scan(/\)/)
493
495
  [')', @src.matched]
494
496
  when @src.scan(/\[/)
@@ -503,10 +505,12 @@ require 'strscan'
503
505
  [:T, @src.matched]
504
506
  when @src.scan(/Z/)
505
507
  [:Z, @src.matched]
508
+ when @src.scan(/\?~/)
509
+ [:UA, [:uncertain!, :approximate!]]
506
510
  when @src.scan(/\?/)
507
- ['?', [:uncertain!]]
511
+ [:UA, [:uncertain!]]
508
512
  when @src.scan(/~/)
509
- ['~', [:approximate!]]
513
+ [:UA, [:approximate!]]
510
514
  when @src.scan(/open/i)
511
515
  [:OPEN, :open]
512
516
  when @src.scan(/unkn?own/i) # matches 'unkown' typo too
@@ -521,6 +525,8 @@ require 'strscan'
521
525
  [:E, @src.matched]
522
526
  when @src.scan(/\+/)
523
527
  ['+', @src.matched]
528
+ when @src.scan(/-\(/)
529
+ ['-(', @src.matched]
524
530
  when @src.scan(/-/)
525
531
  ['-', @src.matched]
526
532
  when @src.scan(/:/)
@@ -1,3 +1,3 @@
1
1
  module EDTF
2
- VERSION = '0.0.7'.freeze
2
+ VERSION = '0.0.8'.freeze
3
3
  end
@@ -270,14 +270,69 @@ module EDTF
270
270
 
271
271
  it 'parses "2004~-(06)?-01~": year and day approximate, month uncertain' do
272
272
  d = Parser.new.parse!("2004~-(06)?-01~")
273
+
274
+ d.approximate?(:year).should be true
275
+ d.uncertain?(:year).should be false
276
+
277
+ d.approximate?(:month).should be false
278
+ d.uncertain?(:month).should be true
279
+
280
+ d.approximate?(:day).should be true
281
+ d.uncertain?(:day).should be false
273
282
  end
274
283
 
275
284
  it 'parses "2004~-(06-(01)~)?": year and day approximate, month and day uncertain' do
276
285
  d = Parser.new.parse!("2004~-(06-(01)~)?")
286
+
287
+ d.approximate?(:year).should be true
288
+ d.uncertain?(:year).should be false
289
+
290
+ d.approximate?(:month).should be false
291
+ d.uncertain?(:month).should be true
292
+
293
+ d.approximate?(:day).should be true
294
+ d.uncertain?(:day).should be true
277
295
  end
278
296
 
279
297
  it 'parses "2004~-(06)?-01?~": year and day approximate, month and day uncertain' do
280
298
  d = Parser.new.parse!("2004~-(06)?-01?~")
299
+
300
+ d.approximate?(:year).should be true
301
+ d.uncertain?(:year).should be false
302
+
303
+ d.approximate?(:month).should be false
304
+ d.uncertain?(:month).should be true
305
+
306
+ d.approximate?(:day).should be true
307
+ d.uncertain?(:day).should be true
308
+ end
309
+
310
+ it 'parses "2004~-(06)?": year approximate, month uncertain' do
311
+ d = Parser.new.parse!("2004~-(06)?")
312
+
313
+ d.approximate?(:year).should be true
314
+ d.uncertain?(:year).should be false
315
+
316
+ d.approximate?(:month).should be false
317
+ d.uncertain?(:month).should be true
318
+
319
+ d.approximate?(:day).should be false
320
+ d.uncertain?(:day).should be false
321
+ end
322
+
323
+
324
+ it 'parses "2004~-06?": year approximate, year and month uncertain' do
325
+ d = Parser.new.parse!("2004~-06?")
326
+
327
+ d.approximate?(:year).should be true
328
+ d.uncertain?(:year).should be true
329
+
330
+ d.approximate?(:month).should be false
331
+ d.uncertain?(:month).should be true
332
+
333
+ d.approximate?(:day).should be false
334
+ d.uncertain?(:day).should be false
335
+
281
336
  end
282
337
 
283
338
 
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.7
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-08 00:00:00.000000000 Z
12
+ date: 2011-11-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70251987936260 !ruby/object:Gem::Requirement
16
+ requirement: &70235877316060 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70251987936260
24
+ version_requirements: *70235877316060
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70251987935560 !ruby/object:Gem::Requirement
27
+ requirement: &70235877525400 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0.9'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70251987935560
35
+ version_requirements: *70235877525400
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: racc
38
- requirement: &70251987934800 !ruby/object:Gem::Requirement
38
+ requirement: &70235877523860 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '1.4'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70251987934800
46
+ version_requirements: *70235877523860
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: cucumber
49
- requirement: &70251987933480 !ruby/object:Gem::Requirement
49
+ requirement: &70235877522840 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '1.0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70251987933480
57
+ version_requirements: *70235877522840
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
- requirement: &70251987932500 !ruby/object:Gem::Requirement
60
+ requirement: &70235877521760 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '2.6'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70251987932500
68
+ version_requirements: *70235877521760
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: ZenTest
71
- requirement: &70251987931320 !ruby/object:Gem::Requirement
71
+ requirement: &70235877521200 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '4.6'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70251987931320
79
+ version_requirements: *70235877521200
80
80
  description: A Ruby implementation of the Extended Date/Time Format (EDTF).
81
81
  email:
82
82
  - http://sylvester.keil.or.at
@@ -98,6 +98,7 @@ files:
98
98
  - features/parser/dates.feature
99
99
  - features/parser/intervals.feature
100
100
  - features/parser/precision.feature
101
+ - features/parser/uncertain_or_approximate.feature
101
102
  - features/parser/unspecified.feature
102
103
  - features/print/level_0_edtf.feature
103
104
  - features/print/level_1_edtf.feature
@@ -144,12 +145,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
145
  - - ! '>='
145
146
  - !ruby/object:Gem::Version
146
147
  version: '0'
148
+ segments:
149
+ - 0
150
+ hash: -533372685399765203
147
151
  required_rubygems_version: !ruby/object:Gem::Requirement
148
152
  none: false
149
153
  requirements:
150
154
  - - ! '>='
151
155
  - !ruby/object:Gem::Version
152
156
  version: '0'
157
+ segments:
158
+ - 0
159
+ hash: -533372685399765203
153
160
  requirements: []
154
161
  rubyforge_project:
155
162
  rubygems_version: 1.8.10
@@ -161,6 +168,7 @@ test_files:
161
168
  - features/parser/dates.feature
162
169
  - features/parser/intervals.feature
163
170
  - features/parser/precision.feature
171
+ - features/parser/uncertain_or_approximate.feature
164
172
  - features/parser/unspecified.feature
165
173
  - features/print/level_0_edtf.feature
166
174
  - features/print/level_1_edtf.feature