From 5e14db0fcdfae565e15f80c8ccfa639ba5b3f180 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Sun, 14 Aug 2011 11:22:57 +0100 Subject: [PATCH 001/184] initial commit for handling scalar day/scalar month --- lib/chronic/chronic.rb | 1 + lib/chronic/handlers.rb | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 646176e9..47f31f16 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -183,6 +183,7 @@ def definitions(options={}) Handler.new([:repeater_month_name, :scalar_year], :handle_rmn_sy), Handler.new([:scalar_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_sd_rmn_sy), Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sy_sm_sd), + Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day], :handle_sd_sm), Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_year], :handle_sm_sy) ], diff --git a/lib/chronic/handlers.rb b/lib/chronic/handlers.rb index 3584c752..05d19bcd 100644 --- a/lib/chronic/handlers.rb +++ b/lib/chronic/handlers.rb @@ -198,6 +198,28 @@ def handle_sy_sm_sd(tokens, options) handle_sm_sd_sy(new_tokens + time_tokens, options) end + # Handle scalar-day/scalar-month + def handle_sd_sm(tokens, options) + day = tokens[1].get_tag(ScalarDay).type + month = tokens[0].get_tag(ScalarMonth).type + + if Array(options[:endian_precedence]).first == :little + day, month = month, day + end + + year = Chronic.now.year + + return if month_overflow?(year, month, day) + + begin + start_time = Chronic.time_class.local(year, month, day) + end_time = Chronic.time_class.local(year, month, day + 1) + Span.new(start_time, end_time) + rescue ArgumentError + nil + end + end + # Handle scalar-month/scalar-year def handle_sm_sy(tokens, options) month = tokens[0].get_tag(ScalarMonth).type @@ -353,6 +375,8 @@ def month_overflow?(year, month, day) else day > RepeaterMonth::MONTH_DAYS[month - 1] end + rescue ArgumentError + false end # Recursively finds repeaters within other repeaters. From bd9ff2d8336577f9e04ef7da25fe7bccfe9d5680 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Sun, 14 Aug 2011 11:34:47 +0100 Subject: [PATCH 002/184] added tests for sm_sd, and commented out sm_sy --- lib/chronic/chronic.rb | 2 +- lib/chronic/handlers.rb | 9 ++++----- test/test_parsing.rb | 23 +++++++++++++++++------ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 47f31f16..a6285dd7 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -183,7 +183,7 @@ def definitions(options={}) Handler.new([:repeater_month_name, :scalar_year], :handle_rmn_sy), Handler.new([:scalar_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_sd_rmn_sy), Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sy_sm_sd), - Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day], :handle_sd_sm), + Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day], :handle_sm_sd), Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_year], :handle_sm_sy) ], diff --git a/lib/chronic/handlers.rb b/lib/chronic/handlers.rb index 05d19bcd..477b300f 100644 --- a/lib/chronic/handlers.rb +++ b/lib/chronic/handlers.rb @@ -198,17 +198,16 @@ def handle_sy_sm_sd(tokens, options) handle_sm_sd_sy(new_tokens + time_tokens, options) end - # Handle scalar-day/scalar-month - def handle_sd_sm(tokens, options) - day = tokens[1].get_tag(ScalarDay).type + # Handle scalar-day/scalar-month AND scalar-month/scalar-day + def handle_sm_sd(tokens, options) month = tokens[0].get_tag(ScalarMonth).type + day = tokens[1].get_tag(ScalarDay).type + year = Chronic.now.year if Array(options[:endian_precedence]).first == :little day, month = month, day end - year = Chronic.now.year - return if month_overflow?(year, month, day) begin diff --git a/test/test_parsing.rb b/test/test_parsing.rb index 0b1ca295..3927fb5b 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -261,17 +261,28 @@ def test_handle_sy_sm_sd assert_equal Time.local(1902, 8, 20, 12, 0, 0), time end - def test_handle_sm_sy + def test_handle_sm_sd time = parse_now("05/06") - assert_equal Time.local(2006, 5, 16, 12), time + assert_equal Time.local(2006, 5, 6, 12), time - time = parse_now("12/06") - assert_equal Time.local(2006, 12, 16, 12), time + time = parse_now("05/06", :endian_precedence => [:little, :medium]) + assert_equal Time.local(2006, 6, 5, 12), time - time = parse_now("13/06") - assert_equal nil, time + time = parse_now("13/01") + assert_nil time end + # def test_handle_sm_sy + # time = parse_now("05/06") + # assert_equal Time.local(2006, 5, 16, 12), time + # + # time = parse_now("12/06") + # assert_equal Time.local(2006, 12, 16, 12), time + # + # time = parse_now("13/06") + # assert_equal nil, time + # end + def test_handle_r end From 03f140759f3911f721fbe2d59566302f5d7628ba Mon Sep 17 00:00:00 2001 From: Harold Date: Wed, 16 Nov 2011 17:24:04 -0700 Subject: [PATCH 003/184] Chronic.parse("thur") no longer returns nil --- lib/chronic/repeater.rb | 2 +- test/test_parsing.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/chronic/repeater.rb b/lib/chronic/repeater.rb index 679f1b00..ba3fe9cd 100644 --- a/lib/chronic/repeater.rb +++ b/lib/chronic/repeater.rb @@ -58,7 +58,7 @@ def self.scan_for_day_names(token) /^m[ou]n(day)?$/ => :monday, /^t(ue|eu|oo|u|)s?(day)?$/ => :tuesday, /^we(d|dnes|nds|nns)(day)?$/ => :wednesday, - /^th(u(?:rs)?|ers)(day)?$/ => :thursday, + /^th(u|ur|urs|ers)(day)?$/ => :thursday, /^fr[iy](day)?$/ => :friday, /^sat(t?[ue]rday)?$/ => :saturday, /^su[nm](day)?$/ => :sunday diff --git a/test/test_parsing.rb b/test/test_parsing.rb index e86b7a61..7e1c1b5e 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -539,6 +539,34 @@ def test_parse_guess_gr time = parse_now("last wed") assert_equal Time.local(2006, 8, 9, 12), time + monday = Time.local(2006, 8, 21, 12) + assert_equal monday, parse_now("mon") + assert_equal monday, parse_now("mun") + + tuesday = Time.local(2006, 8, 22, 12) + assert_equal tuesday, parse_now("tue") + assert_equal tuesday, parse_now("tus") + + wednesday = Time.local(2006, 8, 23, 12) + assert_equal wednesday, parse_now("wed") + assert_equal wednesday, parse_now("wenns") + + thursday = Time.local(2006, 8, 17, 12) + assert_equal thursday, parse_now("thu") + assert_equal thursday, parse_now("thur") + + friday = Time.local(2006, 8, 18, 12) + assert_equal friday, parse_now("fri") + assert_equal friday, parse_now("fry") + + saturday = Time.local(2006, 8, 19, 12) + assert_equal saturday, parse_now("sat") + assert_equal saturday, parse_now("satterday") + + sunday = Time.local(2006, 8, 20, 12) + assert_equal sunday, parse_now("sun") + assert_equal sunday, parse_now("sum") + # day portion time = parse_now("this morning") From 6618267dcf009bc6dc68f91eb47ed5fc7649b903 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 16 Nov 2011 16:33:22 -0800 Subject: [PATCH 004/184] updated history with work from @harold --- HISTORY.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 214afcde..f040ab53 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,7 @@ +HEAD + +* `Chronic.parse('thur')` no longer returns `nil` (@harold) + # 0.6.5 / 2011-11-04 * Fix bug when parsing ordinal repeaters (#73) From 58dc69bed9470711889222f968706984c0a6d193 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 23 Nov 2011 08:22:34 -0800 Subject: [PATCH 005/184] Release 0.6.6 --- HISTORY.md | 2 +- lib/chronic.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index f040ab53..570bf2bb 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,4 @@ -HEAD +# 0.6.6 / 2011-11-23 * `Chronic.parse('thur')` no longer returns `nil` (@harold) diff --git a/lib/chronic.rb b/lib/chronic.rb index 3816d36e..6fdfa127 100644 --- a/lib/chronic.rb +++ b/lib/chronic.rb @@ -28,7 +28,7 @@ # # @author Tom Preston-Werner, Lee Jarvis module Chronic - VERSION = "0.6.5" + VERSION = "0.6.6" class << self From e565e730a1ab2c07159b8d8ac12c67a44957b4e2 Mon Sep 17 00:00:00 2001 From: Joe Fiorini + Eric Hankinson Date: Tue, 31 Jan 2012 16:28:42 -0500 Subject: [PATCH 006/184] Handles day, month names with scalar day and year --- lib/chronic/chronic.rb | 1 + lib/chronic/handlers.rb | 17 +++++++++++++++++ test/test_parsing.rb | 5 +++++ 3 files changed, 23 insertions(+) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 414751d1..2531d0a0 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -170,6 +170,7 @@ def definitions(options={}) :date => [ Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :repeater_time, :separator_slash_or_dash?, :time_zone, :scalar_year], :handle_rdn_rmn_sd_t_tz_sy), Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day], :handle_rdn_rmn_sd), + Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :scalar_year], :handle_rdn_rmn_sd_sy), Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day], :handle_rdn_rmn_od), Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_day, :repeater_time, :time_zone], :handle_sy_sm_sd_t_tz), Handler.new([:repeater_month_name, :scalar_day, :scalar_year], :handle_rmn_sd_sy), diff --git a/lib/chronic/handlers.rb b/lib/chronic/handlers.rb index e19cb947..e333e565 100644 --- a/lib/chronic/handlers.rb +++ b/lib/chronic/handlers.rb @@ -279,6 +279,23 @@ def handle_rdn_rmn_sd(tokens, options) end end + # Handle RepeaterDayName RepeaterMonthName ScalarDay ScalarYear + def handle_rdn_rmn_sd_sy(tokens, options) + month = tokens[1].get_tag(RepeaterMonthName) + day = tokens[2].get_tag(ScalarDay).type + year = tokens[3].get_tag(ScalarYear).type + + return if month_overflow?(year, month.index, day) + + begin + start_time = Chronic.time_class.local(year, month.index, day) + end_time = Chronic.time_class.local(year, month.index, day + 1) + Span.new(start_time, end_time) + rescue ArgumentError + nil + end + end + # anchors # Handle repeaters diff --git a/test/test_parsing.rb b/test/test_parsing.rb index 7e1c1b5e..41984620 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -928,6 +928,11 @@ def test_handle_rdn_rmn_sd assert_equal Time.local(2006, 8, 10, 12), time end + def test_handle_rdn_rmn_sd_sy + time = parse_now("Thu Aug 10 2006") + assert_equal Time.local(2006, 8, 10, 12), time + end + def test_handle_rdn_rmn_od time = parse_now("Thu Aug 10th") assert_equal Time.local(2006, 8, 10, 12), time From f50d4cd9aaa5ebcd5c214e79534b781a2372e775 Mon Sep 17 00:00:00 2001 From: Joe Fiorini + Eric Hankinson Date: Tue, 31 Jan 2012 17:33:23 -0500 Subject: [PATCH 007/184] Ensures 31st parses correctly with day names --- .gitignore | 1 + lib/chronic/handlers.rb | 20 +++++++++++++++++--- test/test_parsing.rb | 21 +++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2c059691..2b5e8498 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ pkg rdoc .yardoc doc +tags diff --git a/lib/chronic/handlers.rb b/lib/chronic/handlers.rb index e333e565..00dcf71f 100644 --- a/lib/chronic/handlers.rb +++ b/lib/chronic/handlers.rb @@ -255,7 +255,7 @@ def handle_rdn_rmn_od(tokens, options) begin start_time = Chronic.time_class.local(year, month.index, day) - end_time = Chronic.time_class.local(year, month.index, day + 1) + end_time = time_with_rollover(year, month.index, day + 1) Span.new(start_time, end_time) rescue ArgumentError nil @@ -272,7 +272,7 @@ def handle_rdn_rmn_sd(tokens, options) begin start_time = Chronic.time_class.local(year, month.index, day) - end_time = Chronic.time_class.local(year, month.index, day + 1) + end_time = time_with_rollover(year, month.index, day + 1) Span.new(start_time, end_time) rescue ArgumentError nil @@ -289,7 +289,7 @@ def handle_rdn_rmn_sd_sy(tokens, options) begin start_time = Chronic.time_class.local(year, month.index, day) - end_time = Chronic.time_class.local(year, month.index, day + 1) + end_time = time_with_rollover(year, month.index, day + 1) Span.new(start_time, end_time) rescue ArgumentError nil @@ -452,6 +452,20 @@ def find_within(tags, span, pointer) end end + def time_with_rollover(year, month, day) + date_parts = + if month_overflow?(year, month, day) + if month == 12 + [year + 1, 1, 1] + else + [year, month + 1, 1] + end + else + [year, month, day] + end + Chronic.time_class.local(*date_parts) + end + def dealias_and_disambiguate_times(tokens, options) # handle aliases of am/pm # 5:00 in the morning -> 5:00 am diff --git a/test/test_parsing.rb b/test/test_parsing.rb index 41984620..994c0314 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -926,16 +926,37 @@ def test_noon def test_handle_rdn_rmn_sd time = parse_now("Thu Aug 10") assert_equal Time.local(2006, 8, 10, 12), time + + time = parse_now("Thursday July 31") + assert_equal Time.local(2006, 7, 31, 12), time + + time = parse_now("Thursday December 31") + assert_equal Time.local(2006, 12, 31, 12), time end def test_handle_rdn_rmn_sd_sy time = parse_now("Thu Aug 10 2006") assert_equal Time.local(2006, 8, 10, 12), time + + time = parse_now("Thursday July 31 2006") + assert_equal Time.local(2006, 7, 31, 12), time + + time = parse_now("Thursday December 31 2006") + assert_equal Time.local(2006, 12, 31, 12), time + + time = parse_now("Thursday December 30 2006") + assert_equal Time.local(2006, 12, 30, 12), time end def test_handle_rdn_rmn_od time = parse_now("Thu Aug 10th") assert_equal Time.local(2006, 8, 10, 12), time + + time = parse_now("Thursday July 31st") + assert_equal Time.local(2006, 7, 31, 12), time + + time = parse_now("Thursday December 31st") + assert_equal Time.local(2006, 12, 31, 12), time end private From 6ab19c6c9a287f9b68d948fe0087687f16276be2 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 1 Feb 2012 02:23:39 +0000 Subject: [PATCH 008/184] Release 0.6.7 --- HISTORY.md | 5 +++++ lib/chronic.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 570bf2bb..f2f743d0 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +# 0.6.7 / 2012-01-31 + +* Handle day, month names with scalar day and year (Joe Fiorini) +* Ensure 31st parses correctly with day names (Joe Fiorini) + # 0.6.6 / 2011-11-23 * `Chronic.parse('thur')` no longer returns `nil` (@harold) diff --git a/lib/chronic.rb b/lib/chronic.rb index 6fdfa127..5de0478c 100644 --- a/lib/chronic.rb +++ b/lib/chronic.rb @@ -28,7 +28,7 @@ # # @author Tom Preston-Werner, Lee Jarvis module Chronic - VERSION = "0.6.6" + VERSION = "0.6.7" class << self From edcbd91514f15580ccc9ff7712a7c52f7004e0a2 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 1 Feb 2012 15:51:01 +0000 Subject: [PATCH 009/184] tomdoc lib/chronic.rb --- lib/chronic.rb | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/chronic.rb b/lib/chronic.rb index 5de0478c..63a234f5 100644 --- a/lib/chronic.rb +++ b/lib/chronic.rb @@ -1,9 +1,10 @@ require 'time' require 'date' -# Parse natural language dates and times into Time or {Chronic::Span} objects +# Parse natural language dates and times into Time or Chronic::Span objects. +# +# Examples: # -# @example # require 'chronic' # # Time.now #=> Sun Aug 27 23:18:25 PDT 2006 @@ -25,17 +26,16 @@ # # Chronic.parse('may 27th', :guess => false) # #=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007 -# -# @author Tom Preston-Werner, Lee Jarvis module Chronic VERSION = "0.6.7" class << self - # @return [Boolean] true when debug mode is enabled + # Returns true when debug mode is enabled. attr_accessor :debug - # @example + # Examples: + # # require 'chronic' # require 'active_support/time' # @@ -44,19 +44,20 @@ class << self # Chronic.parse('June 15 2006 at 5:54 AM') # # => Thu, 15 Jun 2006 05:45:00 UTC +00:00 # - # @return [Time] The time class Chronic uses internally + # Returns The Time class Chronic uses internally. attr_accessor :time_class - # The current Time Chronic is using to base from + # The current Time Chronic is using to base from. + # + # Examples: # - # @example # Time.now #=> 2011-06-06 14:13:43 +0100 # Chronic.parse('yesterday') #=> 2011-06-05 12:00:00 +0100 # # now = Time.local(2025, 12, 24) # Chronic.parse('tomorrow', :now => now) #=> 2025-12-25 12:00:00 +0000 # - # @return [Time, nil] + # Returns a Time object. attr_accessor :now end From fe1fafece59c762e23c58bfe79d7c56b7857cea5 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 1 Feb 2012 16:06:06 +0000 Subject: [PATCH 010/184] tomdoc lib/chronic/chronic.rb --- lib/chronic/chronic.rb | 122 +++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 59 deletions(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 2531d0a0..f79a9630 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -1,5 +1,6 @@ module Chronic + # Returns a Hash of default configuration options. DEFAULT_OPTIONS = { :context => :future, :now => nil, @@ -11,53 +12,43 @@ module Chronic class << self - # Parses a string containing a natural language date or time + # Parses a string containing a natural language date or time. # # If the parser can find a date or time, either a Time or Chronic::Span # will be returned (depending on the value of `:guess`). If no - # date or time can be found, `nil` will be returned + # date or time can be found, `nil` will be returned. # - # @param [String] text The text to parse + # text - The String text to parse. + # opts - An optional Hash of configuration options: + # :context - If your string represents a birthday, you can set + # this value to :past and if an ambiguous string is + # given, it will assume it is in the past. + # :now - Time, all computations will be based off of time + # instead of Time.now. + # :guess - By default the parser will guess a single point in time + # for the given date or time. If you'd rather have the + # entire time span returned, set this to false + # and a Chronic::Span will be returned. + # :ambiguous_time_range - If an Integer is given, ambiguous times + # (like 5:00) will be assumed to be within the range of + # that time in the AM to that time in the PM. For + # example, if you set it to `7`, then the parser will + # look for the time between 7am and 7pm. In the case of + # 5:00, it would assume that means 5:00pm. If `:none` + # is given, no assumption will be made, and the first + # matching instance of that time will be used. + # :endian_precedence - By default, Chronic will parse "03/04/2011" + # as the fourth day of the third month. Alternatively you + # can tell Chronic to parse this as the third day of the + # fourth month by setting this to [:little, :middle]. + # :ambiguous_year_future_bias - When parsing two digit years + # (ie 79) unlike Rubys Time class, Chronic will attempt + # to assume the full year using this figure. Chronic will + # 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. # - # @option opts [Symbol] :context (:future) - # * If your string represents a birthday, you can set `:context` to - # `:past` and if an ambiguous string is given, it will assume it is - # in the past. Specify `:future` or omit to set a future context. - # - # @option opts [Object] :now (Time.now) - # * By setting `:now` to a Time, all computations will be based off of - # that time instead of `Time.now`. If set to nil, Chronic will use - # `Time.now` - # - # @option opts [Boolean] :guess (true) - # * By default, the parser will guess a single point in time for the - # given date or time. If you'd rather have the entire time span - # returned, set `:guess` to `false` and a {Chronic::Span} will - # be returned - # - # @option opts [Integer] :ambiguous_time_range (6) - # * If an Integer is given, ambiguous times (like 5:00) will be - # assumed to be within the range of that time in the AM to that time - # in the PM. For example, if you set it to `7`, then the parser - # will look for the time between 7am and 7pm. In the case of 5:00, it - # would assume that means 5:00pm. If `:none` is given, no - # assumption will be made, and the first matching instance of that - # time will be used - # - # @option opts [Array] :endian_precedence ([:middle, :little]) - # * By default, Chronic will parse "03/04/2011" as the fourth day - # of the third month. Alternatively you can tell Chronic to parse - # this as the third day of the fourth month by altering the - # `:endian_precedence` to `[:little, :middle]` - # - # @option opts [Integer] :ambiguous_year_future_bias (50) - # * When parsing two digit years (ie 79) unlike Rubys Time class, - # Chronic will attempt to assume the full year using this figure. - # Chronic will 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 - # - # @return [Time, Chronic::Span, nil] + # Returns a new Time object, or Chronic::Span if :guess option is false. def parse(text, opts={}) options = DEFAULT_OPTIONS.merge opts @@ -87,14 +78,17 @@ def parse(text, opts={}) end end - # Clean up the specified text ready for parsing + # Clean up the specified text ready for parsing. # # Clean up the string by stripping unwanted characters, converting # idioms to their canonical form, converting number words to numbers # (three => 3), and converting ordinal words to numeric # ordinals (third => 3rd) # - # @example + # text - The String text to normalize. + # + # Examples: + # # Chronic.pre_normalize('first day in May') # #=> "1st day in may" # @@ -104,8 +98,7 @@ def parse(text, opts={}) # Chronic.pre_normalize('one hundred and thirty six days from now') # #=> "136 days future this second" # - # @param [String] text The string to normalize - # @return [String] A new string ready for Chronic to parse + # Returns a new String ready for Chronic to parse. def pre_normalize(text) text = text.to_s.downcase text.gsub!(/['"\.]/, '') @@ -132,20 +125,21 @@ def pre_normalize(text) text end - # Convert number words to numbers (three => 3, fourth => 4th) + # Convert number words to numbers (three => 3, fourth => 4th). + # + # text - The String to convert. # - # @see Numerizer.numerize - # @param [String] text The string to convert - # @return [String] A new string with words converted to numbers + # Returns a new String with words converted to numbers. def numericize_numbers(text) warn "Chronic.numericize_numbers will be deprecated in version 0.7.0. Please use Chronic::Numerizer.numerize instead" Numerizer.numerize(text) end - # Guess a specific time within the given span + # Guess a specific time within the given span. # - # @param [Span] span - # @return [Time] + # span - The Chronic::Span object to calcuate a guess from. + # + # Returns a new Time object. def guess(span) if span.width > 1 span.begin + (span.width / 2) @@ -154,11 +148,13 @@ def guess(span) end end - # List of {Handler} definitions. See {parse} for a list of options this - # method accepts + # List of Handler definitions. See #parse for a list of options this + # method accepts. + # + # options - An optional Hash of configuration options: + # :endian_precedence - # - # @see parse - # @return [Hash] A Hash of Handler definitions + # Returns A Hash of Handler definitions. def definitions(options={}) options[:endian_precedence] ||= [:middle, :little] @@ -229,9 +225,17 @@ def definitions(options={}) @definitions end - # Construct a time Object + # Construct a new time object determining possible month overflows + # and leap years. + # + # year - Integer year. + # month - Integer month. + # day - Integer day. + # hour - Integer hour. + # minute - Integer minute. + # second - Integer second. # - # @return [Time] + # Returns a new Time object constructed from these params. def construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0) if second >= 60 minute += second / 60 From 4884a5746de91cb98441ccab6dfd14ce45e71965 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Thu, 2 Feb 2012 14:44:54 +0000 Subject: [PATCH 011/184] updated changes for #59 --- HISTORY.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index f2f743d0..8a3ccc81 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,7 @@ +# HEAD + +* Support month/day and day/month parsing (#59). + # 0.6.7 / 2012-01-31 * Handle day, month names with scalar day and year (Joe Fiorini) From 0a8193c2fcaced04ccdb8bf3dd1e4bcc2d92617f Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 8 Feb 2012 12:33:11 +0000 Subject: [PATCH 012/184] ensure periods are treated the same as colons closes #81 --- lib/chronic/chronic.rb | 3 ++- test/test_Chronic.rb | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 28e6383c..308357eb 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -101,7 +101,8 @@ def parse(text, opts={}) # Returns a new String ready for Chronic to parse. def pre_normalize(text) text = text.to_s.downcase - text.gsub!(/['"\.]/, '') + text.gsub!(/\./, ':') + text.gsub!(/['"]/, '') text.gsub!(/,/, ' ') text.gsub!(/\bsecond (of|day|month|hour|minute|second)\b/, '2nd \1') text = Numerizer.numerize(text) diff --git a/test/test_Chronic.rb b/test/test_Chronic.rb index d61f3289..99a81341 100644 --- a/test/test_Chronic.rb +++ b/test/test_Chronic.rb @@ -7,6 +7,10 @@ def setup @now = Time.local(2006, 8, 16, 14, 0, 0, 0) end + def test_pre_normalize + assert_equal Chronic.pre_normalize('12:55 pm'), Chronic.pre_normalize('12.55 pm') + end + def test_pre_normalize_numerized_string string = 'two and a half years' assert_equal Chronic::Numerizer.numerize(string), Chronic.pre_normalize(string) From 0e80065c18d1755b77a9e21eea2e94d41400ea38 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 8 Feb 2012 12:34:01 +0000 Subject: [PATCH 013/184] updated changes --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index 8a3ccc81..447dd4f9 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,6 @@ # HEAD +* Ensure periods are interpreted as colons (#81). * Support month/day and day/month parsing (#59). # 0.6.7 / 2012-01-31 From 3f1728182820e7646b4ec53483670960ca94ae28 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 8 Feb 2012 12:47:56 +0000 Subject: [PATCH 014/184] downcase test filenames --- test/{test_Chronic.rb => test_chronic.rb} | 0 test/{test_DaylightSavings.rb => test_daylight_savings.rb} | 0 test/{test_Handler.rb => test_handler.rb} | 0 test/{test_MiniDate.rb => test_mini_date.rb} | 0 test/{test_Numerizer.rb => test_numerizer.rb} | 0 test/{test_RepeaterDayName.rb => test_repeater_day_name.rb} | 0 test/{test_RepeaterFortnight.rb => test_repeater_fortnight.rb} | 0 test/{test_RepeaterHour.rb => test_repeater_hour.rb} | 0 test/{test_RepeaterMinute.rb => test_repeater_minute.rb} | 0 test/{test_RepeaterMonth.rb => test_repeater_month.rb} | 0 test/{test_RepeaterMonthName.rb => test_repeater_month_name.rb} | 0 test/{test_RepeaterSeason.rb => test_repeater_season.rb} | 0 test/{test_RepeaterTime.rb => test_repeater_time.rb} | 0 test/{test_RepeaterWeek.rb => test_repeater_week.rb} | 0 test/{test_RepeaterWeekday.rb => test_repeater_weekday.rb} | 0 test/{test_RepeaterWeekend.rb => test_repeater_weekend.rb} | 0 test/{test_RepeaterYear.rb => test_repeater_year.rb} | 0 test/{test_Span.rb => test_span.rb} | 0 test/{test_Token.rb => test_token.rb} | 0 19 files changed, 0 insertions(+), 0 deletions(-) rename test/{test_Chronic.rb => test_chronic.rb} (100%) rename test/{test_DaylightSavings.rb => test_daylight_savings.rb} (100%) rename test/{test_Handler.rb => test_handler.rb} (100%) rename test/{test_MiniDate.rb => test_mini_date.rb} (100%) rename test/{test_Numerizer.rb => test_numerizer.rb} (100%) rename test/{test_RepeaterDayName.rb => test_repeater_day_name.rb} (100%) rename test/{test_RepeaterFortnight.rb => test_repeater_fortnight.rb} (100%) rename test/{test_RepeaterHour.rb => test_repeater_hour.rb} (100%) rename test/{test_RepeaterMinute.rb => test_repeater_minute.rb} (100%) rename test/{test_RepeaterMonth.rb => test_repeater_month.rb} (100%) rename test/{test_RepeaterMonthName.rb => test_repeater_month_name.rb} (100%) rename test/{test_RepeaterSeason.rb => test_repeater_season.rb} (100%) rename test/{test_RepeaterTime.rb => test_repeater_time.rb} (100%) rename test/{test_RepeaterWeek.rb => test_repeater_week.rb} (100%) rename test/{test_RepeaterWeekday.rb => test_repeater_weekday.rb} (100%) rename test/{test_RepeaterWeekend.rb => test_repeater_weekend.rb} (100%) rename test/{test_RepeaterYear.rb => test_repeater_year.rb} (100%) rename test/{test_Span.rb => test_span.rb} (100%) rename test/{test_Token.rb => test_token.rb} (100%) diff --git a/test/test_Chronic.rb b/test/test_chronic.rb similarity index 100% rename from test/test_Chronic.rb rename to test/test_chronic.rb diff --git a/test/test_DaylightSavings.rb b/test/test_daylight_savings.rb similarity index 100% rename from test/test_DaylightSavings.rb rename to test/test_daylight_savings.rb diff --git a/test/test_Handler.rb b/test/test_handler.rb similarity index 100% rename from test/test_Handler.rb rename to test/test_handler.rb diff --git a/test/test_MiniDate.rb b/test/test_mini_date.rb similarity index 100% rename from test/test_MiniDate.rb rename to test/test_mini_date.rb diff --git a/test/test_Numerizer.rb b/test/test_numerizer.rb similarity index 100% rename from test/test_Numerizer.rb rename to test/test_numerizer.rb diff --git a/test/test_RepeaterDayName.rb b/test/test_repeater_day_name.rb similarity index 100% rename from test/test_RepeaterDayName.rb rename to test/test_repeater_day_name.rb diff --git a/test/test_RepeaterFortnight.rb b/test/test_repeater_fortnight.rb similarity index 100% rename from test/test_RepeaterFortnight.rb rename to test/test_repeater_fortnight.rb diff --git a/test/test_RepeaterHour.rb b/test/test_repeater_hour.rb similarity index 100% rename from test/test_RepeaterHour.rb rename to test/test_repeater_hour.rb diff --git a/test/test_RepeaterMinute.rb b/test/test_repeater_minute.rb similarity index 100% rename from test/test_RepeaterMinute.rb rename to test/test_repeater_minute.rb diff --git a/test/test_RepeaterMonth.rb b/test/test_repeater_month.rb similarity index 100% rename from test/test_RepeaterMonth.rb rename to test/test_repeater_month.rb diff --git a/test/test_RepeaterMonthName.rb b/test/test_repeater_month_name.rb similarity index 100% rename from test/test_RepeaterMonthName.rb rename to test/test_repeater_month_name.rb diff --git a/test/test_RepeaterSeason.rb b/test/test_repeater_season.rb similarity index 100% rename from test/test_RepeaterSeason.rb rename to test/test_repeater_season.rb diff --git a/test/test_RepeaterTime.rb b/test/test_repeater_time.rb similarity index 100% rename from test/test_RepeaterTime.rb rename to test/test_repeater_time.rb diff --git a/test/test_RepeaterWeek.rb b/test/test_repeater_week.rb similarity index 100% rename from test/test_RepeaterWeek.rb rename to test/test_repeater_week.rb diff --git a/test/test_RepeaterWeekday.rb b/test/test_repeater_weekday.rb similarity index 100% rename from test/test_RepeaterWeekday.rb rename to test/test_repeater_weekday.rb diff --git a/test/test_RepeaterWeekend.rb b/test/test_repeater_weekend.rb similarity index 100% rename from test/test_RepeaterWeekend.rb rename to test/test_repeater_weekend.rb diff --git a/test/test_RepeaterYear.rb b/test/test_repeater_year.rb similarity index 100% rename from test/test_RepeaterYear.rb rename to test/test_repeater_year.rb diff --git a/test/test_Span.rb b/test/test_span.rb similarity index 100% rename from test/test_Span.rb rename to test/test_span.rb diff --git a/test/test_Token.rb b/test/test_token.rb similarity index 100% rename from test/test_Token.rb rename to test/test_token.rb From 82863e52529c9a3475af216e1532e541680bbaea Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 8 Feb 2012 12:53:28 +0000 Subject: [PATCH 015/184] lets get with the times and start using minitest --- HISTORY.md | 1 + chronic.gemspec | 3 +++ test/helper.rb | 8 +++++++- test/test_chronic.rb | 8 ++------ test/test_daylight_savings.rb | 2 +- test/test_handler.rb | 2 +- test/test_mini_date.rb | 18 +++++++++--------- test/test_numerizer.rb | 2 +- test/test_parsing.rb | 8 ++++---- test/test_repeater_day_name.rb | 2 +- test/test_repeater_fortnight.rb | 2 +- test/test_repeater_hour.rb | 2 +- test/test_repeater_minute.rb | 2 +- test/test_repeater_month.rb | 2 +- test/test_repeater_month_name.rb | 2 +- test/test_repeater_season.rb | 2 +- test/test_repeater_time.rb | 2 +- test/test_repeater_week.rb | 2 +- test/test_repeater_weekday.rb | 2 +- test/test_repeater_weekend.rb | 2 +- test/test_repeater_year.rb | 2 +- test/test_span.rb | 2 +- test/test_token.rb | 2 +- 23 files changed, 43 insertions(+), 37 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 447dd4f9..645cd839 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,6 @@ # HEAD +* Start using minitest for testing * Ensure periods are interpreted as colons (#81). * Support month/day and day/month parsing (#59). diff --git a/chronic.gemspec b/chronic.gemspec index 84a007b6..7d7cd4ec 100644 --- a/chronic.gemspec +++ b/chronic.gemspec @@ -14,4 +14,7 @@ Gem::Specification.new do |s| s.extra_rdoc_files = %w[README.md HISTORY.md LICENSE] s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- test`.split("\n") + + s.add_development_dependency 'rake' + s.add_development_dependency 'minitest' end \ No newline at end of file diff --git a/test/helper.rb b/test/helper.rb index 30b5c1f2..3adc2923 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -3,4 +3,10 @@ require 'chronic' end -require 'test/unit' \ No newline at end of file +require 'minitest/autorun' + +class TestCase < MiniTest::Unit::TestCase + def self.test(name, &block) + define_method("test_#{name.gsub(/\W/, '_')}", &block) if block + end +end \ No newline at end of file diff --git a/test/test_chronic.rb b/test/test_chronic.rb index 99a81341..ab4c81bb 100644 --- a/test/test_chronic.rb +++ b/test/test_chronic.rb @@ -1,6 +1,6 @@ require 'helper' -class TestChronic < Test::Unit::TestCase +class TestChronic < TestCase def setup # Wed Aug 16 14:00:00 UTC 2006 @@ -135,11 +135,7 @@ def test_day_overflow assert_equal Time.local(2004, 3, 4), Chronic.construct(2004, 2, 33) assert_equal Time.local(2000, 3, 4), Chronic.construct(2000, 2, 33) - assert_nothing_raised do - Chronic.construct(2006, 1, 56) - end - - assert_raise(RuntimeError) do + assert_raises(RuntimeError) do Chronic.construct(2006, 1, 57) end end diff --git a/test/test_daylight_savings.rb b/test/test_daylight_savings.rb index fc58ba97..d6f303fb 100644 --- a/test/test_daylight_savings.rb +++ b/test/test_daylight_savings.rb @@ -1,6 +1,6 @@ require 'helper' -class TestDaylightSavings < Test::Unit::TestCase +class TestDaylightSavings < TestCase def setup @begin_daylight_savings = Time.local(2008, 3, 9, 5, 0, 0, 0) diff --git a/test/test_handler.rb b/test/test_handler.rb index 22b4a3ba..1bf3c0d7 100644 --- a/test/test_handler.rb +++ b/test/test_handler.rb @@ -1,6 +1,6 @@ require 'helper' -class TestHandler < Test::Unit::TestCase +class TestHandler < TestCase def setup # Wed Aug 16 14:00:00 UTC 2006 diff --git a/test/test_mini_date.rb b/test/test_mini_date.rb index 0710568f..3ae441d5 100644 --- a/test/test_mini_date.rb +++ b/test/test_mini_date.rb @@ -1,32 +1,32 @@ require 'helper' -class TestMiniDate < Test::Unit::TestCase +class TestMiniDate < TestCase def test_valid_month - assert_raise(ArgumentError){ Chronic::MiniDate.new(0,12) } - assert_raise(ArgumentError){ Chronic::MiniDate.new(13,1) } + assert_raises(ArgumentError){ Chronic::MiniDate.new(0,12) } + assert_raises(ArgumentError){ Chronic::MiniDate.new(13,1) } end - + def test_is_between m=Chronic::MiniDate.new(3,2) assert m.is_between?(Chronic::MiniDate.new(2,4), Chronic::MiniDate.new(4,7)) - assert !m.is_between?(Chronic::MiniDate.new(1,5), Chronic::MiniDate.new(2,7)) - + assert !m.is_between?(Chronic::MiniDate.new(1,5), Chronic::MiniDate.new(2,7)) + #There was a hang if date tested is in december and outside the testing range m=Chronic::MiniDate.new(12,24) assert !m.is_between?(Chronic::MiniDate.new(10,1), Chronic::MiniDate.new(12,21)) end - + def test_is_between_short_range m=Chronic::MiniDate.new(5,10) assert m.is_between?(Chronic::MiniDate.new(5,3), Chronic::MiniDate.new(5,12)) assert !m.is_between?(Chronic::MiniDate.new(5,11), Chronic::MiniDate.new(5,15)) end - + def test_is_between_wrapping_range m=Chronic::MiniDate.new(1,1) assert m.is_between?(Chronic::MiniDate.new(11,11), Chronic::MiniDate.new(2,2)) m=Chronic::MiniDate.new(12,12) assert m.is_between?(Chronic::MiniDate.new(11,11), Chronic::MiniDate.new(1,5)) end - + end diff --git a/test/test_numerizer.rb b/test/test_numerizer.rb index 9f6b1e99..d958c0f2 100644 --- a/test/test_numerizer.rb +++ b/test/test_numerizer.rb @@ -1,6 +1,6 @@ require 'helper' -class ParseNumbersTest < Test::Unit::TestCase +class ParseNumbersTest < TestCase def test_straight_parsing strings = { diff --git a/test/test_parsing.rb b/test/test_parsing.rb index 7b50abd6..958f3655 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -1,6 +1,6 @@ require 'helper' -class TestParsing < Test::Unit::TestCase +class TestParsing < TestCase # Wed Aug 16 14:00:00 UTC 2006 TIME_2006_08_16_14_00_00 = Time.local(2006, 8, 16, 14, 0, 0, 0) @@ -866,11 +866,11 @@ def test_a_p end def test_argument_validation - assert_raise(ArgumentError) do + assert_raises(ArgumentError) do time = Chronic.parse("may 27", :foo => :bar) end - assert_raise(ArgumentError) do + assert_raises(ArgumentError) do time = Chronic.parse("may 27", :context => :bar) end end @@ -926,7 +926,7 @@ def test_now_changes t1 = Chronic.parse("now") sleep 0.1 t2 = Chronic.parse("now") - assert_not_equal t1, t2 + refute_equal t1, t2 end def test_noon diff --git a/test/test_repeater_day_name.rb b/test/test_repeater_day_name.rb index 21562a2c..7fa7f0da 100644 --- a/test/test_repeater_day_name.rb +++ b/test/test_repeater_day_name.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterDayName < Test::Unit::TestCase +class TestRepeaterDayName < TestCase def setup @now = Time.local(2006, 8, 16, 14, 0, 0, 0) diff --git a/test/test_repeater_fortnight.rb b/test/test_repeater_fortnight.rb index 6df9b72f..d1fb0cf5 100644 --- a/test/test_repeater_fortnight.rb +++ b/test/test_repeater_fortnight.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterFortnight < Test::Unit::TestCase +class TestRepeaterFortnight < TestCase def setup @now = Time.local(2006, 8, 16, 14, 0, 0, 0) diff --git a/test/test_repeater_hour.rb b/test/test_repeater_hour.rb index 27ede67e..d729e5ce 100644 --- a/test/test_repeater_hour.rb +++ b/test/test_repeater_hour.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterHour < Test::Unit::TestCase +class TestRepeaterHour < TestCase def setup @now = Time.local(2006, 8, 16, 14, 0, 0, 0) diff --git a/test/test_repeater_minute.rb b/test/test_repeater_minute.rb index 95408385..a04f8b0e 100644 --- a/test/test_repeater_minute.rb +++ b/test/test_repeater_minute.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterMinute < Test::Unit::TestCase +class TestRepeaterMinute < TestCase def setup @now = Time.local(2008, 6, 25, 7, 15, 30, 0) diff --git a/test/test_repeater_month.rb b/test/test_repeater_month.rb index b05ac310..73f3dfc9 100644 --- a/test/test_repeater_month.rb +++ b/test/test_repeater_month.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterMonth < Test::Unit::TestCase +class TestRepeaterMonth < TestCase def setup # Wed Aug 16 14:00:00 2006 diff --git a/test/test_repeater_month_name.rb b/test/test_repeater_month_name.rb index 36a3e65e..45a7c8c4 100644 --- a/test/test_repeater_month_name.rb +++ b/test/test_repeater_month_name.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterMonthName < Test::Unit::TestCase +class TestRepeaterMonthName < TestCase def setup # Wed Aug 16 14:00:00 2006 diff --git a/test/test_repeater_season.rb b/test/test_repeater_season.rb index 20838942..e76fa72c 100644 --- a/test/test_repeater_season.rb +++ b/test/test_repeater_season.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterSeason < Test::Unit::TestCase +class TestRepeaterSeason < TestCase def setup @now = Time.local(2006, 8, 16, 14, 0, 0, 0) diff --git a/test/test_repeater_time.rb b/test/test_repeater_time.rb index 5572c930..b1a0be3f 100644 --- a/test/test_repeater_time.rb +++ b/test/test_repeater_time.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterTime < Test::Unit::TestCase +class TestRepeaterTime < TestCase def setup # Wed Aug 16 14:00:00 2006 diff --git a/test/test_repeater_week.rb b/test/test_repeater_week.rb index b69f0479..ed1ec284 100644 --- a/test/test_repeater_week.rb +++ b/test/test_repeater_week.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterWeek < Test::Unit::TestCase +class TestRepeaterWeek < TestCase def setup @now = Time.local(2006, 8, 16, 14, 0, 0, 0) diff --git a/test/test_repeater_weekday.rb b/test/test_repeater_weekday.rb index 8f2f5b3e..af981256 100644 --- a/test/test_repeater_weekday.rb +++ b/test/test_repeater_weekday.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterWeekday < Test::Unit::TestCase +class TestRepeaterWeekday < TestCase def setup @now = Time.local(2007, 6, 11, 14, 0, 0, 0) # Mon diff --git a/test/test_repeater_weekend.rb b/test/test_repeater_weekend.rb index c0d471ad..8727c5de 100644 --- a/test/test_repeater_weekend.rb +++ b/test/test_repeater_weekend.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterWeekend < Test::Unit::TestCase +class TestRepeaterWeekend < TestCase def setup # Wed Aug 16 14:00:00 2006 diff --git a/test/test_repeater_year.rb b/test/test_repeater_year.rb index 9cef1701..916ef04c 100644 --- a/test/test_repeater_year.rb +++ b/test/test_repeater_year.rb @@ -1,6 +1,6 @@ require 'helper' -class TestRepeaterYear < Test::Unit::TestCase +class TestRepeaterYear < TestCase def setup @now = Time.local(2006, 8, 16, 14, 0, 0, 0) diff --git a/test/test_span.rb b/test/test_span.rb index 0271233a..fe522932 100644 --- a/test/test_span.rb +++ b/test/test_span.rb @@ -1,6 +1,6 @@ require 'helper' -class TestSpan < Test::Unit::TestCase +class TestSpan < TestCase def setup # Wed Aug 16 14:00:00 UTC 2006 diff --git a/test/test_token.rb b/test/test_token.rb index 78802d1b..43300294 100644 --- a/test/test_token.rb +++ b/test/test_token.rb @@ -1,6 +1,6 @@ require 'helper' -class TestToken < Test::Unit::TestCase +class TestToken < TestCase def setup # Wed Aug 16 14:00:00 UTC 2006 From 6a36a376717dda5d767c248de0494553a9432036 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 8 Feb 2012 13:58:22 +0000 Subject: [PATCH 016/184] remove .gemtest --- .gemtest | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .gemtest diff --git a/.gemtest b/.gemtest deleted file mode 100644 index e69de29b..00000000 From 98429ff1dfd6ea758f946fcd5eb8e4726282b303 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 8 Feb 2012 13:58:30 +0000 Subject: [PATCH 017/184] remove .yardopts --- .yardopts | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .yardopts diff --git a/.yardopts b/.yardopts deleted file mode 100644 index 6a5ddf21..00000000 --- a/.yardopts +++ /dev/null @@ -1,3 +0,0 @@ --m markdown ---readme README.md ---title "Chronic - Natural language date/time parsing" From f5a247025ab02ced1fd5fbb8d779b34a1fe43331 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 8 Feb 2012 14:13:03 +0000 Subject: [PATCH 018/184] tomdoc all the things \o/ --- lib/chronic/grabber.rb | 16 ++++++------ lib/chronic/handler.rb | 22 ++++++++--------- lib/chronic/ordinal.rb | 21 +++++++++------- lib/chronic/pointer.rb | 16 ++++++------ lib/chronic/repeater.rb | 41 ++++++++++++++++++------------- lib/chronic/scalar.rb | 53 +++++++++++++++++++++++----------------- lib/chronic/season.rb | 13 +--------- lib/chronic/separator.rb | 36 +++++++++++++++------------ lib/chronic/tag.rb | 16 ++++-------- lib/chronic/time_zone.rb | 16 ++++++------ lib/chronic/token.rb | 22 +++++++++-------- 11 files changed, 142 insertions(+), 130 deletions(-) diff --git a/lib/chronic/grabber.rb b/lib/chronic/grabber.rb index 1a7ab9b8..b6ced8fa 100644 --- a/lib/chronic/grabber.rb +++ b/lib/chronic/grabber.rb @@ -1,20 +1,22 @@ module Chronic class Grabber < Tag - # Scan an Array of {Token}s and apply any necessary Grabber tags to - # each token + # Scan an Array of Tokens and apply any necessary Grabber tags to + # each token. # - # @param [Array] tokens Array of tokens to scan - # @param [Hash] options Options specified in {Chronic.parse} - # @return [Array] list of tokens + # tokens - An Array of Token objects to scan. + # options - The Hash of options specified in Chronic::parse. + # + # Returns an Array of Token objects. def self.scan(tokens, options) tokens.each do |token| if t = scan_for_all(token) then token.tag(t); next end end end - # @param [Token] token - # @return [Grabber, nil] + # token - The Token object to scan. + # + # Returns a new Grabber object. def self.scan_for_all(token) scan_for token, self, { diff --git a/lib/chronic/handler.rb b/lib/chronic/handler.rb index da9a0ed8..12f1195e 100644 --- a/lib/chronic/handler.rb +++ b/lib/chronic/handler.rb @@ -1,25 +1,22 @@ module Chronic class Handler - # @return [Array] A list of patterns attr_reader :pattern - # @return [Symbol] The method which handles this list of patterns. - # This method should exist inside the {Handlers} module attr_reader :handler_method - # @param [Array] pattern A list of patterns to match tokens against - # @param [Symbol] handler_method The method to be invoked when patterns - # are matched. This method should exist inside the {Handlers} module + # pattern - An Array of patterns to match tokens against. + # handler_method - A Symbole representing the method to be invoked + # when patterns are matched. def initialize(pattern, handler_method) @pattern = pattern @handler_method = handler_method end - # @param [Array] tokens - # @param [Hash] definitions - # @return [Boolean] - # @see Chronic.tokens_to_span + # tokens - An Array of tokens to process. + # definitions - A Hash of definitions to check against. + # + # Returns true if a match is found. def match(tokens, definitions) token_index = 0 @@ -70,8 +67,9 @@ def invoke(type, tokens, options) Handlers.send(@handler_method, tokens, options) end - # @param [Handler] The handler to compare - # @return [Boolean] True if these handlers match + # other - The other Handler object to compare. + # + # Returns true if these Handlers match. def ==(other) @pattern == other.pattern end diff --git a/lib/chronic/ordinal.rb b/lib/chronic/ordinal.rb index 3645aa2b..267ba5b0 100644 --- a/lib/chronic/ordinal.rb +++ b/lib/chronic/ordinal.rb @@ -1,12 +1,13 @@ module Chronic class Ordinal < Tag - # Scan an Array of {Token}s and apply any necessary Ordinal tags to - # each token + # Scan an Array of Token objects and apply any necessary Ordinal + # tags to each token. # - # @param [Array] tokens Array of tokens to scan - # @param [Hash] options Options specified in {Chronic.parse} - # @return [Array] list of tokens + # tokens - An Array of tokens to scan. + # options - The Hash of options specified in Chronic::parse. + # + # Returns an Array of tokens. def self.scan(tokens, options) tokens.each do |token| if t = scan_for_ordinals(token) then token.tag(t) end @@ -14,14 +15,16 @@ def self.scan(tokens, options) end end - # @param [Token] token - # @return [Ordinal, nil] + # token - The Token object we want to scan. + # + # Returns a new Ordinal object. def self.scan_for_ordinals(token) Ordinal.new($1.to_i) if token.word =~ /^(\d*)(st|nd|rd|th)$/ end - # @param [Token] token - # @return [OrdinalDay, nil] + # token - The Token object we want to scan. + # + # Returns a new Ordinal object. def self.scan_for_days(token) if token.word =~ /^(\d*)(st|nd|rd|th)$/ unless $1.to_i > 31 || $1.to_i < 1 diff --git a/lib/chronic/pointer.rb b/lib/chronic/pointer.rb index 0ae8e223..50f4abf4 100644 --- a/lib/chronic/pointer.rb +++ b/lib/chronic/pointer.rb @@ -1,20 +1,22 @@ module Chronic class Pointer < Tag - # Scan an Array of {Token}s and apply any necessary Pointer tags to - # each token + # Scan an Array of Token objects and apply any necessary Pointer + # tags to each token. # - # @param [Array] tokens Array of tokens to scan - # @param [Hash] options Options specified in {Chronic.parse} - # @return [Array] list of tokens + # tokens - An Array of tokens to scan. + # options - The Hash of options specified in Chronic::parse. + # + # Returns an Array of tokens. def self.scan(tokens, options) tokens.each do |token| if t = scan_for_all(token) then token.tag(t) end end end - # @param [Token] token - # @return [Pointer, nil] + # token - The Token object we want to scan. + # + # Returns a new Pointer object. def self.scan_for_all(token) scan_for token, self, { diff --git a/lib/chronic/repeater.rb b/lib/chronic/repeater.rb index ba3fe9cd..2daf1368 100644 --- a/lib/chronic/repeater.rb +++ b/lib/chronic/repeater.rb @@ -1,12 +1,13 @@ module Chronic class Repeater < Tag - # Scan an Array of {Token}s and apply any necessary Repeater tags to - # each token + # Scan an Array of Token objects and apply any necessary Repeater + # tags to each token. # - # @param [Array] tokens Array of tokens to scan - # @param [Hash] options Options specified in {Chronic.parse} - # @return [Array] list of tokens + # tokens - An Array of tokens to scan. + # options - The Hash of options specified in Chronic::parse. + # + # Returns an Array of tokens. def self.scan(tokens, options) tokens.each do |token| if t = scan_for_season_names(token) then token.tag(t); next end @@ -18,8 +19,9 @@ def self.scan(tokens, options) end end - # @param [Token] token - # @return [RepeaterSeasonName, nil] + # token - The Token object we want to scan. + # + # Returns a new Repeater object. def self.scan_for_season_names(token) scan_for token, RepeaterSeasonName, { @@ -30,8 +32,9 @@ def self.scan_for_season_names(token) } end - # @param [Token] token - # @return [RepeaterMonthName, nil] + # token - The Token object we want to scan. + # + # Returns a new Repeater object. def self.scan_for_month_names(token) scan_for token, RepeaterMonthName, { @@ -50,8 +53,9 @@ def self.scan_for_month_names(token) } end - # @param [Token] token - # @return [RepeaterDayName, nil] + # token - The Token object we want to scan. + # + # Returns a new Repeater object. def self.scan_for_day_names(token) scan_for token, RepeaterDayName, { @@ -65,8 +69,9 @@ def self.scan_for_day_names(token) } end - # @param [Token] token - # @return [RepeaterDayPortion, nil] + # token - The Token object we want to scan. + # + # Returns a new Repeater object. def self.scan_for_day_portions(token) scan_for token, RepeaterDayPortion, { @@ -79,14 +84,16 @@ def self.scan_for_day_portions(token) } end - # @param [Token] token - # @return [RepeaterTime, nil] + # token - The Token object we want to scan. + # + # Returns a new Repeater object. def self.scan_for_times(token) scan_for token, RepeaterTime, /^\d{1,2}(:?\d{2})?([\.:]?\d{2})?$/ end - # @param [Token] token - # @return [Repeater] A new instance of a subclass of Repeater + # token - The Token object we want to scan. + # + # Returns a new Repeater object. def self.scan_for_units(token) { /^years?$/ => :year, diff --git a/lib/chronic/scalar.rb b/lib/chronic/scalar.rb index 09e3e40a..4f50d421 100644 --- a/lib/chronic/scalar.rb +++ b/lib/chronic/scalar.rb @@ -2,12 +2,13 @@ module Chronic class Scalar < Tag DAY_PORTIONS = %w( am pm morning afternoon evening night ) - # Scan an Array of {Token}s and apply any necessary Scalar tags to - # each token + # Scan an Array of Token objects and apply any necessary Scalar + # tags to each token. # - # @param [Array] tokens Array of tokens to scan - # @param [Hash] options Options specified in {Chronic.parse} - # @return [Array] list of tokens + # tokens - An Array of tokens to scan. + # options - The Hash of options specified in Chronic::parse. + # + # Returns an Array of tokens. def self.scan(tokens, options) tokens.each_index do |i| if t = scan_for_scalars(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end @@ -17,9 +18,10 @@ def self.scan(tokens, options) end end - # @param [Token] token - # @param [Token] post_token - # @return [Scalar, nil] + # token - The Token object we want to scan. + # post_token - The next Token object. + # + # Returns a new Scalar object. def self.scan_for_scalars(token, post_token) if token.word =~ /^\d*$/ unless post_token && DAY_PORTIONS.include?(post_token.word) @@ -28,9 +30,10 @@ def self.scan_for_scalars(token, post_token) end end - # @param [Token] token - # @param [Token] post_token - # @return [ScalarDay, nil] + # token - The Token object we want to scan. + # post_token - The next Token object. + # + # Returns a new Scalar object. def self.scan_for_days(token, post_token) if token.word =~ /^\d\d?$/ toi = token.word.to_i @@ -40,9 +43,10 @@ def self.scan_for_days(token, post_token) end end - # @param [Token] token - # @param [Token] post_token - # @return [ScalarMonth, nil] + # token - The Token object we want to scan. + # post_token - The next Token object. + # + # Returns a new Scalar object. def self.scan_for_months(token, post_token) if token.word =~ /^\d\d?$/ toi = token.word.to_i @@ -52,10 +56,11 @@ def self.scan_for_months(token, post_token) end end - # @param [Token] token - # @param [Token] post_token - # @param [Hash] options Options specified in {Chronic.parse} - # @return [ScalarYear, nil] + # token - The Token object we want to scan. + # post_token - The next Token object. + # options - The Hash of options specified in Chronic::parse. + # + # Returns a new Scalar object. def self.scan_for_years(token, post_token, options) if token.word =~ /^([1-9]\d)?\d\d?$/ unless post_token && DAY_PORTIONS.include?(post_token.word) @@ -65,16 +70,18 @@ def self.scan_for_years(token, post_token, options) end end - # Build a year from a 2 digit suffix + # Build a year from a 2 digit suffix. + # + # year - The two digit Integer year to build from. + # bias - The Integer amount of future years to bias. + # + # Examples: # - # @example # make_year(96, 50) #=> 1996 # make_year(79, 20) #=> 2079 # make_year(00, 50) #=> 2000 # - # @param [Integer] year The two digit year to build from - # @param [Integer] bias The amount of future years to bias - # @return [Integer] The 4 digit year + # Returns The Integer 4 digit year. def self.make_year(year, bias) return year if year.to_s.size > 2 start_year = Chronic.time_class.now.year - bias diff --git a/lib/chronic/season.rb b/lib/chronic/season.rb index 478163f0..43937a8b 100644 --- a/lib/chronic/season.rb +++ b/lib/chronic/season.rb @@ -1,35 +1,24 @@ module Chronic class Season - # @return [MiniDate] - attr_reader :start - # @return [MiniDate] + attr_reader :start attr_reader :end - # @param [MiniDate] start_date - # @param [MiniDate] end_date def initialize(start_date, end_date) @start = start_date @end = end_date end - # @param [Symbol] season The season name - # @param [Integer] pointer The direction (-1 for past, 1 for future) - # @return [Symbol] The new season name def self.find_next_season(season, pointer) lookup = [:spring, :summer, :autumn, :winter] next_season_num = (lookup.index(season) + 1 * pointer) % 4 lookup[next_season_num] end - # @param [Symbol] season The season name - # @return [Symbol] The new season name def self.season_after(season) find_next_season(season, +1) end - # @param [Symbol] season The season name - # @return [Symbol] The new season name def self.season_before(season) find_next_season(season, -1) end diff --git a/lib/chronic/separator.rb b/lib/chronic/separator.rb index a67f6fae..40fce976 100644 --- a/lib/chronic/separator.rb +++ b/lib/chronic/separator.rb @@ -1,12 +1,13 @@ module Chronic class Separator < Tag - # Scan an Array of {Token}s and apply any necessary Separator tags to - # each token + # Scan an Array of Token objects and apply any necessary Separator + # tags to each token. # - # @param [Array] tokens Array of tokens to scan - # @param [Hash] options Options specified in {Chronic.parse} - # @return [Array] list of tokens + # tokens - An Array of tokens to scan. + # options - The Hash of options specified in Chronic::parse. + # + # Returns an Array of tokens. def self.scan(tokens, options) tokens.each do |token| if t = scan_for_commas(token) then token.tag(t); next end @@ -17,14 +18,16 @@ def self.scan(tokens, options) end end - # @param [Token] token - # @return [SeparatorComma, nil] + # token - The Token object we want to scan. + # + # Returns a new SeparatorComma object. def self.scan_for_commas(token) scan_for token, SeparatorComma, { /^,$/ => :comma } end - # @param [Token] token - # @return [SeparatorSlashOrDash, nil] + # token - The Token object we want to scan. + # + # Returns a new SeparatorSlashOrDash object. def self.scan_for_slash_or_dash(token) scan_for token, SeparatorSlashOrDash, { @@ -33,20 +36,23 @@ def self.scan_for_slash_or_dash(token) } end - # @param [Token] token - # @return [SeparatorAt, nil] + # token - The Token object we want to scan. + # + # Returns a new SeparatorAt object. def self.scan_for_at(token) scan_for token, SeparatorAt, { /^(at|@)$/ => :at } end - # @param [Token] token - # @return [SeparatorIn, nil] + # token - The Token object we want to scan. + # + # Returns a new SeparatorIn object. def self.scan_for_in(token) scan_for token, SeparatorIn, { /^in$/ => :in } end - # @param [Token] token - # @return [SeparatorOn, nil] + # token - The Token object we want to scan. + # + # Returns a new SeparatorOn object. def self.scan_for_on(token) scan_for token, SeparatorOn, { /^on$/ => :on } end diff --git a/lib/chronic/tag.rb b/lib/chronic/tag.rb index 9dcb3efa..89e4513f 100644 --- a/lib/chronic/tag.rb +++ b/lib/chronic/tag.rb @@ -1,29 +1,23 @@ module Chronic # Tokens are tagged with subclassed instances of this class when - # they match specific criteria + # they match specific criteria. class Tag - # @return [Symbol] attr_accessor :type - # @param [Symbol] type + # type - The Symbol type of this tag. def initialize(type) @type = type end - # @param [Time] s Set the start timestamp for this Tag - def start=(s) - @now = s + # time - Set the start Time for this Tag. + def start=(time) + @now = time end class << self private - # @param [Token] token - # @param [Class] klass The class instance to create - # @param [Regexp, Hash] items - # @return [Object, nil] either a new instance of `klass` or `nil` if - # no match is found def scan_for(token, klass, items={}) case items when Regexp diff --git a/lib/chronic/time_zone.rb b/lib/chronic/time_zone.rb index 5624dfcd..58ce02a4 100644 --- a/lib/chronic/time_zone.rb +++ b/lib/chronic/time_zone.rb @@ -1,20 +1,22 @@ module Chronic class TimeZone < Tag - # Scan an Array of {Token}s and apply any necessary TimeZone tags to - # each token + # Scan an Array of Token objects and apply any necessary TimeZone + # tags to each token. # - # @param [Array] tokens Array of tokens to scan - # @param [Hash] options Options specified in {Chronic.parse} - # @return [Array] list of tokens + # tokens - An Array of tokens to scan. + # options - The Hash of options specified in Chronic::parse. + # + # Returns an Array of tokens. def self.scan(tokens, options) tokens.each do |token| if t = scan_for_all(token) then token.tag(t); next end end end - # @param [Token] token - # @return [TimeZone, nil] + # token - The Token object we want to scan. + # + # Returns a new Pointer object. def self.scan_for_all(token) scan_for token, self, { diff --git a/lib/chronic/token.rb b/lib/chronic/token.rb index 6faac34e..e3a83832 100644 --- a/lib/chronic/token.rb +++ b/lib/chronic/token.rb @@ -1,10 +1,7 @@ module Chronic class Token - # @return [String] The word this Token represents attr_accessor :word - - # @return [Array] A list of tag associated with this Token attr_accessor :tags def initialize(word) @@ -12,27 +9,32 @@ def initialize(word) @tags = [] end - # Tag this token with the specified tag + # Tag this token with the specified tag. + # + # new_tag - The new Tag object. # - # @param [Tag] new_tag An instance of {Tag} or one of its subclasses + # Returns nothing. def tag(new_tag) @tags << new_tag end - # Remove all tags of the given class + # Remove all tags of the given class. # - # @param [Class] The tag class to remove + # tag_class - The tag Class to remove. + # + # Returns nothing. def untag(tag_class) @tags.delete_if { |m| m.kind_of? tag_class } end - # @return [Boolean] true if this token has any tags + # Returns true if this token has any tags. def tagged? @tags.size > 0 end - # @param [Class] tag_class The tag class to search for - # @return [Tag] The first Tag that matches the given class + # tag_class - The tag Class to search for. + # + # Returns The first Tag that matches the given class. def get_tag(tag_class) @tags.find { |m| m.kind_of? tag_class } end From 4aba0192b68f85bc31c3796c40c591d164467c6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ce=CC=81dric=20FABIANSKI?= Date: Fri, 6 Apr 2012 15:10:44 +0200 Subject: [PATCH 019/184] Update README for endian_precedence options --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index acfa8ce4..381eab34 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,10 @@ You can parse strings containing a natural language date using the Chronic.parse('may 27th', :guess => false) #=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007 + + Chronic.parse('6/4/2012', :endian_precedence => :little) + #=> Fri Apr 06 00:00:00 PDT 2012 + See `Chronic.parse` for detailed usage instructions. From 3f3c51a42e23c1f9721bd23c77dddddf904778c5 Mon Sep 17 00:00:00 2001 From: AnoHito Date: Fri, 20 Apr 2012 02:00:07 -0500 Subject: [PATCH 020/184] add autoload support --- lib/chronic.rb | 71 +++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/lib/chronic.rb b/lib/chronic.rb index 63a234f5..530e88aa 100644 --- a/lib/chronic.rb +++ b/lib/chronic.rb @@ -63,43 +63,47 @@ class << self self.debug = false self.time_class = Time + + autoload :Handler, 'chronic/handler' + autoload :Handlers, 'chronic/handlers' + autoload :MiniDate, 'chronic/mini_date' + autoload :Tag, 'chronic/tag' + autoload :Span, 'chronic/span' + autoload :Token, 'chronic/token' + autoload :Grabber, 'chronic/grabber' + autoload :Pointer, 'chronic/pointer' + autoload :Scalar, 'chronic/scalar' + autoload :Ordinal, 'chronic/ordinal' + autoload :OrdinalDay, 'chronic/ordinal' + autoload :Separator, 'chronic/separator' + autoload :TimeZone, 'chronic/time_zone' + autoload :Numerizer, 'chronic/numerizer' + autoload :Season, 'chronic/season' + + autoload :Repeater, 'chronic/repeater' + autoload :RepeaterYear, 'chronic/repeaters/repeater_year' + autoload :RepeaterSeason, 'chronic/repeaters/repeater_season' + autoload :RepeaterSeasonName, 'chronic/repeaters/repeater_season_name' + autoload :RepeaterMonth, 'chronic/repeaters/repeater_month' + autoload :RepeaterMonthName, 'chronic/repeaters/repeater_month_name' + autoload :RepeaterFortnight, 'chronic/repeaters/repeater_fortnight' + autoload :RepeaterWeek, 'chronic/repeaters/repeater_week' + autoload :RepeaterWeekend, 'chronic/repeaters/repeater_weekend' + autoload :RepeaterWeekday, 'chronic/repeaters/repeater_weekday' + autoload :RepeaterDay, 'chronic/repeaters/repeater_day' + autoload :RepeaterDayName, 'chronic/repeaters/repeater_day_name' + autoload :RepeaterDayPortion, 'chronic/repeaters/repeater_day_portion' + autoload :RepeaterHour, 'chronic/repeaters/repeater_hour' + autoload :RepeaterMinute, 'chronic/repeaters/repeater_minute' + autoload :RepeaterSecond, 'chronic/repeaters/repeater_second' + autoload :RepeaterTime, 'chronic/repeaters/repeater_time' + end -require 'chronic/chronic' -require 'chronic/handler' -require 'chronic/handlers' -require 'chronic/mini_date' -require 'chronic/tag' -require 'chronic/span' -require 'chronic/token' -require 'chronic/grabber' -require 'chronic/pointer' -require 'chronic/scalar' -require 'chronic/ordinal' -require 'chronic/separator' -require 'chronic/time_zone' -require 'chronic/numerizer' -require 'chronic/season' - -require 'chronic/repeater' -require 'chronic/repeaters/repeater_year' -require 'chronic/repeaters/repeater_season' -require 'chronic/repeaters/repeater_season_name' -require 'chronic/repeaters/repeater_month' -require 'chronic/repeaters/repeater_month_name' -require 'chronic/repeaters/repeater_fortnight' -require 'chronic/repeaters/repeater_week' -require 'chronic/repeaters/repeater_weekend' -require 'chronic/repeaters/repeater_weekday' -require 'chronic/repeaters/repeater_day' -require 'chronic/repeaters/repeater_day_name' -require 'chronic/repeaters/repeater_day_portion' -require 'chronic/repeaters/repeater_hour' -require 'chronic/repeaters/repeater_minute' -require 'chronic/repeaters/repeater_second' -require 'chronic/repeaters/repeater_time' +require 'lib/chronic/chronic' class Time + def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0) warn "Time.construct will be deprecated in version 0.7.0. Please use Chronic.construct instead" Chronic.construct(year, month, day, hour, minute, second) @@ -109,4 +113,5 @@ def to_minidate warn "Time.to_minidate will be deprecated in version 0.7.0. Please use Chronic::MiniDate.from_time(time) instead" Chronic::MiniDate.from_time(self) end + end From 8b895845325caa748325a02cd75de974a4f75cb7 Mon Sep 17 00:00:00 2001 From: AnoHito Date: Fri, 20 Apr 2012 02:08:39 -0500 Subject: [PATCH 021/184] fixed require of chronic/chronic --- lib/chronic.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/chronic.rb b/lib/chronic.rb index 530e88aa..d1239e42 100644 --- a/lib/chronic.rb +++ b/lib/chronic.rb @@ -100,7 +100,7 @@ class << self end -require 'lib/chronic/chronic' +require 'chronic/chronic' class Time From 8d2e4d22ae4a14fbabe46b92006b00609fbffa75 Mon Sep 17 00:00:00 2001 From: Jeremy Friesen Date: Tue, 15 May 2012 19:20:37 -0400 Subject: [PATCH 022/184] Added tests to verify behavior of RepeaterDayPortion In addition to adding tests for the RepeaterDayPortion, the class now properly handles construction of date ranges in which the end time occurs on a day in which the time changes. --- lib/chronic/repeaters/repeater_day_portion.rb | 36 ++- test/test_repeater_day_portion.rb | 254 ++++++++++++++++++ 2 files changed, 279 insertions(+), 11 deletions(-) create mode 100644 test/test_repeater_day_portion.rb diff --git a/lib/chronic/repeaters/repeater_day_portion.rb b/lib/chronic/repeaters/repeater_day_portion.rb index 536e43b5..84b78961 100644 --- a/lib/chronic/repeaters/repeater_day_portion.rb +++ b/lib/chronic/repeaters/repeater_day_portion.rb @@ -25,8 +25,6 @@ def initialize(type) def next(pointer) super - full_day = 60 * 60 * 24 - if !@current_span now_seconds = @now - Chronic.construct(@now.year, @now.month, @now.day) if now_seconds < @range.begin @@ -34,32 +32,38 @@ def next(pointer) when :future range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin when :past - range_start = Chronic.construct(@now.year, @now.month, @now.day) - full_day + @range.begin + range_start = Chronic.construct(@now.year, @now.month, @now.day - 1) + @range.begin end elsif now_seconds > @range.end case pointer when :future - range_start = Chronic.construct(@now.year, @now.month, @now.day) + full_day + @range.begin + range_start = Chronic.construct(@now.year, @now.month, @now.day + 1) + @range.begin when :past range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin end else case pointer when :future - range_start = Chronic.construct(@now.year, @now.month, @now.day) + full_day + @range.begin + range_start = Chronic.construct(@now.year, @now.month, @now.day + 1) + @range.begin when :past - range_start = Chronic.construct(@now.year, @now.month, @now.day) - full_day + @range.begin + range_start = Chronic.construct(@now.year, @now.month, @now.day - 1) + @range.begin end end - - @current_span = Span.new(range_start, range_start + (@range.end - @range.begin)) + offset = (@range.end - @range.begin) + range_end = construct_date_from_reference_and_offset(range_start, offset) + @current_span = Span.new(range_start, range_end) else + days_to_shift_window = case pointer when :future - @current_span += full_day + 1 when :past - @current_span -= full_day + -1 end + + new_begin = Chronic.construct(@current_span.begin.year, @current_span.begin.month, @current_span.begin.day + days_to_shift_window, @current_span.begin.hour, @current_span.begin.min, @current_span.begin.sec) + new_end = Chronic.construct(@current_span.end.year, @current_span.end.month, @current_span.end.day + days_to_shift_window, @current_span.end.hour, @current_span.end.min, @current_span.end.sec) + @current_span = Span.new(new_begin, new_end) end end @@ -67,7 +71,8 @@ def this(context = :future) super range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin - @current_span = Span.new(range_start, range_start + (@range.end - @range.begin)) + range_end = construct_date_from_reference_and_offset(range_start) + @current_span = Span.new(range_start, range_end) end def offset(span, amount, pointer) @@ -90,5 +95,14 @@ def width def to_s super << '-dayportion-' << @type.to_s end + + private + def construct_date_from_reference_and_offset(reference, offset = nil) + elapsed_seconds_for_range = offset || (@range.end - @range.begin) + second_hand = ((elapsed_seconds_for_range - (12 * 60))) % 60 + minute_hand = (elapsed_seconds_for_range - second_hand) / (60) % 60 + hour_hand = (elapsed_seconds_for_range - minute_hand - second_hand) / (60 * 60) + reference.hour % 24 + Chronic.construct(reference.year, reference.month, reference.day, hour_hand, minute_hand, second_hand) + end end end \ No newline at end of file diff --git a/test/test_repeater_day_portion.rb b/test/test_repeater_day_portion.rb new file mode 100644 index 00000000..1959c21e --- /dev/null +++ b/test/test_repeater_day_portion.rb @@ -0,0 +1,254 @@ +require 'helper' + +class TestRepeaterDayPortion < TestCase + + def setup + @now = Time.local(2006, 8, 16, 14, 0, 0, 0) + end + + def test_am_future + day_portion = Chronic::RepeaterDayPortion.new(:am) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 17, 00), next_time.begin + assert_equal Time.local(2006, 8, 17, 11, 59, 59), next_time.end + + next_next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 18, 00), next_next_time.begin + assert_equal Time.local(2006, 8, 18, 11, 59, 59), next_next_time.end + end + + def test_am_past + day_portion = Chronic::RepeaterDayPortion.new(:am) + day_portion.start = @now + + next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 16, 00), next_time.begin + assert_equal Time.local(2006, 8, 16, 11, 59, 59), next_time.end + + next_next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 15, 00), next_next_time.begin + assert_equal Time.local(2006, 8, 15, 11, 59, 59), next_next_time.end + end + + def test_am_future_with_daylight_savings_time_boundary + @now = Time.local(2012,11,3,0,0,0) + day_portion = Chronic::RepeaterDayPortion.new(:am) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2012, 11, 4, 00), next_time.begin + assert_equal Time.local(2012, 11, 4, 11, 59, 59), next_time.end + + next_next_time = day_portion.next(:future) + + assert_equal Time.local(2012, 11, 5, 00), next_next_time.begin + assert_equal Time.local(2012, 11, 5, 11, 59, 59), next_next_time.end + end + + def test_pm_future + day_portion = Chronic::RepeaterDayPortion.new(:pm) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 17, 12), next_time.begin + assert_equal Time.local(2006, 8, 17, 23, 59, 59), next_time.end + + next_next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 18, 12), next_next_time.begin + assert_equal Time.local(2006, 8, 18, 23, 59, 59), next_next_time.end + end + + def test_pm_past + day_portion = Chronic::RepeaterDayPortion.new(:pm) + day_portion.start = @now + + next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 15, 12), next_time.begin + assert_equal Time.local(2006, 8, 15, 23, 59, 59), next_time.end + + next_next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 14, 12), next_next_time.begin + assert_equal Time.local(2006, 8, 14, 23, 59, 59), next_next_time.end + end + + def test_pm_future_with_daylight_savings_time_boundary + @now = Time.local(2012,11,3,0,0,0) + day_portion = Chronic::RepeaterDayPortion.new(:pm) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2012, 11, 3, 12), next_time.begin + assert_equal Time.local(2012, 11, 3, 23, 59, 59), next_time.end + + next_next_time = day_portion.next(:future) + + assert_equal Time.local(2012, 11, 4, 12), next_next_time.begin + assert_equal Time.local(2012, 11, 4, 23, 59, 59), next_next_time.end + end + + def test_morning_future + day_portion = Chronic::RepeaterDayPortion.new(:morning) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 17, 6), next_time.begin + assert_equal Time.local(2006, 8, 17, 12), next_time.end + + next_next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 18, 6), next_next_time.begin + assert_equal Time.local(2006, 8, 18, 12), next_next_time.end + end + + def test_morning_past + day_portion = Chronic::RepeaterDayPortion.new(:morning) + day_portion.start = @now + + next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 16, 6), next_time.begin + assert_equal Time.local(2006, 8, 16, 12), next_time.end + + next_next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 15, 6), next_next_time.begin + assert_equal Time.local(2006, 8, 15, 12), next_next_time.end + end + + def test_morning_future_with_daylight_savings_time_boundary + @now = Time.local(2012,11,3,0,0,0) + day_portion = Chronic::RepeaterDayPortion.new(:morning) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2012, 11, 3, 6), next_time.begin + assert_equal Time.local(2012, 11, 3, 12), next_time.end + + next_next_time = day_portion.next(:future) + + assert_equal Time.local(2012, 11, 4, 6), next_next_time.begin + assert_equal Time.local(2012, 11, 4, 12), next_next_time.end + end + + def test_afternoon_future + day_portion = Chronic::RepeaterDayPortion.new(:afternoon) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 17, 13), next_time.begin + assert_equal Time.local(2006, 8, 17, 17), next_time.end + + next_next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 18, 13), next_next_time.begin + assert_equal Time.local(2006, 8, 18, 17), next_next_time.end + end + + def test_afternoon_past + day_portion = Chronic::RepeaterDayPortion.new(:afternoon) + day_portion.start = @now + + next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 15, 13), next_time.begin + assert_equal Time.local(2006, 8, 15, 17), next_time.end + + next_next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 14, 13), next_next_time.begin + assert_equal Time.local(2006, 8, 14, 17), next_next_time.end + end + + def test_afternoon_future_with_daylight_savings_time_boundary + @now = Time.local(2012,11,3,0,0,0) + day_portion = Chronic::RepeaterDayPortion.new(:afternoon) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2012, 11, 3, 13), next_time.begin + assert_equal Time.local(2012, 11, 3, 17), next_time.end + + next_next_time = day_portion.next(:future) + + assert_equal Time.local(2012, 11, 4, 13), next_next_time.begin + assert_equal Time.local(2012, 11, 4, 17), next_next_time.end + end + + def test_evening_future + day_portion = Chronic::RepeaterDayPortion.new(:evening) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 16, 17), next_time.begin + assert_equal Time.local(2006, 8, 16, 20), next_time.end + + next_next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 17, 17), next_next_time.begin + assert_equal Time.local(2006, 8, 17, 20), next_next_time.end + end + + def test_evening_past + day_portion = Chronic::RepeaterDayPortion.new(:evening) + day_portion.start = @now + + next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 15, 17), next_time.begin + assert_equal Time.local(2006, 8, 15, 20), next_time.end + + next_next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 14, 17), next_next_time.begin + assert_equal Time.local(2006, 8, 14, 20), next_next_time.end + end + + def test_evening_future_with_daylight_savings_time_boundary + @now = Time.local(2012,11,3,0,0,0) + day_portion = Chronic::RepeaterDayPortion.new(:evening) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2012, 11, 3, 17), next_time.begin + assert_equal Time.local(2012, 11, 3, 20), next_time.end + + next_next_time = day_portion.next(:future) + + assert_equal Time.local(2012, 11, 4, 17), next_next_time.begin + assert_equal Time.local(2012, 11, 4, 20), next_next_time.end + end + + def test_night_future + day_portion = Chronic::RepeaterDayPortion.new(:night) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 16, 20), next_time.begin + assert_equal Time.local(2006, 8, 17, 0), next_time.end + + next_next_time = day_portion.next(:future) + assert_equal Time.local(2006, 8, 17, 20), next_next_time.begin + assert_equal Time.local(2006, 8, 18, 0), next_next_time.end + end + + def test_night_past + day_portion = Chronic::RepeaterDayPortion.new(:night) + day_portion.start = @now + + next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 15, 20), next_time.begin + assert_equal Time.local(2006, 8, 16, 0), next_time.end + + next_next_time = day_portion.next(:past) + assert_equal Time.local(2006, 8, 14, 20), next_next_time.begin + assert_equal Time.local(2006, 8, 15, 0), next_next_time.end + end + + def test_night_future_with_daylight_savings_time_boundary + @now = Time.local(2012,11,3,0,0,0) + day_portion = Chronic::RepeaterDayPortion.new(:night) + day_portion.start = @now + + next_time = day_portion.next(:future) + assert_equal Time.local(2012, 11, 3, 20), next_time.begin + assert_equal Time.local(2012, 11, 4, 0), next_time.end + + next_next_time = day_portion.next(:future) + + assert_equal Time.local(2012, 11, 4, 20), next_next_time.begin + assert_equal Time.local(2012, 11, 5, 0), next_next_time.end + end +end From f9aa0e21d5e442ec13c45bafbc40d790472c4bfc Mon Sep 17 00:00:00 2001 From: Steve Burkett Date: Thu, 24 May 2012 19:32:55 -0700 Subject: [PATCH 023/184] handle text starting w/ a ... --- lib/chronic/chronic.rb | 1 + test/test_parsing.rb | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 308357eb..cb903c9f 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -123,6 +123,7 @@ def pre_normalize(text) text.gsub!(/\b\d+:?\d*[ap]\b/,'\0m') text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2') text.gsub!(/\b(hence|after|from)\b/, 'future') + text.gsub!(/^a /, '1 ') text end diff --git a/test/test_parsing.rb b/test/test_parsing.rb index 958f3655..d0adfe85 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -685,6 +685,17 @@ def test_parse_guess_rgr assert_equal Time.local(2006, 8, 8, 12), time end + def test_parse_guess_a_ago + time = parse_now("a day ago") + assert_equal Time.local(2006, 8, 15, 14), time + + time = parse_now("a month ago") + assert_equal Time.local(2006, 7, 16, 14), time + + time = parse_now("a year ago") + assert_equal Time.local(2005, 8, 16, 14), time + end + def test_parse_guess_s_r_p # past From 0d3abd1cf1203b2899d133c7adbccb53650ec81d Mon Sep 17 00:00:00 2001 From: Steve Burkett Date: Thu, 24 May 2012 19:54:36 -0700 Subject: [PATCH 024/184] any number of spaces may preceed --- lib/chronic/chronic.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index cb903c9f..1873ff45 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -123,7 +123,7 @@ def pre_normalize(text) text.gsub!(/\b\d+:?\d*[ap]\b/,'\0m') text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2') text.gsub!(/\b(hence|after|from)\b/, 'future') - text.gsub!(/^a /, '1 ') + text.gsub!(/^\s?a /, '1 ') text end From 0024100f6427db36e6a3c91878ff617ccd4109da Mon Sep 17 00:00:00 2001 From: Steve Burkett Date: Thu, 24 May 2012 20:02:09 -0700 Subject: [PATCH 025/184] add support for an hour --- README.md | 1 + lib/chronic/chronic.rb | 2 +- test/test_parsing.rb | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 381eab34..0cef6791 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ Simple Complex * 3 years ago +* a year ago * 5 months before now * 7 hours ago * 7 days from now diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 1873ff45..0cbcad42 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -123,7 +123,7 @@ def pre_normalize(text) text.gsub!(/\b\d+:?\d*[ap]\b/,'\0m') text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2') text.gsub!(/\b(hence|after|from)\b/, 'future') - text.gsub!(/^\s?a /, '1 ') + text.gsub!(/^\s?an? /, '1 ') text end diff --git a/test/test_parsing.rb b/test/test_parsing.rb index d0adfe85..d0eeabf9 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -686,6 +686,9 @@ def test_parse_guess_rgr end def test_parse_guess_a_ago + time = parse_now("an hour ago") + assert_equal Time.local(2006, 8, 16, 13), time + time = parse_now("a day ago") assert_equal Time.local(2006, 8, 15, 14), time From 6c08067a00b64a8f7147da7deeafc814626be8ff Mon Sep 17 00:00:00 2001 From: Steve Burkett Date: Fri, 25 May 2012 08:29:11 -0700 Subject: [PATCH 026/184] handle any case AN --- lib/chronic/chronic.rb | 2 +- test/test_parsing.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 0cbcad42..7caef708 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -123,7 +123,7 @@ def pre_normalize(text) text.gsub!(/\b\d+:?\d*[ap]\b/,'\0m') text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2') text.gsub!(/\b(hence|after|from)\b/, 'future') - text.gsub!(/^\s?an? /, '1 ') + text.gsub!(/^\s?[aA][nN]? /, '1 ') text end diff --git a/test/test_parsing.rb b/test/test_parsing.rb index d0eeabf9..aac32082 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -686,10 +686,10 @@ def test_parse_guess_rgr end def test_parse_guess_a_ago - time = parse_now("an hour ago") + time = parse_now("AN hour ago") assert_equal Time.local(2006, 8, 16, 13), time - time = parse_now("a day ago") + time = parse_now("A day ago") assert_equal Time.local(2006, 8, 15, 14), time time = parse_now("a month ago") From 3d3c1fca7d8f565dd03df298a7f3c5f5b05ad49f Mon Sep 17 00:00:00 2001 From: Bryan Dunsmore Date: Fri, 25 May 2012 15:48:29 -0500 Subject: [PATCH 027/184] Add support for common time abbreviations. Replaces common time abbreviations, such as hr, min, and sec, with their full names. References: #100 --- lib/chronic/chronic.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 308357eb..d2fade03 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -123,6 +123,9 @@ def pre_normalize(text) text.gsub!(/\b\d+:?\d*[ap]\b/,'\0m') text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2') text.gsub!(/\b(hence|after|from)\b/, 'future') + text.gsub!(/\bhrs?\b/, 'hour') + text.gsub!(/\bmins?\b/, 'minute') + text.gsub!(/\bsecs?\b/, 'second') text end From 41d226d3bc7e3a6adade9b97b6b3984bbc22eff5 Mon Sep 17 00:00:00 2001 From: Bryan Dunsmore Date: Fri, 25 May 2012 16:30:28 -0500 Subject: [PATCH 028/184] Move support for time abbreviations to repeater. Moves the suppor for time abbreviations from lib/chronic/chronic.rb to lib/chronic/repeater.rb. --- lib/chronic/chronic.rb | 3 --- lib/chronic/repeater.rb | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index d2fade03..308357eb 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -123,9 +123,6 @@ def pre_normalize(text) text.gsub!(/\b\d+:?\d*[ap]\b/,'\0m') text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2') text.gsub!(/\b(hence|after|from)\b/, 'future') - text.gsub!(/\bhrs?\b/, 'hour') - text.gsub!(/\bmins?\b/, 'minute') - text.gsub!(/\bsecs?\b/, 'second') text end diff --git a/lib/chronic/repeater.rb b/lib/chronic/repeater.rb index 2daf1368..394e5d09 100644 --- a/lib/chronic/repeater.rb +++ b/lib/chronic/repeater.rb @@ -104,8 +104,11 @@ def self.scan_for_units(token) /^weekends?$/ => :weekend, /^(week|business)days?$/ => :weekday, /^days?$/ => :day, + /^hrs?$/ => :hour, /^hours?$/ => :hour, + /^mins?$/ => :minute, /^minutes?$/ => :minute, + /^secs?$/ => :second, /^seconds?$/ => :second }.each do |item, symbol| if item =~ token.word @@ -139,4 +142,4 @@ def to_s 'repeater' end end -end \ No newline at end of file +end From 122810d8f98862e8d3bbdb20b056fa2d270d945c Mon Sep 17 00:00:00 2001 From: Bryan Dunsmore Date: Fri, 25 May 2012 16:54:42 -0500 Subject: [PATCH 029/184] Add tests for time abbreviations. Add tests for time abbreviations in test/test_parsing.rb. --- test/test_parsing.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/test_parsing.rb b/test/test_parsing.rb index 958f3655..dbcca3bb 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -586,13 +586,33 @@ def test_parse_guess_gr time = parse_now("tonight") assert_equal Time.local(2006, 8, 16, 22), time + # hour + + time = parse_now("next hr") + assert_equal Time.local(2006, 8, 16, 15, 30, 0), time + + time = parse_now("next hrs") + assert_equal Time.local(2006, 8, 16, 15, 30, 0), time + # minute + time = parse_now("next min") + assert_equal Time.local(2006, 8, 16, 14, 1, 30), time + + time = parse_now("next mins") + assert_equal Time.local(2006, 8, 16, 14, 1, 30), time + time = parse_now("next minute") assert_equal Time.local(2006, 8, 16, 14, 1, 30), time # second + time = parse_now("next sec") + assert_equal Time.local(2006, 8, 16, 14, 0, 1), time + + time = parse_now("next secs") + assert_equal Time.local(2006, 8, 16, 14, 0, 1), time + time = parse_now("this second") assert_equal Time.local(2006, 8, 16, 14), time From f5eeaf75cac25818eae83356076b2cd3572b58b7 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Thu, 31 May 2012 16:55:30 +0100 Subject: [PATCH 030/184] support parsing day(scalar)-month(name)-year(scalar) closes #99 --- HISTORY.md | 1 + lib/chronic/chronic.rb | 3 ++- lib/chronic/handlers.rb | 9 +++++++++ test/test_parsing.rb | 5 +++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 645cd839..c790ff8c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -3,6 +3,7 @@ * Start using minitest for testing * Ensure periods are interpreted as colons (#81). * Support month/day and day/month parsing (#59). +* Support day(scalar)-month(name)-year(scalar) (#99). # 0.6.7 / 2012-01-31 diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 308357eb..280fd4b7 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -186,7 +186,8 @@ def definitions(options={}) Handler.new([:scalar_day, :repeater_month_name, :separator_at?, 'time?'], :handle_sd_rmn), Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sy_sm_sd), Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day], :handle_sm_sd), - Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_year], :handle_sm_sy) + Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_year], :handle_sm_sy), + Handler.new([:scalar_day, :separator_slash_or_dash, :repeater_month_name, :separator_slash_or_dash, :scalar_year], :handle_sm_rmn_sy) ], # tonight at 7pm diff --git a/lib/chronic/handlers.rb b/lib/chronic/handlers.rb index 97d72588..67e7e3a4 100644 --- a/lib/chronic/handlers.rb +++ b/lib/chronic/handlers.rb @@ -317,6 +317,15 @@ def handle_rdn_rmn_sd_sy(tokens, options) end end + def handle_sm_rmn_sy(tokens, options) + day = tokens[0].get_tag(ScalarDay).type + month = tokens[1].get_tag(RepeaterMonthName).index + year = tokens[2].get_tag(ScalarYear).type + time = Chronic.time_class.local(year, month, day) + end_time = Chronic.time_class.local(year, month, day + 1) + Span.new(time, end_time) + end + # anchors # Handle repeaters diff --git a/test/test_parsing.rb b/test/test_parsing.rb index 958f3655..f83b1e1a 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -365,6 +365,11 @@ def test_handle_o_r_g_r assert_equal Time.local(2006, 8, 9, 12), time end + def test_handle_sm_rmn_sy + time = parse_now('30-Mar-11') + assert_equal Time.local(2011, 3, 30, 12), time + end + # end of testing handlers def test_parse_guess_r From 7c5f962f5af6f4c1cdd9c585f8fc8d7abe494180 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Thu, 31 May 2012 17:03:35 +0100 Subject: [PATCH 031/184] modify an? gsub regexp to simplify --- lib/chronic/chronic.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 883102e9..0a178e66 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -123,7 +123,7 @@ def pre_normalize(text) text.gsub!(/\b\d+:?\d*[ap]\b/,'\0m') text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2') text.gsub!(/\b(hence|after|from)\b/, 'future') - text.gsub!(/^\s?[aA][nN]? /, '1 ') + text.gsub!(/^\s?an? /i, '1 ') text end From 953d16f5ddd0f2cd5d41bfad8958d3c0df193448 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Thu, 31 May 2012 17:04:20 +0100 Subject: [PATCH 032/184] updated history --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index c790ff8c..840a746b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,7 @@ * Ensure periods are interpreted as colons (#81). * Support month/day and day/month parsing (#59). * Support day(scalar)-month(name)-year(scalar) (#99). +* Handle text starting with 'a' or 'an' (#101, @steveburkett). # 0.6.7 / 2012-01-31 From 7585ccbe0e7f847217a59a82f3d3ece59beae2b8 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Thu, 31 May 2012 17:58:08 +0100 Subject: [PATCH 033/184] only execute #offset on repeaters which handle them ref #86 --- lib/chronic/handlers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/chronic/handlers.rb b/lib/chronic/handlers.rb index 67e7e3a4..b7546490 100644 --- a/lib/chronic/handlers.rb +++ b/lib/chronic/handlers.rb @@ -348,7 +348,7 @@ def handle_srp(tokens, span, options) repeater = tokens[1].get_tag(Repeater) pointer = tokens[2].get_tag(Pointer).type - repeater.offset(span, distance, pointer) + repeater.offset(span, distance, pointer) if repeater.respond_to?(:offset) end # Handle scalar/repeater/pointer From b75dedd30e4c03b2318e70143eee0d9fe540721f Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Sun, 24 Jun 2012 20:35:37 +0100 Subject: [PATCH 034/184] ensure use of 'second' at the start of string acts as ordinal There's no chance of second representing a unit of time when it's used at the beginning of a sentence, so it should always be treated as 2nd would be closes #103 --- lib/chronic/chronic.rb | 1 + test/test_parsing.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 0a178e66..e0d48cc2 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -104,6 +104,7 @@ def pre_normalize(text) text.gsub!(/\./, ':') text.gsub!(/['"]/, '') text.gsub!(/,/, ' ') + text.gsub!(/^second /, '2nd ') text.gsub!(/\bsecond (of|day|month|hour|minute|second)\b/, '2nd \1') text = Numerizer.numerize(text) text.gsub!(/ \-(\d{4})\b/, ' tzminus\1') diff --git a/test/test_parsing.rb b/test/test_parsing.rb index bf1b50d7..fded5536 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -598,7 +598,7 @@ def test_parse_guess_gr time = parse_now("next hrs") assert_equal Time.local(2006, 8, 16, 15, 30, 0), time - + # minute time = parse_now("next min") @@ -886,6 +886,7 @@ def test_parse_words assert_equal parse_now("33 days from now"), parse_now("thirty-three days from now") assert_equal parse_now("2867532 seconds from now"), parse_now("two million eight hundred and sixty seven thousand five hundred and thirty two seconds from now") assert_equal parse_now("may 10th"), parse_now("may tenth") + assert_equal parse_now("second monday in january"), parse_now("2nd monday in january") end def test_parse_only_complete_pointers From 53b62a98d886c29389ba9cbe5c37a082f8731423 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Fri, 29 Jun 2012 15:58:17 +0100 Subject: [PATCH 035/184] ensure a single whitespace character is prepended when replacing post medium timestamps closes #89 --- lib/chronic/chronic.rb | 2 +- test/test_parsing.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index e0d48cc2..303459fd 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -109,7 +109,7 @@ def pre_normalize(text) text = Numerizer.numerize(text) text.gsub!(/ \-(\d{4})\b/, ' tzminus\1') text.gsub!(/([\/\-\,\@])/) { ' ' + $1 + ' ' } - text.gsub!(/(?:^|\s)0(\d+:\d+\s*pm?\b)/, '\1') + text.gsub!(/(?:^|\s)0(\d+:\d+\s*pm?\b)/, ' \1') text.gsub!(/\btoday\b/, 'this day') text.gsub!(/\btomm?orr?ow\b/, 'next day') text.gsub!(/\byesterday\b/, 'last day') diff --git a/test/test_parsing.rb b/test/test_parsing.rb index fded5536..e3f97fa2 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -252,6 +252,9 @@ def test_handle_sd_sm_sy time = parse_now("27/5/1979 @ 0700") assert_equal Time.local(1979, 5, 27, 7), time + + time = parse_now("03/18/2012 09:26 pm") + assert_equal Time.local(2012, 3, 18, 21, 26), time end def test_handle_sy_sm_sd From b554169fb9e74d705da879c7dfc59af3c5aed6c5 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Fri, 29 Jun 2012 16:01:01 +0100 Subject: [PATCH 036/184] updated history --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index 840a746b..40acb5b6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,6 +5,7 @@ * Support month/day and day/month parsing (#59). * Support day(scalar)-month(name)-year(scalar) (#99). * Handle text starting with 'a' or 'an' (#101, @steveburkett). +* Ensure post medium timestamps are correctly formatted (#89) # 0.6.7 / 2012-01-31 From 89340ac78153e80258927573a68891847bb2d6a0 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 1 Aug 2012 08:53:48 +0100 Subject: [PATCH 037/184] support parsing EXIF date format closes #112 --- lib/chronic/chronic.rb | 1 + test/test_parsing.rb | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 303459fd..c8233d35 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -125,6 +125,7 @@ def pre_normalize(text) text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2') text.gsub!(/\b(hence|after|from)\b/, 'future') text.gsub!(/^\s?an? /i, '1 ') + text.gsub!(/\b(\d{4}):(\d{2}):(\d{2})\b/, '\1 / \2 / \3') # DTOriginal text end diff --git a/test/test_parsing.rb b/test/test_parsing.rb index e3f97fa2..a34e913b 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -281,6 +281,10 @@ def test_handle_sy_sm_sd time = parse_now("1902-08-20") assert_equal Time.local(1902, 8, 20, 12, 0, 0), time + + # exif date time original + time = parse_now("2012:05:25 22:06:50") + assert_equal Time.local(2012, 5, 25, 22, 6, 50), time end def test_handle_sm_sd From b3702846e14006519161aed68884a0960f3cde42 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 1 Aug 2012 08:54:39 +0100 Subject: [PATCH 038/184] updated history file --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index 40acb5b6..e5597f6d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,6 @@ # HEAD +* Support parsing EXIF date format (#112) * Start using minitest for testing * Ensure periods are interpreted as colons (#81). * Support month/day and day/month parsing (#59). From cdf07ea7efc124b6e4f73b4f910f7c1e40d67d44 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Wed, 1 Aug 2012 12:50:44 +0100 Subject: [PATCH 039/184] Release 0.7.0 --- lib/chronic.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/chronic.rb b/lib/chronic.rb index d1239e42..fdfaa910 100644 --- a/lib/chronic.rb +++ b/lib/chronic.rb @@ -27,7 +27,7 @@ # Chronic.parse('may 27th', :guess => false) # #=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007 module Chronic - VERSION = "0.6.7" + VERSION = "0.7.0" class << self @@ -63,7 +63,7 @@ class << self self.debug = false self.time_class = Time - + autoload :Handler, 'chronic/handler' autoload :Handlers, 'chronic/handlers' autoload :MiniDate, 'chronic/mini_date' @@ -79,7 +79,7 @@ class << self autoload :TimeZone, 'chronic/time_zone' autoload :Numerizer, 'chronic/numerizer' autoload :Season, 'chronic/season' - + autoload :Repeater, 'chronic/repeater' autoload :RepeaterYear, 'chronic/repeaters/repeater_year' autoload :RepeaterSeason, 'chronic/repeaters/repeater_season' @@ -97,13 +97,13 @@ class << self autoload :RepeaterMinute, 'chronic/repeaters/repeater_minute' autoload :RepeaterSecond, 'chronic/repeaters/repeater_second' autoload :RepeaterTime, 'chronic/repeaters/repeater_time' - + end require 'chronic/chronic' class Time - + def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0) warn "Time.construct will be deprecated in version 0.7.0. Please use Chronic.construct instead" Chronic.construct(year, month, day, hour, minute, second) @@ -113,5 +113,5 @@ def to_minidate warn "Time.to_minidate will be deprecated in version 0.7.0. Please use Chronic::MiniDate.from_time(time) instead" Chronic::MiniDate.from_time(self) end - + end From 8fde6672437e2c67413855ef6029daa96079f4bb Mon Sep 17 00:00:00 2001 From: Alex Grant Date: Fri, 7 Sep 2012 11:48:20 -0400 Subject: [PATCH 040/184] Introduce failing test for sm/sd with time --- test/test_parsing.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test_parsing.rb b/test/test_parsing.rb index a34e913b..b3d6194f 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -294,6 +294,12 @@ def test_handle_sm_sd time = parse_now("05/06", :endian_precedence => [:little, :medium]) assert_equal Time.local(2006, 6, 5, 12), time + time = parse_now("05/06 6:05:57 PM") + assert_equal Time.local(2006, 5, 6, 18, 05, 57), time + + time = parse_now("05/06 6:05:57 PM", :endian_precedence => [:little, :medium]) + assert_equal Time.local(2006, 6, 5, 18, 05, 57), time + time = parse_now("13/01") assert_nil time end From 2b4fdb07220479240749320ca65b10e57778f8d0 Mon Sep 17 00:00:00 2001 From: Alex Grant Date: Fri, 7 Sep 2012 13:43:21 -0400 Subject: [PATCH 041/184] Fix sd/sm test that shouldn't return nil --- test/test_parsing.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_parsing.rb b/test/test_parsing.rb index b3d6194f..c0aa1053 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -301,7 +301,7 @@ def test_handle_sm_sd assert_equal Time.local(2006, 6, 5, 18, 05, 57), time time = parse_now("13/01") - assert_nil time + assert_equal Time.local(2006, 1, 13, 12), time end # def test_handle_sm_sy From 32b19808cacb8c89c5557e8ddfeb29f23242aa4c Mon Sep 17 00:00:00 2001 From: Alex Grant Date: Fri, 7 Sep 2012 13:53:27 -0400 Subject: [PATCH 042/184] Handle sm/sd and sd/sm with time --- lib/chronic/chronic.rb | 3 ++- lib/chronic/handlers.rb | 19 +++++++++++-------- test/test_chronic.rb | 2 ++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index c8233d35..29726b28 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -188,7 +188,6 @@ def definitions(options={}) Handler.new([:scalar_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_sd_rmn_sy), Handler.new([:scalar_day, :repeater_month_name, :separator_at?, 'time?'], :handle_sd_rmn), Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sy_sm_sd), - Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day], :handle_sm_sd), Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_year], :handle_sm_sy), Handler.new([:scalar_day, :separator_slash_or_dash, :repeater_month_name, :separator_slash_or_dash, :scalar_year], :handle_sm_rmn_sy) ], @@ -216,6 +215,8 @@ def definitions(options={}) endians = [ Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy), + Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sm_sd), + Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_at?, 'time?'], :handle_sd_sm), Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sd_sm_sy) ] diff --git a/lib/chronic/handlers.rb b/lib/chronic/handlers.rb index b7546490..6e0c3d91 100644 --- a/lib/chronic/handlers.rb +++ b/lib/chronic/handlers.rb @@ -224,27 +224,30 @@ def handle_sy_sm_sd(tokens, options) handle_sm_sd_sy(new_tokens + time_tokens, options) end - # Handle scalar-day/scalar-month AND scalar-month/scalar-day + # Handle scalar-month/scalar-day def handle_sm_sd(tokens, options) month = tokens[0].get_tag(ScalarMonth).type day = tokens[1].get_tag(ScalarDay).type year = Chronic.now.year - - if Array(options[:endian_precedence]).first == :little - day, month = month, day - end + time_tokens = tokens.last(tokens.size - 2) return if month_overflow?(year, month, day) begin - start_time = Chronic.time_class.local(year, month, day) - end_time = Chronic.time_class.local(year, month, day + 1) - Span.new(start_time, end_time) + day_start = Chronic.time_class.local(year, month, day) + day_or_time(day_start, time_tokens, options) rescue ArgumentError nil end end + # Handle scalar-day/scalar-month + def handle_sd_sm(tokens, options) + new_tokens = [tokens[1], tokens[0]] + time_tokens = tokens.last(tokens.size - 2) + handle_sm_sd(new_tokens + time_tokens, options) + end + # Handle scalar-month/scalar-year def handle_sm_sy(tokens, options) month = tokens[0].get_tag(ScalarMonth).type diff --git a/test/test_chronic.rb b/test/test_chronic.rb index ab4c81bb..325c1bdb 100644 --- a/test/test_chronic.rb +++ b/test/test_chronic.rb @@ -67,6 +67,8 @@ def test_endian_definitions # middle, little endians = [ Chronic::Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy), + Chronic::Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sm_sd), + Chronic::Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_at?, 'time?'], :handle_sd_sm), Chronic::Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sd_sm_sy) ] From d1c4a9d1c16176cba15bf3a82a90984eacc1b538 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Sat, 8 Sep 2012 15:12:39 +0100 Subject: [PATCH 043/184] support optional 'at' with anchor closes #124 --- lib/chronic/chronic.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index 29726b28..c35a0ae1 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -203,7 +203,7 @@ def definitions(options={}) :arrow => [ Handler.new([:scalar, :repeater, :pointer], :handle_s_r_p), Handler.new([:pointer, :scalar, :repeater], :handle_p_s_r), - Handler.new([:scalar, :repeater, :pointer, 'anchor'], :handle_s_r_p_a) + Handler.new([:scalar, :repeater, :pointer, :separator_at?, 'anchor'], :handle_s_r_p_a) ], # 3rd week in march From a1a64e6b2d662d2e545e6a94aa22b2a0ebcb5971 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Sun, 16 Sep 2012 17:37:42 +0100 Subject: [PATCH 044/184] allow anchor handler to accept any optional separators By using 'separator?' instead of 'separator_at?' it means we can match 'on' as well as 'at'. Before this, "9am at Saturday" would parse, where "9am on Saturday" would not closes #128 --- lib/chronic/chronic.rb | 2 +- test/test_parsing.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/chronic/chronic.rb b/lib/chronic/chronic.rb index c35a0ae1..96a44f40 100644 --- a/lib/chronic/chronic.rb +++ b/lib/chronic/chronic.rb @@ -195,7 +195,7 @@ def definitions(options={}) # tonight at 7pm :anchor => [ Handler.new([:grabber?, :repeater, :separator_at?, :repeater?, :repeater?], :handle_r), - Handler.new([:grabber?, :repeater, :repeater, :separator_at?, :repeater?, :repeater?], :handle_r), + Handler.new([:grabber?, :repeater, :repeater, :separator?, :repeater?, :repeater?], :handle_r), Handler.new([:repeater, :grabber, :repeater], :handle_r_g_r) ], diff --git a/test/test_parsing.rb b/test/test_parsing.rb index c0aa1053..89f1d216 100644 --- a/test/test_parsing.rb +++ b/test/test_parsing.rb @@ -316,6 +316,8 @@ def test_handle_sm_sd # end def test_handle_r + time = parse_now("9am on Saturday") + assert_equal Time.local(2006, 8, 19, 9), time end def test_handle_r_g_r From 077a66eecbf85ce30a44f4e123f8d6e0718b97a9 Mon Sep 17 00:00:00 2001 From: Lee Jarvis Date: Sun, 16 Sep 2012 18:06:05 +0100 Subject: [PATCH 045/184] support time when parsing dd-mmm-yyy