class EDTF::Interval
An interval behaves like a regular Range
but is dedicated to EDTF
dates. Most importantly, intervals use the date’s precision when generating the set of contained values and for membership tests. All tests are implemented without iteration and should therefore be considerably faster than if you were to use a regular Range
.
For example, the interval “2003/2006” covers the years 2003, 2004, 2005 and 2006. Converting the interval to an array would result in a an array containing exactly four dates with year precision. This is also reflected in membership tests.
Date.edtf('2003/2006').length -> 4 Date.edtf('2003/2006').include? Date.edtf('2004') -> true Date.edtf('2003/2006').include? Date.edtf('2004-03') -> false Date.edtf('2003/2006').cover? Date.edtf('2004-03') -> true
Attributes
Public Class Methods
# File lib/edtf/interval.rb 34 def initialize(from = Date.today, to = :open) 35 self.from, self.to = from, to 36 end
Public Instance Methods
# File lib/edtf/interval.rb 268 def <=>(other) 269 case other 270 when Interval, Season, Epoch 271 [min, max] <=> [other.min, other.max] 272 when Date 273 cover?(other) ? min <=> other : 0 274 else 275 nil 276 end 277 end
# File lib/edtf/interval.rb 279 def ===(other) 280 case other 281 when Interval 282 cover?(other.min) && cover?(other.max) 283 when Date 284 cover?(other) 285 else 286 false 287 end 288 end
# File lib/edtf/interval.rb 231 def begin 232 min 233 end
Returns true if other is an element of the Interval
, false otherwise. In contrast to include?
and member?
this method does not take into account the date’s precision.
# File lib/edtf/interval.rb 163 def cover?(other) 164 return false unless other.is_a?(Date) 165 166 other = other.day_precision 167 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 178 end
# File lib/edtf/interval.rb 94 def each(&block) 95 step(1, &block) 96 end
Returns the Interval
as an EDTF
string.
# File lib/edtf/interval.rb 292 def edtf 293 [ 294 from.send(from.respond_to?(:edtf) ? :edtf : :to_s), 295 to.send(to.respond_to?(:edtf) ? :edtf : :to_s) 296 ] * '/' 297 end
# File lib/edtf/interval.rb 264 def end 265 max 266 end
Returns the first date in the interval, or the first n dates.
# File lib/edtf/interval.rb 185 def first(n = 1) 186 if n > 1 187 (ds = Array(min)).empty? ? ds : ds.concat(ds[0].next(n - 1)) 188 else 189 min 190 end 191 end
# File lib/edtf/interval.rb 38 def from=(date) 39 case date 40 when Date, :unknown 41 @from = date 42 else 43 throw ArgumentError.new("Intervals cannot start with: #{date}") 44 end 45 end
Returns true if other is an element of the Interval
, false otherwise. Comparision is done according to the Interval’s min/max date and precision.
# File lib/edtf/interval.rb 155 def include?(other) 156 cover?(other) && precision == other.precision 157 end
Returns the last date in the interval, or the last n dates.
# File lib/edtf/interval.rb 198 def last(n = 1) 199 if n > 1 200 (ds = Array(max)).empty? ? ds : ds.concat(ds[0].prev(n - 1)) 201 else 202 max 203 end 204 end
Returns the maximum value in the interval. If a block is given, it is used to compare values (slower). Returns nil if the first date of the interval is larger than the last or if the interval has an unknown or open end.
To calculate the dates, precision is taken into account. Thus, the max Date
of “2007/2008” would be 2008-12-31, whilst the max Date
of “2007-12/2008-10” would be 2009-10-31.
# File lib/edtf/interval.rb 247 def max(&block) 248 if block_given? 249 to_a.max(&block) 250 else 251 case 252 when open_end?, unknown_end?, !unknown_start? && to < from 253 nil 254 when to.day_precision? 255 to 256 when to.month_precision? 257 to.end_of_month 258 else 259 to.end_of_year 260 end 261 end 262 end
Returns the minimum value in the interval. If a block is given, it is used to compare values (slower). Returns nil if the first date of the interval is larger than the last or if the interval has an unknown or open start.
# File lib/edtf/interval.rb 214 def min(&block) 215 if block_given? 216 to_a.min(&block) 217 else 218 case 219 when unknown_start?, !unknown_end? && !open? && to < from 220 nil 221 when from.day_precision? 222 from 223 when from.month_precision? 224 from.beginning_of_month 225 else 226 from.beginning_of_year 227 end 228 end 229 end
Returns true if the precisions of start and end date are not the same.
# File lib/edtf/interval.rb 90 def mixed_precision? 91 min.precision != max.precision 92 end
Returns the intervals precision. Mixed precisions are currently not supported; in that case, the start date’s precision takes precedence.
# File lib/edtf/interval.rb 85 def precision 86 min.precision || max.precision 87 end
Iterates over the interval by passing by elements at each step and yielding each date to the passed-in block. Note that the semantics of by are precision dependent: e.g., a value of 2 can mean 2 days, 2 months, or 2 years.
If not block is given, returns an enumerator instead.
# File lib/edtf/interval.rb 110 def step(by = 1) 111 raise ArgumentError unless by.respond_to?(:to_i) 112 113 if block_given? 114 f, t, by = min, max, by.to_i 115 116 unless f.nil? || t.nil? || by < 1 117 by = { Date::PRECISIONS[precision] => by } 118 119 until f > t do 120 yield f 121 f = f.advance(by) 122 end 123 end 124 125 self 126 else 127 enum_for(:step, by) 128 end 129 end
# File lib/edtf/interval.rb 47 def to=(date) 48 case date 49 when Date, :unknown, :open 50 @to = date 51 else 52 throw ArgumentError.new("Intervals cannot end with: #{date}") 53 end 54 end
# File lib/edtf/interval.rb 79 def unknown? 80 unknown_start? || unknown_end? 81 end
# File lib/edtf/interval.rb 74 def unknown_start! 75 @from = :unknown 76 self 77 end
# File lib/edtf/interval.rb 70 def unknown_start? 71 from == :unknown 72 end