mirror of
https://github.com/jimeh/time_ext.git
synced 2026-02-19 13:26:39 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b29c232939 | |||
| f3b9d3751a | |||
| a612a17c54 | |||
| 71c5421587 | |||
| d564c31b93 | |||
| 29e1c7f500 | |||
| f49c6bd455 | |||
| 5ece10846a | |||
| 5afb6bc2b9 | |||
| 9bbd974a75 | |||
| ca929c6ae1 | |||
| edd828bb3e | |||
| 4afd3f84d5 | |||
| ea6d87e35f | |||
| 74574beaf0 | |||
| ba33dfec57 | |||
| c9cd80fd9e | |||
| 06e167d1ab | |||
| ac1ad2dba4 | |||
| ab6e1e8003 | |||
| 3d2b5d0b9e | |||
| b8ba272b95 | |||
| 3201485eaf | |||
| 77d9d67ed1 |
10
Gemfile
Normal file
10
Gemfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
source 'http://rubygems.org/'
|
||||||
|
|
||||||
|
gem 'activesupport', '>= 2.3.0'
|
||||||
|
gem 'i18n', '>= 0.4.2'
|
||||||
|
|
||||||
|
group :development do
|
||||||
|
gem 'jeweler', '>= 1.4.0'
|
||||||
|
gem 'rspec', '>= 2.1.0'
|
||||||
|
gem 'yard', '>= 0.6.3'
|
||||||
|
end
|
||||||
34
Gemfile.lock
Normal file
34
Gemfile.lock
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
GEM
|
||||||
|
remote: http://rubygems.org/
|
||||||
|
specs:
|
||||||
|
activesupport (3.0.3)
|
||||||
|
diff-lcs (1.1.2)
|
||||||
|
gemcutter (0.6.1)
|
||||||
|
git (1.2.5)
|
||||||
|
i18n (0.4.2)
|
||||||
|
jeweler (1.4.0)
|
||||||
|
gemcutter (>= 0.1.0)
|
||||||
|
git (>= 1.2.5)
|
||||||
|
rubyforge (>= 2.0.0)
|
||||||
|
json_pure (1.4.6)
|
||||||
|
rspec (2.1.0)
|
||||||
|
rspec-core (~> 2.1.0)
|
||||||
|
rspec-expectations (~> 2.1.0)
|
||||||
|
rspec-mocks (~> 2.1.0)
|
||||||
|
rspec-core (2.1.0)
|
||||||
|
rspec-expectations (2.1.0)
|
||||||
|
diff-lcs (~> 1.1.2)
|
||||||
|
rspec-mocks (2.1.0)
|
||||||
|
rubyforge (2.0.4)
|
||||||
|
json_pure (>= 1.1.7)
|
||||||
|
yard (0.6.3)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
activesupport (>= 2.3.0)
|
||||||
|
i18n (>= 0.4.2)
|
||||||
|
jeweler (>= 1.4.0)
|
||||||
|
rspec (>= 2.1.0)
|
||||||
|
yard (>= 0.6.3)
|
||||||
21
Rakefile
21
Rakefile
@@ -10,23 +10,24 @@ begin
|
|||||||
gem.email = "contact@jimeh.me"
|
gem.email = "contact@jimeh.me"
|
||||||
gem.homepage = "http://github.com/jimeh/time_ext"
|
gem.homepage = "http://github.com/jimeh/time_ext"
|
||||||
gem.authors = ["Jim Myhrberg"]
|
gem.authors = ["Jim Myhrberg"]
|
||||||
gem.add_dependency "activesupport", ">= 2.3.0"
|
gem.add_dependency 'activesupport', '>= 2.3.0'
|
||||||
gem.add_development_dependency "rspec", ">= 1.2.9"
|
gem.add_dependency 'i18n', '>= 0.4.2'
|
||||||
gem.add_development_dependency "yard", ">= 0"
|
gem.add_development_dependency 'jeweler', '>= 1.4.0'
|
||||||
|
gem.add_development_dependency 'rspec', '>= 2.1.0'
|
||||||
|
gem.add_development_dependency 'yard', '>= 0.6.3'
|
||||||
end
|
end
|
||||||
Jeweler::GemcutterTasks.new
|
Jeweler::GemcutterTasks.new
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'spec/rake/spectask'
|
# Rspec
|
||||||
Spec::Rake::SpecTask.new(:spec) do |spec|
|
require 'rspec/core/rake_task'
|
||||||
spec.libs << 'lib' << 'spec'
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
||||||
spec.spec_files = FileList['spec/**/*_spec.rb']
|
spec.pattern = 'spec/**/*_spec.rb'
|
||||||
end
|
end
|
||||||
|
|
||||||
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
||||||
spec.libs << 'lib' << 'spec'
|
|
||||||
spec.pattern = 'spec/**/*_spec.rb'
|
spec.pattern = 'spec/**/*_spec.rb'
|
||||||
spec.rcov = true
|
spec.rcov = true
|
||||||
end
|
end
|
||||||
@@ -35,9 +36,11 @@ task :spec => :check_dependencies
|
|||||||
|
|
||||||
task :default => :spec
|
task :default => :spec
|
||||||
|
|
||||||
|
desc "Start an irb console with TimeExt pre-loaded."
|
||||||
task :console do
|
task :console do
|
||||||
exec "irb -r spec/spec_helper"
|
exec "irb -r spec/spec_helper"
|
||||||
end
|
end
|
||||||
|
task :c => :console
|
||||||
|
|
||||||
begin
|
begin
|
||||||
require 'yard'
|
require 'yard'
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
require 'active_support'
|
require 'active_support'
|
||||||
|
|
||||||
require 'time_ext/backwards_compatibility'
|
# support both Active Support 2.x and 3.x
|
||||||
|
require 'active_support/time' if !Time.respond_to?(:days_in_month)
|
||||||
|
|
||||||
require 'time_ext/calculations'
|
require 'time_ext/calculations'
|
||||||
require 'time_ext/iterations'
|
require 'time_ext/iterations'
|
||||||
require 'time_ext/method_chain'
|
require 'time_ext/support'
|
||||||
require 'time_ext/core_ext/time'
|
require 'time_ext/core_ext/time'
|
||||||
|
require 'time_ext/core_ext/numeric'
|
||||||
|
|||||||
@@ -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
|
|
||||||
4
lib/time_ext/core_ext/numeric.rb
Normal file
4
lib/time_ext/core_ext/numeric.rb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
class Numeric
|
||||||
|
alias :sec :seconds
|
||||||
|
alias :min :minutes
|
||||||
|
end
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
class Time
|
class Time
|
||||||
include TimeExt::MethodChain
|
include TimeExt::Support
|
||||||
include TimeExt::BackwardsCompatibility
|
|
||||||
include TimeExt::Calculations
|
include TimeExt::Calculations
|
||||||
include TimeExt::Iterations
|
include TimeExt::Iterations
|
||||||
|
|
||||||
|
|||||||
@@ -4,16 +4,23 @@ module TimeExt
|
|||||||
|
|
||||||
# Used by #each, #map_each and similar methods to iterate over ranges of time.
|
# Used by #each, #map_each and similar methods to iterate over ranges of time.
|
||||||
def iterate(unit, options = {}, &block)
|
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?
|
if block_given?
|
||||||
units = [:year, :month, :day, :hour, :min, :sec, :usec]
|
units = [:year, :month, :day, :hour, :min, :sec, :usec]
|
||||||
parent_unit = units[units.index(unit)-1]
|
parent_unit = units[units.index(unit)-1]
|
||||||
@until ||= (!parent_unit.nil?) ? self.send("#{parent_unit}s_since", 1) : self.send("#{unit}s_since", 1)
|
if @of_the.nil?
|
||||||
time = self.clone
|
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.next(@of_the).beginning_of(@of_the)
|
||||||
|
options.merge!(:beginning_of => true, :include_start => true, :include_end => false)
|
||||||
|
end
|
||||||
direction = (self < @until) ? :f : :b
|
direction = (self < @until) ? :f : :b
|
||||||
succ_method = (direction == :f) ? "next_#{unit}" : "prev_#{unit}"
|
succ_method = (direction == :f) ? "next_#{unit}" : "prev_#{unit}"
|
||||||
time = time.beginning_of(unit) if options[:beginning_of]
|
time = time.beginning_of(unit) if options[:beginning_of]
|
||||||
time = time.send(succ_method) if !options[:include_start]
|
time = time.send(succ_method) if !options[:include_start]
|
||||||
|
@until = @until.prev(unit).end_of(unit) if !options[:include_end]
|
||||||
results = []
|
results = []
|
||||||
while (direction == :f && time <= @until) || (direction == :b && time >= @until)
|
while (direction == :f && time <= @until) || (direction == :b && time >= @until)
|
||||||
options[:map_result] ? results << yield(time) : yield(time)
|
options[:map_result] ? results << yield(time) : yield(time)
|
||||||
@@ -46,6 +53,14 @@ module TimeExt
|
|||||||
end
|
end
|
||||||
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.
|
# 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)
|
def each(unit, options = {}, &block)
|
||||||
iterate(unit, options.merge(:map_result => false), &block)
|
iterate(unit, options.merge(:map_result => false), &block)
|
||||||
@@ -60,7 +75,6 @@ module TimeExt
|
|||||||
def map_each(unit, options = {}, &block)
|
def map_each(unit, options = {}, &block)
|
||||||
iterate(unit, options.merge(:map_result => true), &block)
|
iterate(unit, options.merge(:map_result => true), &block)
|
||||||
end
|
end
|
||||||
alias :map :map_each
|
|
||||||
|
|
||||||
# Executes passed block for each "unit" of time specified, returning an array with the return values from passed block. Additionally the time object passed into the block is set to the beginning of specified "unit".
|
# Executes passed block for each "unit" of time specified, returning an array with the return values from passed block. Additionally the time object passed into the block is set to the beginning of specified "unit".
|
||||||
def map_beginning_of_each(unit, options = {}, &block)
|
def map_beginning_of_each(unit, options = {}, &block)
|
||||||
@@ -69,7 +83,14 @@ module TimeExt
|
|||||||
|
|
||||||
# Dynamically define convenience methods, like #each_hour instead of #each(:hour).
|
# Dynamically define convenience methods, like #each_hour instead of #each(:hour).
|
||||||
[:year, :month, :day, :hour, :min, :sec].each do |unit|
|
[:year, :month, :day, :hour, :min, :sec].each do |unit|
|
||||||
[:each, :beginning_of_each, :map_each, :map_beginning_of_each, :map].each do |method|
|
[:each, :beginning_of_each, :map_each, :map_beginning_of_each].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
|
||||||
|
[:of_the, :of].each do |method|
|
||||||
define_method "#{method}_#{unit}" do |*args, &block|
|
define_method "#{method}_#{unit}" do |*args, &block|
|
||||||
send(method, unit, *args, &block)
|
send(method, unit, *args, &block)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -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
|
|
||||||
27
lib/time_ext/support.rb
Normal file
27
lib/time_ext/support.rb
Normal file
@@ -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
|
||||||
19
spec/core_ext_spec.rb
Normal file
19
spec/core_ext_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||||
|
|
||||||
|
describe "Core Extensions" do
|
||||||
|
|
||||||
|
it "should alias Numeric class methods" do
|
||||||
|
number = 1
|
||||||
|
number.sec.should == number.second
|
||||||
|
number.min.should == number.minute
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should alias Time instance methods" do
|
||||||
|
time = Time.now
|
||||||
|
time.secs_ago(10).should == time.ago(10)
|
||||||
|
time.seconds_ago(10).should == time.ago(10)
|
||||||
|
time.secs_since(10).should == time.since(10)
|
||||||
|
time.seconds_since(10).should == time.since(10)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
--format specdoc
|
|
||||||
--color
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
||||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||||
|
|
||||||
require 'time_ext'
|
require 'time_ext'
|
||||||
require 'spec'
|
require 'rspec'
|
||||||
require 'spec/autorun'
|
require 'rspec/autorun'
|
||||||
|
|
||||||
Spec::Runner.configure do |config|
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ describe "Time Iterations" do
|
|||||||
match = (1..6).map { |i| @now + i.hours }
|
match = (1..6).map { |i| @now + i.hours }
|
||||||
@now.map_each_hour.until(@now + 6.hours) { |time| time }.should == match
|
@now.map_each_hour.until(@now + 6.hours) { |time| time }.should == match
|
||||||
@now.until(@now + 6.hours).map_each(:hour) { |time| time }.should == match
|
@now.until(@now + 6.hours).map_each(:hour) { |time| time }.should == match
|
||||||
# check so the #map alias for #map_each works
|
|
||||||
@now.map_hour.until(@now + 6.hours) { |time| time }.should == match
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should iterate over time objects backwards with #until set in the past" do
|
it "should iterate over time objects backwards with #until set in the past" do
|
||||||
@@ -68,4 +66,32 @@ describe "Time Iterations" do
|
|||||||
(@now + 6.hours).from(@now).map_each(:hour) { |time| time }.should == match
|
(@now + 6.hours).from(@now).map_each(:hour) { |time| time }.should == match
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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, :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 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
|
||||||
|
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
|
end
|
||||||
Reference in New Issue
Block a user