edtf 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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