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 ⇒ Object
call-seq: interval.max -> Date or nil interval.max { |a,b| block } -> Date or nil.
-
#min ⇒ 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.
-
#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
- #unknown_start! ⇒ Object
- #unknown_start? ⇒ 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
250 251 252 253 254 255 256 257 258 259 |
# File 'lib/edtf/interval.rb', line 250 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
261 262 263 264 265 266 267 268 269 270 |
# File 'lib/edtf/interval.rb', line 261 def ===(other) case other when Interval cover?(other.min) && cover?(other.max) when Date cover?(other) else false end end |
#begin ⇒ Object
213 214 215 |
# File 'lib/edtf/interval.rb', line 213 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.
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/edtf/interval.rb', line 145 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_end? min.day_precision! <= other else min.day_precision! <= other && other <= max.day_precision! end end |
#each(&block) ⇒ Object
76 77 78 |
# File 'lib/edtf/interval.rb', line 76 def each(&block) step(1, &block) end |
#edtf ⇒ Object Also known as: to_s
Returns the Interval as an EDTF string.
274 275 276 277 278 279 |
# File 'lib/edtf/interval.rb', line 274 def edtf [ from.send(from.respond_to?(:edtf) ? :edtf : :to_s), to.send(to.respond_to?(:edtf) ? :edtf : :to_s) ] * '/' end |
#end ⇒ Object
246 247 248 |
# File 'lib/edtf/interval.rb', line 246 def end max end |
#exclude_end? ⇒ Boolean
This method always returns false for Range compatibility. EDTF intervals always include the last date.
116 117 118 |
# File 'lib/edtf/interval.rb', line 116 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.
167 168 169 170 171 172 173 |
# File 'lib/edtf/interval.rb', line 167 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.
137 138 139 |
# File 'lib/edtf/interval.rb', line 137 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.
180 181 182 183 184 185 186 |
# File 'lib/edtf/interval.rb', line 180 def last(n = 1) if n > 1 (ds = Array(max)).empty? ? ds : ds.concat(ds[0].prev(n - 1)) else max end end |
#max ⇒ 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.
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/edtf/interval.rb', line 229 def max if block_given? to_a.max(&Proc.new) else case when open_end?, unknown_end?, !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 ⇒ 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.
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/edtf/interval.rb', line 196 def min if block_given? to_a.min(&Proc.new) else case when unknown_start?, !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.
72 73 74 |
# File 'lib/edtf/interval.rb', line 72 def mixed_precision? min.precsion != max.precision end |
#precision ⇒ Object
Returns the intervals precision. Mixed precisions are currently not supported; in that case, the start date’s precision takes precedence.
67 68 69 |
# File 'lib/edtf/interval.rb', line 67 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.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/edtf/interval.rb', line 92 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.
125 126 127 128 129 130 131 132 |
# File 'lib/edtf/interval.rb', line 125 def to_range case when open?, unknown? nil else Range.new(unknown_start? ? Date.new : @from, max) end end |
#unknown? ⇒ Boolean
61 62 63 |
# File 'lib/edtf/interval.rb', line 61 def unknown? unknown_start? || unknown_end? end |
#unknown_start! ⇒ Object
56 57 58 59 |
# File 'lib/edtf/interval.rb', line 56 def unknown_start! @from = :unknown self end |
#unknown_start? ⇒ Boolean
52 53 54 |
# File 'lib/edtf/interval.rb', line 52 def unknown_start? from == :unknown end |