edtf 3.2.0 → 4.0.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.
data/lib/edtf/interval.rb CHANGED
@@ -37,7 +37,7 @@ module EDTF
37
37
 
38
38
  def from=(date)
39
39
  case date
40
- when Date, :unknown
40
+ when Date, :unknown, :open
41
41
  @from = date
42
42
  else
43
43
  throw ArgumentError.new("Intervals cannot start with: #{date}")
@@ -54,6 +54,15 @@ module EDTF
54
54
  end
55
55
 
56
56
  [:open, :unknown].each do |method_name|
57
+ define_method("#{method_name}_start!") do
58
+ @from = method_name
59
+ self
60
+ end
61
+
62
+ define_method("#{method_name}_start?") do
63
+ @from == method_name
64
+ end
65
+
57
66
  define_method("#{method_name}_end!") do
58
67
  @to = method_name
59
68
  self
@@ -64,16 +73,8 @@ module EDTF
64
73
  end
65
74
  end
66
75
 
67
- alias open! open_end!
68
- alias open? open_end?
69
-
70
- def unknown_start?
71
- from == :unknown
72
- end
73
-
74
- def unknown_start!
75
- @from = :unknown
76
- self
76
+ def open?
77
+ open_start? || open_end?
77
78
  end
78
79
 
79
80
  def unknown?
@@ -83,12 +84,12 @@ module EDTF
83
84
  # Returns the intervals precision. Mixed precisions are currently not
84
85
  # supported; in that case, the start date's precision takes precedence.
85
86
  def precision
86
- min.precision || max.precision
87
+ min&.precision || max&.precision
87
88
  end
88
89
 
89
90
  # Returns true if the precisions of start and end date are not the same.
90
91
  def mixed_precision?
91
- min.precision != max.precision
92
+ min&.precision != max&.precision
92
93
  end
93
94
 
94
95
  def each(&block)
@@ -165,16 +166,8 @@ module EDTF
165
166
 
166
167
  other = other.day_precision
167
168
 
168
- case
169
- when unknown_start?
170
- max.day_precision! == other
171
- when unknown_end?
172
- min.day_precision! == other
173
- when open_end?
174
- min.day_precision! <= other
175
- else
176
- min.day_precision! <= other && other <= max.day_precision!
177
- end
169
+ (unbounded_start? || min.day_precision! <= other) &&
170
+ (unbounded_end? || other <= max.day_precision!)
178
171
  end
179
172
 
180
173
  # call-seq:
@@ -216,7 +209,7 @@ module EDTF
216
209
  to_a.min(&block)
217
210
  else
218
211
  case
219
- when unknown_start?, !unknown_end? && !open? && to < from
212
+ when open_start?, unknown_start?, !(open_end? || unknown_end?) && !open? && to < from
220
213
  nil
221
214
  when from.day_precision?
222
215
  from
@@ -249,7 +242,7 @@ module EDTF
249
242
  to_a.max(&block)
250
243
  else
251
244
  case
252
- when open_end?, unknown_end?, !unknown_start? && to < from
245
+ when open_end?, unknown_end?, !(open_start? || unknown_start?) && to < from
253
246
  nil
254
247
  when to.day_precision?
255
248
  to
@@ -265,12 +258,20 @@ module EDTF
265
258
  max
266
259
  end
267
260
 
261
+ # Intervals are compared by their min and max dates. Open and unknown
262
+ # starts and ends are treated like -/+ infinity, with open being the
263
+ # more extreme of the two. Dates are equal to an interval if they are
264
+ # covered by it.
268
265
  def <=>(other)
269
266
  case other
270
267
  when Interval, Season, Epoch
271
- [min, max] <=> [other.min, other.max]
268
+ bounds <=> bounds_of(other)
272
269
  when Date
273
- cover?(other) ? min <=> other : 0
270
+ case
271
+ when cover?(other) then 0
272
+ when unbounded_start? then -1
273
+ else min.day_precision <=> other.day_precision
274
+ end
274
275
  else
275
276
  nil
276
277
  end
@@ -279,7 +280,8 @@ module EDTF
279
280
  def ===(other)
280
281
  case other
281
282
  when Interval
282
- cover?(other.min) && cover?(other.max)
283
+ (other.unbounded_start? ? unbounded_start? : cover?(other.min)) &&
284
+ (other.unbounded_end? ? unbounded_end? : cover?(other.max))
283
285
  when Date
284
286
  cover?(other)
285
287
  else
@@ -298,6 +300,32 @@ module EDTF
298
300
 
299
301
  alias to_s edtf
300
302
 
303
+ protected
304
+
305
+ def unbounded_start?
306
+ open_start? || unknown_start?
307
+ end
308
+
309
+ def unbounded_end?
310
+ open_end? || unknown_end?
311
+ end
312
+
313
+ START_RANK = { :open => -2, :unknown => -1 }.freeze
314
+ END_RANK = { :unknown => 1, :open => 2 }.freeze
315
+
316
+ def bounds
317
+ [
318
+ unbounded_start? ? START_RANK[from] : 0, min,
319
+ unbounded_end? ? END_RANK[to] : 0, max
320
+ ]
321
+ end
322
+
323
+ private
324
+
325
+ def bounds_of(other)
326
+ other.is_a?(Interval) ? other.bounds : [0, other.min, 0, other.max]
327
+ end
328
+
301
329
  end
302
330
 
303
331
  end