diff --git a/lib/chronic/handlers.rb b/lib/chronic/handlers.rb index adc9700c..2a6e9efd 100644 --- a/lib/chronic/handlers.rb +++ b/lib/chronic/handlers.rb @@ -92,6 +92,25 @@ def handle_sd_rmn(tokens, options) handle_m_d(month, day, tokens[2..tokens.size], options) end + def handle_od(tokens, options) + t = Chronic.time_class.parse(options[:text]) + t = Chronic.time_class.new(self.now.year, self.now.month, t.day) + + Span.new(t, t + 1) + rescue ArgumentError => e + raise e unless e.message =~ /out of range/ + end + + # Handle scalar-day + def handle_sd(tokens, options) + day = tokens[0].get_tag(ScalarDay) + t = Chronic.time_class.new(self.now.year, self.now.month, day.type) + + Span.new(t, t + 1) + rescue ArgumentError => e + raise e unless e.message =~ /out of range/ + end + # Handle repeater-month-name/ordinal-day with separator-on def handle_rmn_od_on(tokens, options) if tokens.size > 3 diff --git a/lib/chronic/parser.rb b/lib/chronic/parser.rb index 28d16a60..8fa4065f 100644 --- a/lib/chronic/parser.rb +++ b/lib/chronic/parser.rb @@ -12,7 +12,8 @@ class Parser :guess => true, :ambiguous_time_range => 6, :endian_precedence => [:middle, :little], - :ambiguous_year_future_bias => 50 + :ambiguous_year_future_bias => 50, + :ambiguous_number_priority => :time } attr_accessor :now @@ -47,6 +48,9 @@ class Parser # look x amount of years into the future and past. If the # two digit year is `now + x years` it's assumed to be the # future, `now - x years` is assumed to be the past. + # :ambiguous_number_priority - When parsing a number on its own (e.g. "1"), + # should it be treated as a time (1pm) or a date (1st of + # the current month)? Valid values are :time (default) or :date def initialize(options = {}) @options = DEFAULT_OPTIONS.merge(options) @now = options.delete(:now) || Chronic.time_class.now @@ -162,7 +166,7 @@ def definitions(options = {}) Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day, :separator_at?, 'time?'], :handle_rdn_rmn_od), Handler.new([:repeater_day_name, :ordinal_day, :separator_at?, 'time?'], :handle_rdn_od), Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar_day, :repeater_time, :time_zone], :handle_generic), - Handler.new([:ordinal_day], :handle_generic), + Handler.new([:ordinal_day], :handle_od), Handler.new([:repeater_month_name, :scalar_day, :scalar_year], :handle_rmn_sd_sy), Handler.new([:repeater_month_name, :ordinal_day, :scalar_year], :handle_rmn_od_sy), Handler.new([:repeater_month_name, :scalar_day, :scalar_year, :separator_at?, 'time?'], :handle_rmn_sd_sy), @@ -204,6 +208,12 @@ def definitions(options = {}) ] } + if options[:ambiguous_number_priority] == :date + @@definitions[:date] << Handler.new([:scalar_day], :handle_sd) + else + @@definitions[:date] = @@definitions[:date].reject { |l| l.pattern == [:scalar_day] } + end + endians = [ Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_day, [:separator_slash, :separator_dash], :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy), Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_day, :separator_at?, 'time?'], :handle_sm_sd), diff --git a/test/helper.rb b/test/helper.rb index cb961435..d2da8d79 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -3,6 +3,7 @@ require 'chronic' end +require 'minitest' require 'minitest/autorun' class TestCase < MiniTest::Test diff --git a/test/test_parsing.rb b/test/test_parsing.rb index efc0a1e5..274abb1a 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -34,9 +34,26 @@ def test_handle_generic assert_in_delta time, time2, 0.000001 assert_nil Chronic.parse("1/1/32.1") + end + + def test_handle_od + now = Time.new(2013, 8, 1) + time = Chronic.parse("28th", :now => now) + assert_equal Time.new(2013, 8, 28), time + + now = Time.new(2013, 9, 1) + time = Chronic.parse("28th", :now => now) + assert_equal Time.new(2013, 9, 28), time + end + + def test_handle_sd + now = Time.new(2013, 8, 1) + time = Chronic.parse("28", :now => now, :ambiguous_number_priority => :date) + assert_equal Time.new(2013, 8, 28), time - time = Chronic.parse("28th") - assert_equal Time.new(Time.now.year, Time.now.month, 28), time + now = Time.new(2013, 9, 1) + time = Chronic.parse("28", :now => now, :ambiguous_number_priority => :date) + assert_equal Time.new(2013, 9, 28), time end def test_handle_rmn_sd