Class: Tempr::DateTimeRange::SubRangeIterator
- Inherits:
-
Object
- Object
- Tempr::DateTimeRange::SubRangeIterator
- Includes:
- Enumerable, Tempr::DateTimeRange
- Defined in:
- lib/tempr/date_time_range.rb
Overview
Iterators are defined by
-
‘range`: base range (required)
-
‘step`: repetition length (default = 1)
-
‘adjust_range`: proc that adjusts base range before iteration (optional)
-
‘offset`: proc that adjusts start of adjusted range prior to iteration (optional)
-
‘increment`: proc that defines scale of each step (required)
-
‘span`: proc that defines duration of each returned subrange (required)
-
‘except`: proc(s) that don’t yield subrange if true of current step date (but don’t stop iteration)
-
‘limit`: stop iteration after self.limit steps (yields)
TODO:
-
‘until`: proc that stops iteration if true of current step date
Note that SubRangeIterator is coupled to DateTimeRange since it itself includes DateTimeRange (for chaining); However, otherwise it could be used just as well on other (e.g. numeric) ranges
Instance Attribute Summary collapse
-
#limit ⇒ Object
Returns the value of attribute limit.
-
#range ⇒ Object
Returns the value of attribute range.
-
#step ⇒ Object
Returns the value of attribute step.
Instance Method Summary collapse
- #adjust_range(&p) ⇒ Object
-
#by_step(n) ⇒ Object
‘stateless’ step enumerator simply generates infinite integer sequence if ruby already has such a facility built-in, let me know.
- #cover?(dt) ⇒ Boolean
-
#each(&b) ⇒ Object
Recursive madness…
-
#each_by_step(rng = self.range) ⇒ Object
Iteration 1.
- #except(&p) ⇒ Object
- #increment(&p) ⇒ Object
-
#initialize(range) {|_self| ... } ⇒ SubRangeIterator
constructor
A new instance of SubRangeIterator.
-
#limit_to(n) ⇒ Object
note: useful for chaining instead of limit=.
- #offset(&p) ⇒ Object
-
#range_extensions ⇒ Object
a bit hacky - used to extend concrete subranges with the same extensions as the range.
- #span(&p) ⇒ Object
-
#step_by(n) ⇒ Object
note: useful for chaining instead of step=.
Methods included from Tempr::DateTimeRange
#Apr, #April, #Aug, #August, #Dec, #December, #Feb, #February, #Fri, #Friday, #Jan, #January, #Jul, #July, #Jun, #June, #Mar, #March, #May, #Mon, #Monday, #Nov, #November, #Oct, #October, #Sat, #Saturday, #Sep, #September, #Sun, #Sunday, #Thu, #Thursday, #Tue, #Tuesday, #WEEKDAYS, #WEEKENDS, #Wed, #Wednesday, #adjacent_to?, #at_time, #between_times, #build_subrange, #day, #day_range, #each_april, #each_august, #each_day_of_month, #each_days, #each_days_of_week, #each_december, #each_february, #each_friday, #each_hours, #each_january, #each_july, #each_june, #each_march, #each_may, #each_minutes, #each_monday, #each_monthnum, #each_months, #each_november, #each_october, #each_saturday, #each_seconds, #each_september, #each_sunday, #each_thursday, #each_time_of_day, #each_tuesday, #each_wdays, #each_wednesday, #each_weekdays, #each_weekends, #each_weekends_including_friday, #each_weeks, #each_years, #friday, #hour, #intersection_with, #intersects?, #minute, #monday, #month, #on_day, #precedes?, #saturday, #second, #subsume?, #succeeds?, #sunday, #thursday, #time_range, #tuesday, #wday, #wednesday, #week, #within?, #year
Constructor Details
#initialize(range) {|_self| ... } ⇒ SubRangeIterator
Returns a new instance of SubRangeIterator.
609 610 611 612 |
# File 'lib/tempr/date_time_range.rb', line 609 def initialize(range) self.range = range yield self if block_given? end |
Instance Attribute Details
#limit ⇒ Object
Returns the value of attribute limit.
597 598 599 |
# File 'lib/tempr/date_time_range.rb', line 597 def limit @limit end |
#range ⇒ Object
Returns the value of attribute range.
597 598 599 |
# File 'lib/tempr/date_time_range.rb', line 597 def range @range end |
#step ⇒ Object
Returns the value of attribute step.
597 598 599 |
# File 'lib/tempr/date_time_range.rb', line 597 def step @step end |
Instance Method Details
#adjust_range(&p) ⇒ Object
626 627 628 629 |
# File 'lib/tempr/date_time_range.rb', line 626 def adjust_range(&p) self.range_proc = p self end |
#by_step(n) ⇒ Object
‘stateless’ step enumerator simply generates infinite integer sequence if ruby already has such a facility built-in, let me know
704 705 706 707 708 709 710 711 |
# File 'lib/tempr/date_time_range.rb', line 704 def by_step(n) @step_enumerator ||= Enumerator.new do |y| i=0 loop do y << i; i+=n end end end |
#cover?(dt) ⇒ Boolean
651 652 653 |
# File 'lib/tempr/date_time_range.rb', line 651 def cover?(dt) any? {|r| r.cover?(dt)} end |
#each(&b) ⇒ Object
Recursive madness… note this could possibly use cached results stored by #all method, similar to Sequel
658 659 660 661 662 663 664 665 666 667 668 669 |
# File 'lib/tempr/date_time_range.rb', line 658 def each(&b) if self.range.respond_to?(:each_by_step) self.range.each do |sub| each_by_step(sub, &b) end else each_by_step do |sub| # puts "self.range = #{self.range} yielded: #{sub}" yield sub end end end |
#each_by_step(rng = self.range) ⇒ Object
Iteration
-
adjust base range
-
get offset
-
for each step, 3.1. if limit reached, break 3.2. find begin of next subrange (step_proc) 3.3. find end of next subrange (span_proc) 3.4. check if begin in adjusted base range, stop iteration if not 3.5. check if begin matches any exceptions (exception_procs)
3.5.1 if not, increment the yield count (i) 3.5.2 and yield the subrange, extended with same modules as base range
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 |
# File 'lib/tempr/date_time_range.rb', line 682 def each_by_step(rng=self.range) rng = range_proc.call(rng) # puts "each_by_step range: #{rng}" initial = offset_proc.call(rng.begin) i=0 by_step(self.step).each do |n| break if self.limit && self.limit <= i next_begin = step_proc.call(initial,n) next_end = span_proc.call(next_begin) if rng.respond_to?(:cover?) && !rng.cover?(next_begin) raise StopIteration end unless exception_procs.any? {|except| except.call(next_begin)} i+=1 yield((next_begin...next_end).extend(*range_extensions)) end end end |
#except(&p) ⇒ Object
646 647 648 649 |
# File 'lib/tempr/date_time_range.rb', line 646 def except(&p) exception_procs << p self end |
#increment(&p) ⇒ Object
636 637 638 639 |
# File 'lib/tempr/date_time_range.rb', line 636 def increment(&p) self.step_proc = p self end |
#limit_to(n) ⇒ Object
note: useful for chaining instead of limit=
621 622 623 624 |
# File 'lib/tempr/date_time_range.rb', line 621 def limit_to(n) self.limit = n self end |
#offset(&p) ⇒ Object
631 632 633 634 |
# File 'lib/tempr/date_time_range.rb', line 631 def offset(&p) self.offset_proc = p self end |
#range_extensions ⇒ Object
a bit hacky - used to extend concrete subranges with the same extensions as the range
602 603 604 605 606 607 |
# File 'lib/tempr/date_time_range.rb', line 602 def range_extensions @range_extensions ||= class << self.range self.included_modules - [Kernel] end end |
#span(&p) ⇒ Object
641 642 643 644 |
# File 'lib/tempr/date_time_range.rb', line 641 def span(&p) self.span_proc = p self end |
#step_by(n) ⇒ Object
note: useful for chaining instead of step=
615 616 617 618 |
# File 'lib/tempr/date_time_range.rb', line 615 def step_by(n) self.step = n self end |