From 77d9d67ed18978eba3424d70b2ccdd39916c6ddb Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Wed, 4 Aug 2010 17:28:22 +0300 Subject: [PATCH 1/4] merged MethodChain and BackwardsCompatibility modules into a single TimeExt::Support module --- lib/time_ext.rb | 2 +- lib/time_ext/backwards_compatibility.rb | 14 ------------- lib/time_ext/core_ext/time.rb | 3 +-- lib/time_ext/method_chain.rb | 19 ----------------- lib/time_ext/support.rb | 27 +++++++++++++++++++++++++ 5 files changed, 29 insertions(+), 36 deletions(-) delete mode 100644 lib/time_ext/backwards_compatibility.rb delete mode 100644 lib/time_ext/method_chain.rb create mode 100644 lib/time_ext/support.rb diff --git a/lib/time_ext.rb b/lib/time_ext.rb index 7ecb4eb..a849076 100644 --- a/lib/time_ext.rb +++ b/lib/time_ext.rb @@ -1,8 +1,8 @@ require 'rubygems' require 'active_support' -require 'time_ext/backwards_compatibility' require 'time_ext/calculations' require 'time_ext/iterations' require 'time_ext/method_chain' +require 'time_ext/support' require 'time_ext/core_ext/time' diff --git a/lib/time_ext/backwards_compatibility.rb b/lib/time_ext/backwards_compatibility.rb deleted file mode 100644 index 376ad4e..0000000 --- a/lib/time_ext/backwards_compatibility.rb +++ /dev/null @@ -1,14 +0,0 @@ -module TimeExt - # Provides helper methods used by TimeExt::Calculations for backwards compatibility with ActiveSupport. - module BackwardsCompatibility - - def days_into_week - defined?(DAYS_INTO_WEEK) ? DAYS_INTO_WEEK : { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 } - end - - def common_year_days_in_month - defined?(COMMON_YEAR_DAYS_IN_MONTH) ? COMMON_YEAR_DAYS_IN_MONTH : [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] - end - - end -end \ No newline at end of file diff --git a/lib/time_ext/core_ext/time.rb b/lib/time_ext/core_ext/time.rb index c060b89..aa5c599 100644 --- a/lib/time_ext/core_ext/time.rb +++ b/lib/time_ext/core_ext/time.rb @@ -1,6 +1,5 @@ class Time - include TimeExt::MethodChain - include TimeExt::BackwardsCompatibility + include TimeExt::Support include TimeExt::Calculations include TimeExt::Iterations diff --git a/lib/time_ext/method_chain.rb b/lib/time_ext/method_chain.rb deleted file mode 100644 index 09592c8..0000000 --- a/lib/time_ext/method_chain.rb +++ /dev/null @@ -1,19 +0,0 @@ -module TimeExt - # Allows iterators' #until and #from methods to chain back to the parent iteration method. - module MethodChain - - def add_to_chain(method, *args, &block) - @method_chain ||= [] - @method_chain << [method.to_sym, args, block] - end - - def call_chain(custom_block = nil, &block) - method, args, iblock = @method_chain.pop - return nil if method.nil? - iblock = custom_block if !custom_block.nil? - method, args, iblock = yield(method, args, iblock) if block_given? - self.send(method, *args, &iblock) - end - - end -end \ No newline at end of file diff --git a/lib/time_ext/support.rb b/lib/time_ext/support.rb new file mode 100644 index 0000000..ff3e0e2 --- /dev/null +++ b/lib/time_ext/support.rb @@ -0,0 +1,27 @@ +module TimeExt + # Provides helper methods used by TimeExt::Calculations for backwards compatibility with ActiveSupport, and method chaining helpers for TimeExt::Iterations. + module Support + + def days_into_week + defined?(DAYS_INTO_WEEK) ? DAYS_INTO_WEEK : { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 } + end + + def common_year_days_in_month + defined?(COMMON_YEAR_DAYS_IN_MONTH) ? COMMON_YEAR_DAYS_IN_MONTH : [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + end + + def add_to_chain(method, *args, &block) + @method_chain ||= [] + @method_chain << [method.to_sym, args, block] + end + + def call_chain(custom_block = nil, &block) + method, args, iblock = @method_chain.pop + return nil if method.nil? + iblock = custom_block if !custom_block.nil? + method, args, iblock = yield(method, args, iblock) if block_given? + self.send(method, *args, &iblock) + end + + end +end \ No newline at end of file From 3201485eaf295da28c2bd8913a505f70698869d7 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Wed, 4 Aug 2010 17:58:58 +0300 Subject: [PATCH 2/4] Added #of_the / #of range modifier which is used like #until and #from. Except #of_the makes the iteration walk through each unit of time passed to the #each / #map method, from the beginning till end of unit passed to #of_the. Example: Time.now.each_hour.of_the(:month) { |t puts t } #=> iterates over each over of the whole current month --- lib/time_ext/iterations.rb | 26 ++++++++++++++++++++++++-- spec/time_iterations_spec.rb | 21 ++++++++++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/lib/time_ext/iterations.rb b/lib/time_ext/iterations.rb index 6cd4112..1144237 100644 --- a/lib/time_ext/iterations.rb +++ b/lib/time_ext/iterations.rb @@ -8,12 +8,19 @@ module TimeExt if block_given? units = [:year, :month, :day, :hour, :min, :sec, :usec] parent_unit = units[units.index(unit)-1] - @until ||= (!parent_unit.nil?) ? self.send("#{parent_unit}s_since", 1) : self.send("#{unit}s_since", 1) - time = self.clone + if @of_the.nil? + time = self.clone + @until ||= (!parent_unit.nil?) ? self.send("#{parent_unit}s_since", 1) : self.send("#{unit}s_since", 1) + else + time = self.beginning_of(@of_the) + @until = self.end_of(@of_the) + options.merge!(:beginning_of => true, :include_start => true) + end direction = (self < @until) ? :f : :b succ_method = (direction == :f) ? "next_#{unit}" : "prev_#{unit}" time = time.beginning_of(unit) if options[:beginning_of] time = time.send(succ_method) if !options[:include_start] + @until = @until.prev(unit).end_of(unit) if options[:include_start] && @of_the.nil? results = [] while (direction == :f && time <= @until) || (direction == :b && time >= @until) options[:map_result] ? results << yield(time) : yield(time) @@ -46,6 +53,14 @@ module TimeExt end end + # Let's you iterate over every unit specified in the #each or #map call for the specified unit. + def of_the(unit, &block) + @of_the = unit + return call_chain(block) if block_given? + self + end + alias :of :of_the + # Executes passed block for each "unit" of time specified, with a new time object for each interval passed to the block. def each(unit, options = {}, &block) iterate(unit, options.merge(:map_result => false), &block) @@ -76,6 +91,13 @@ module TimeExt class_eval { alias :"#{method}_minute" :"#{method}_min" } if unit == :min class_eval { alias :"#{method}_second" :"#{method}_sec" } if unit == :sec end + [:of_the, :of].each do |method| + define_method "#{method}_#{unit}" do |*args, &block| + send(method, unit, *args, &block) + end + class_eval { alias :"#{method}_minute" :"#{method}_min" } if unit == :min + class_eval { alias :"#{method}_second" :"#{method}_sec" } if unit == :sec + end end end diff --git a/spec/time_iterations_spec.rb b/spec/time_iterations_spec.rb index b9e0b5e..605488a 100644 --- a/spec/time_iterations_spec.rb +++ b/spec/time_iterations_spec.rb @@ -68,4 +68,23 @@ describe "Time Iterations" do (@now + 6.hours).from(@now).map_each(:hour) { |time| time }.should == match end -end \ No newline at end of file + it "should iterate over time objects with #map_each and #of_the via method chaining" do + match = (0..23).map { |i| ((@now - (@now.hour).hours) + i.hours).beginning_of_hour } + @now.map_each_hour.of_the(:day) { |time| time }.should == match + @now.map_each_hour.of_the_day { |time| time }.should == match + match = @now.beginning_of_month.map_beginning_of_each_hour(:include_start => true).until(@now.next_month.beginning_of_month) { |time| time } + @now.map_each_hour.of_the(:month) { |time| time }.should == match + end + + it "should iterate and respect the include_start option" do + match = (0..5).map { |i| @now + i.hours } + @now.map_each_hour(:include_start => true).until(@now + 6.hours) { |time| time }.should == match + end + + it "should iterate and respect the beginning_of option" do + match = (1..6).map { |i| @now.beginning_of_hour + i.hours } + @now.map_beginning_of_each_hour.until(@now.beginning_of_hour + 6.hours) { |time| time }.should == match + @now.map_each_hour(:beginning_of => true).until(@now.beginning_of_hour + 6.hours) { |time| time }.should == match + end + +end From b8ba272b955b4ca0dedfd6740cbe352488bb8755 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Wed, 4 Aug 2010 18:26:14 +0300 Subject: [PATCH 3/4] added include_end option to #iterate --- lib/time_ext/iterations.rb | 8 ++++---- spec/time_iterations_spec.rb | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/time_ext/iterations.rb b/lib/time_ext/iterations.rb index 1144237..24519bc 100644 --- a/lib/time_ext/iterations.rb +++ b/lib/time_ext/iterations.rb @@ -4,7 +4,7 @@ module TimeExt # Used by #each, #map_each and similar methods to iterate over ranges of time. def iterate(unit, options = {}, &block) - options.reverse_merge!(:map_result => false, :beginning_of => false, :include_start => false) + options.reverse_merge!(:map_result => false, :beginning_of => false, :include_start => false, :include_end => true) if block_given? units = [:year, :month, :day, :hour, :min, :sec, :usec] parent_unit = units[units.index(unit)-1] @@ -13,14 +13,14 @@ module TimeExt @until ||= (!parent_unit.nil?) ? self.send("#{parent_unit}s_since", 1) : self.send("#{unit}s_since", 1) else time = self.beginning_of(@of_the) - @until = self.end_of(@of_the) - options.merge!(:beginning_of => true, :include_start => true) + @until = self.next(@of_the).beginning_of(@of_the) + options.merge!(:beginning_of => true, :include_start => true, :include_end => false) end direction = (self < @until) ? :f : :b succ_method = (direction == :f) ? "next_#{unit}" : "prev_#{unit}" time = time.beginning_of(unit) if options[:beginning_of] time = time.send(succ_method) if !options[:include_start] - @until = @until.prev(unit).end_of(unit) if options[:include_start] && @of_the.nil? + @until = @until.prev(unit).end_of(unit) if !options[:include_end] results = [] while (direction == :f && time <= @until) || (direction == :b && time >= @until) options[:map_result] ? results << yield(time) : yield(time) diff --git a/spec/time_iterations_spec.rb b/spec/time_iterations_spec.rb index 605488a..4eaa326 100644 --- a/spec/time_iterations_spec.rb +++ b/spec/time_iterations_spec.rb @@ -72,13 +72,22 @@ describe "Time Iterations" do match = (0..23).map { |i| ((@now - (@now.hour).hours) + i.hours).beginning_of_hour } @now.map_each_hour.of_the(:day) { |time| time }.should == match @now.map_each_hour.of_the_day { |time| time }.should == match - match = @now.beginning_of_month.map_beginning_of_each_hour(:include_start => true).until(@now.next_month.beginning_of_month) { |time| time } + match = @now.beginning_of_month.map_beginning_of_each_hour(:include_start => true, :include_end => false).until(@now.next_month.beginning_of_month) { |time| time } @now.map_each_hour.of_the(:month) { |time| time }.should == match end - it "should iterate and respect the include_start option" do - match = (0..5).map { |i| @now + i.hours } + it "should iterate and respect the include_start and include_end options" do + match = (1..6).map { |i| @now + i.hours } + @now.map_each_hour.until(@now + 6.hours) { |time| time }.should == match + match = (1..6).map { |i| @now + i.hours } + @now.map_each_hour(:include_end => true).until(@now + 6.hours) { |time| time }.should == match + @now.map_each_hour(:include_start => false).until(@now + 6.hours) { |time| time }.should == match + match = (0..6).map { |i| @now + i.hours } @now.map_each_hour(:include_start => true).until(@now + 6.hours) { |time| time }.should == match + match = (0..5).map { |i| @now + i.hours } + @now.map_each_hour(:include_start => true, :include_end => false).until(@now + 6.hours) { |time| time }.should == match + match = (0..6).map { |i| @now + i.hours } + @now.map_each_hour(:include_start => true, :include_end => true).until(@now + 6.hours) { |time| time }.should == match end it "should iterate and respect the beginning_of option" do From 3d2b5d0b9e319f1e70861c78a2ac9ab977d4e2e5 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Thu, 5 Aug 2010 12:49:49 +0300 Subject: [PATCH 4/4] Version bump to 0.2.2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0c62199..ee1372d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.1 +0.2.2