Class: EDTF::Interval
- Inherits:
-
Object
- Object
- EDTF::Interval
- Extended by:
- Forwardable
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/edtf/interval.rb
Overview
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
Instance Attribute Summary collapse
-
#from ⇒ Object
Returns the value of attribute from.
-
#to ⇒ Object
Returns the value of attribute to.
Instance Method Summary collapse
- #<=>(other) ⇒ Object
- #===(other) ⇒ Object
- #begin ⇒ Object
-
#cover?(other) ⇒ Boolean
Returns true if other is an element of the Interval, false otherwise.
- #each(&block) ⇒ Object
-
#edtf ⇒ Object
(also: #to_s)
Returns the Interval as an EDTF string.
- #end ⇒ Object
-
#exclude_end? ⇒ Boolean
This method always returns false for Range compatibility.
-
#first(n = 1) ⇒ Object
call-seq: interval.first -> Date or nil interval.first(n) -> Array.
-
#include?(other) ⇒ Boolean
(also: #member?)
Returns true if other is an element of the Interval, false otherwise.
-
#initialize(from = Date.today, to = :open) ⇒ Interval
constructor
A new instance of Interval.
-
#last(n = 1) ⇒ Object
call-seq: interval.last -> Date or nil interval.last(n) -> Array.
-
#max(&block) ⇒ Object
call-seq: interval.max -> Date or nil interval.max { |a,b| block } -> Date or nil.
-
#min(&block) ⇒ Object
call-seq: interval.min -> Date or nil interval.min { |a,b| block } -> Date or nil.
-
#mixed_precision? ⇒ Boolean
Returns true if the precisions of start and end date are not the same.
- #open? ⇒ Boolean
-
#precision ⇒ Object
Returns the intervals precision.
-
#step(by = 1) ⇒ Object
call-seq: interval.step(by=1) { |date| block } -> self interval.step(by=1) -> Enumerator.
-
#to_range ⇒ Object
Returns the Interval as a Range.
- #unknown? ⇒ Boolean
Constructor Details
Instance Attribute Details
#from ⇒ Object
Returns the value of attribute from.
32 33 34 |
# File 'lib/edtf/interval.rb', line 32 def from @from end |
#to ⇒ Object
Returns the value of attribute to.
32 33 34 |
# File 'lib/edtf/interval.rb', line 32 def to @to end |
Instance Method Details
#<=>(other) ⇒ Object
271 272 273 274 275 276 277 278 279 280 |
# File 'lib/edtf/interval.rb', line 271 def <=>(other) case other when Interval, Season, Epoch [min, max] <=> [other.min, other.max] when Date cover?(other) ? min <=> other : 0 else nil end end |
#===(other) ⇒ Object
282 283 284 285 286 287 288 289 290 291 |
# File 'lib/edtf/interval.rb', line 282 def ===(other) case other when Interval cover?(other.min) && cover?(other.max) when Date cover?(other) else false end end |
#begin ⇒ Object
234 235 236 |
# File 'lib/edtf/interval.rb', line 234 def begin min end |
#cover?(other) ⇒ Boolean
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.
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/edtf/interval.rb', line 164 def cover?(other) return false unless other.is_a?(Date) other = other.day_precision case when unknown_start? max.day_precision! == other when unknown_end? min.day_precision! == other when open_start? max.day_precision! >= other when open_end? min.day_precision! <= other else min.day_precision! <= other && other <= max.day_precision! end end |
#each(&block) ⇒ Object
95 96 97 |
# File 'lib/edtf/interval.rb', line 95 def each(&block) step(1, &block) end |
#edtf ⇒ Object Also known as: to_s
Returns the Interval as an EDTF string.
295 296 297 298 299 300 |
# File 'lib/edtf/interval.rb', line 295 def edtf [ from.send(from.respond_to?(:edtf) ? :edtf : :to_s), to.send(to.respond_to?(:edtf) ? :edtf : :to_s) ] * '/' end |
#end ⇒ Object
267 268 269 |
# File 'lib/edtf/interval.rb', line 267 def end max end |
#exclude_end? ⇒ Boolean
This method always returns false for Range compatibility. EDTF intervals always include the last date.
135 136 137 |
# File 'lib/edtf/interval.rb', line 135 def exclude_end? false end |
#first(n = 1) ⇒ Object
call-seq:
interval.first -> Date or nil
interval.first(n) -> Array
Returns the first date in the interval, or the first n dates.
188 189 190 191 192 193 194 |
# File 'lib/edtf/interval.rb', line 188 def first(n = 1) if n > 1 (ds = Array(min)).empty? ? ds : ds.concat(ds[0].next(n - 1)) else min end end |
#include?(other) ⇒ Boolean Also known as: member?
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.
156 157 158 |
# File 'lib/edtf/interval.rb', line 156 def include?(other) cover?(other) && precision == other.precision end |
#last(n = 1) ⇒ Object
call-seq:
interval.last -> Date or nil
interval.last(n) -> Array
Returns the last date in the interval, or the last n dates.
201 202 203 204 205 206 207 |
# File 'lib/edtf/interval.rb', line 201 def last(n = 1) if n > 1 (ds = Array(max)).empty? ? ds : ds.concat(ds[0].prev(n - 1)) else max end end |
#max(&block) ⇒ Object
call-seq:
interval.max -> Date or nil
interval.max { |a,b| block } -> Date or nil
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.
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/edtf/interval.rb', line 250 def max(&block) if block_given? to_a.max(&block) else case when open_end?, unknown_end?, !(open_start? || unknown_start?) && to < from nil when to.day_precision? to when to.month_precision? to.end_of_month else to.end_of_year end end end |
#min(&block) ⇒ Object
call-seq:
interval.min -> Date or nil
interval.min { |a,b| block } -> Date or nil
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.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/edtf/interval.rb', line 217 def min(&block) if block_given? to_a.min(&block) else case when open_start?, unknown_start?, !(open_end? || unknown_end?) && !open? && to < from nil when from.day_precision? from when from.month_precision? from.beginning_of_month else from.beginning_of_year end end end |
#mixed_precision? ⇒ Boolean
Returns true if the precisions of start and end date are not the same.
91 92 93 |
# File 'lib/edtf/interval.rb', line 91 def mixed_precision? min&.precision != max&.precision end |
#open? ⇒ Boolean
76 77 78 |
# File 'lib/edtf/interval.rb', line 76 def open? open_start? || open_end? end |
#precision ⇒ Object
Returns the intervals precision. Mixed precisions are currently not supported; in that case, the start date’s precision takes precedence.
86 87 88 |
# File 'lib/edtf/interval.rb', line 86 def precision min&.precision || max&.precision end |
#step(by = 1) ⇒ Object
call-seq:
interval.step(by=1) { |date| block } -> self
interval.step(by=1) -> Enumerator
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.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/edtf/interval.rb', line 111 def step(by = 1) raise ArgumentError unless by.respond_to?(:to_i) if block_given? f, t, by = min, max, by.to_i unless f.nil? || t.nil? || by < 1 by = { Date::PRECISIONS[precision] => by } until f > t do yield f f = f.advance(by) end end self else enum_for(:step, by) end end |
#to_range ⇒ Object
Returns the Interval as a Range.
144 145 146 147 148 149 150 151 |
# File 'lib/edtf/interval.rb', line 144 def to_range case when open?, unknown? nil else Range.new(unknown_start? ? Date.new : @from, max) end end |
#unknown? ⇒ Boolean
80 81 82 |
# File 'lib/edtf/interval.rb', line 80 def unknown? unknown_start? || unknown_end? end |