Permalink
Browse files

length of month support. defaults to current month length

  • Loading branch information...
1 parent c4722c9 commit 7934dfaeb07feef9e4c10613a75dfc46596cf531 @joshbuddy committed May 3, 2010
Showing with 21 additions and 7 deletions.
  1. +16 −6 lib/spanner.rb
  2. +5 −1 spec/spanner_spec.rb
View
22 lib/spanner.rb
@@ -1,17 +1,19 @@
+require 'date'
+
class Spanner
ParseError = Class.new(RuntimeError)
def self.parse(str, opts = nil)
- Spanner.new(str, opts).parse
+ Spanner.new(opts).parse(str)
end
attr_reader :value, :raise_on_error, :from
- def initialize(value, opts)
+ def initialize(opts)
@value = value
@on_error = opts && opts.key?(:on_error) ? opts[:on_error] : :raise
-
+ @length_of_month = opts && opts[:length_of_month]
@from = if opts && opts.key?(:from)
case opts[:from]
@@ -25,13 +27,21 @@ def initialize(value, opts)
end
end
+ def self.days_in_month(year, month)
+ (Date.new(year, 12, 31) << (12-month)).day
+ end
+
+ def length_of_month
+ @length_of_month ||= Spanner.parse("#{Spanner.days_in_month(Time.new.year, Time.new.month)} days")
+ end
+
def error(err)
if on_error == :raise
raise ParseError.new(err)
end
end
- def parse
+ def parse(value)
parts = []
part_contextualized = nil
value.scan(/[\+\-]?(?:\d*\.\d+|\d+)|[a-z]+/i).each do |part|
@@ -56,13 +66,13 @@ def parse
when 'm', 'min', 'minutes' then 60
when 'd', 'days' then 86_400
when 'w', 'wks', 'weeks' then 604_800
- when 'months', 'month', 'm' then 2_629_743.83
+ when 'months', 'month', 'M' then length_of_month
when 'years', 'y' then 31_556_926
when /\As/ then 1
when /\Am/ then 60
when /\Ah/ then 86_400
when /\Aw/ then 604_800
- when /\Am/ then 2_629_743.83
+ when /\AM/ then length_of_month
when /\Ay/ then 31_556_926
end
View
6 spec/spanner_spec.rb
@@ -11,7 +11,7 @@
end
#simple
- { '.5s' => 0.5, '1s' => 1, '1.5s' => 1.5, '1m' => 60, '1.5m' => 90, '1d' => 86400, '1.7233312d' => 148895.81568 }.each do |input, output|
+ { '.5s' => 0.5, '1s' => 1, '1.5s' => 1.5, '1m' => 60, '1.5m' => 90, '1d' => 86400, '1.7233312d' => 148895.81568, '1M' => Spanner.days_in_month(Time.new.year, Time.new.month) * 24 * 60 * 60 }.each do |input, output|
it "should parse #{input} and return #{output}" do
Spanner.parse(input).should == output
end
@@ -24,6 +24,10 @@
end
end
+ it "should let you set the length of a month" do
+ Spanner.parse("4 months", :length_of_month => 1234).should == 4936
+ end
+
it "should accept time as from option" do
now = Time.new
Spanner.parse('23s', :from => now).should == now.to_i + 23

0 comments on commit 7934dfa

Please sign in to comment.