Skip to content
Browse files

svrc updates

  • Loading branch information...
1 parent 044fbd7 commit f4fef51a3a315e08132366506cd76a9a893689e5 @mojombo mojombo committed Jun 16, 2007
View
19 History.txt
@@ -1,11 +1,22 @@
-= 0.2.0 2007-03-20
+= 0.2.2
+
+* added missing files (damn you manifest
+
+= 0.2.1
* fixed time overflow issue
-* implemented numerizer, allowing the use of number words (e.g. five weeks ago) (thanks shalev!)
+* implemented "next" for minute repeater
+* generalized time dealiasing to dealias regardless of day portion and time position
+* added additional token match for cases like "friday evening at 7" and "tomorrow evening at 7"
+* added support for Time#to_s output format: "Mon Apr 02 17:00:00 PDT 2007"
+
+= 0.2.0 2007-03-20
+
+* implemented numerizer, allowing the use of number words (e.g. five weeks ago) (by shalev)
= 0.1.6 2006-01-15
-* added 'weekend' support (eventualbuddha)
+* added 'weekend' support (by eventualbuddha)
= 0.1.5 2006-12-20
@@ -20,7 +31,7 @@
= 0.1.3
-* improved regexes for word variations (Josh Goebel)
+* improved regexes for word variations (by Josh Goebel)
* fixed a bug that caused "today at 3am" to return nil if current time is after 3am
= 0.1.2
View
2 Manifest.txt
@@ -26,6 +26,7 @@ lib/chronic/repeaters/repeater_weekend.rb
lib/chronic/repeaters/repeater_year.rb
lib/chronic/scalar.rb
lib/chronic/separator.rb
+lib/chronic/time_zone.rb
lib/numerizer/numerizer.rb
test/suite.rb
test/test_Chronic.rb
@@ -41,5 +42,6 @@ test/test_RepeaterWeek.rb
test/test_RepeaterWeekend.rb
test/test_RepeaterYear.rb
test/test_Span.rb
+test/test_Time.rb
test/test_Token.rb
test/test_parsing.rb
View
30 lib/chronic.rb
@@ -34,11 +34,12 @@
require 'chronic/scalar'
require 'chronic/ordinal'
require 'chronic/separator'
+require 'chronic/time_zone'
require 'numerizer/numerizer'
module Chronic
- VERSION = "0.2.0"
+ VERSION = "0.2.2"
def self.debug; false; end
end
@@ -50,6 +51,33 @@ def p(val)
puts
end
+# class Time
+# def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
+# # extra_seconds = second > 60 ? second - 60 : 0
+# # extra_minutes = minute > 59 ? minute - 59 : 0
+# # extra_hours = hour > 23 ? hour - 23 : 0
+# # extra_days = day >
+#
+# if month > 12
+# if month % 12 == 0
+# year += (month - 12) / 12
+# month = 12
+# else
+# year += month / 12
+# month = month % 12
+# end
+# end
+#
+# base = Time.local(year, month)
+# puts base
+# offset = ((day - 1) * 24 * 60 * 60) + (hour * 60 * 60) + (minute * 60) + second
+# puts offset.to_s
+# date = base + offset
+# puts date
+# date
+# end
+# end
+
class Time
def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
if second >= 60
View
2 lib/chronic/chronic.rb
@@ -66,7 +66,7 @@ def parse(text, specified_options = {})
@tokens = tokenizer.scan(@tokens, options)
end
- [Grabber, Pointer, Scalar, Ordinal, Separator].each do |tokenizer|
+ [Grabber, Pointer, Scalar, Ordinal, Separator, TimeZone].each do |tokenizer|
@tokens = tokenizer.scan(@tokens)
end
View
87 lib/chronic/handlers.rb
@@ -6,7 +6,8 @@ def definitions #:nodoc:
@definitions ||=
{:time => [Handler.new([:repeater_time, :repeater_day_portion?], nil)],
- :date => [Handler.new([:repeater_month_name, :scalar_day, :scalar_year], :handle_rmn_sd_sy),
+ :date => [Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :repeater_time, :time_zone, :scalar_year], :handle_rdn_rmn_sd_t_tz_sy),
+ Handler.new([:repeater_month_name, :scalar_day, :scalar_year], :handle_rmn_sd_sy),
Handler.new([:repeater_month_name, :scalar_day, :scalar_year, :separator_at?, 'time?'], :handle_rmn_sd_sy),
Handler.new([:repeater_month_name, :scalar_day, :separator_at?, 'time?'], :handle_rmn_sd),
Handler.new([:repeater_month_name, :ordinal_day, :separator_at?, 'time?'], :handle_rmn_od),
@@ -17,13 +18,17 @@ def definitions #:nodoc:
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_year], :handle_sm_sy)],
+ # 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([:repeater, :grabber, :repeater], :handle_r_g_r)],
+ # 3 weeks from now, in 2 months
: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)],
+ # 3rd week in march
:narrow => [Handler.new([:ordinal, :repeater, :separator_in, :repeater], :handle_o_r_s_r),
Handler.new([:ordinal, :repeater, :grabber, :repeater], :handle_o_r_g_r)]
}
@@ -34,6 +39,7 @@ def tokens_to_span(tokens, options) #:nodoc:
self.definitions[:date].each do |handler|
if handler.match(tokens, self.definitions)
+ puts "-date" if Chronic.debug
good_tokens = tokens.select { |o| !o.get_tag Separator }
return self.send(handler.handler_method, good_tokens, options)
end
@@ -43,6 +49,7 @@ def tokens_to_span(tokens, options) #:nodoc:
self.definitions[:anchor].each do |handler|
if handler.match(tokens, self.definitions)
+ puts "-anchor" if Chronic.debug
good_tokens = tokens.select { |o| !o.get_tag Separator }
return self.send(handler.handler_method, good_tokens, options)
end
@@ -52,21 +59,24 @@ def tokens_to_span(tokens, options) #:nodoc:
self.definitions[:arrow].each do |handler|
if handler.match(tokens, self.definitions)
+ puts "-arrow" if Chronic.debug
good_tokens = tokens.reject { |o| o.get_tag(SeparatorAt) || o.get_tag(SeparatorSlashOrDash) || o.get_tag(SeparatorComma) }
return self.send(handler.handler_method, good_tokens, options)
end
end
- # not an arrow, let's hope it's an narrow
+ # not an arrow, let's hope it's a narrow
self.definitions[:narrow].each do |handler|
if handler.match(tokens, self.definitions)
+ puts "-narrow" if Chronic.debug
#good_tokens = tokens.select { |o| !o.get_tag Separator }
return self.send(handler.handler_method, tokens, options)
end
end
# I guess you're out of luck!
+ puts "-none" if Chronic.debug
return nil
end
@@ -122,6 +132,19 @@ def handle_rmn_sy(tokens, options) #:nodoc:
end
end
+ def handle_rdn_rmn_sd_t_tz_sy(tokens, options) #:nodoc:
+ month = tokens[1].get_tag(RepeaterMonthName).index
+ day = tokens[2].get_tag(ScalarDay).type
+ year = tokens[5].get_tag(ScalarYear).type
+
+ begin
+ day_start = Time.local(year, month, day)
+ day_or_time(day_start, [tokens[3]], options)
+ rescue ArgumentError
+ nil
+ end
+ end
+
def handle_rmn_sd_sy(tokens, options) #:nodoc:
month = tokens[0].get_tag(RepeaterMonthName).index
day = tokens[1].get_tag(ScalarDay).type
@@ -333,22 +356,54 @@ def find_within(tags, span, pointer) #:nodoc:
def dealias_and_disambiguate_times(tokens, options) #:nodoc:
# handle aliases of am/pm
- # 5:00 in the morning => 5:00 am
- # 7:00 in the evening => 7:00 pm
- #ttokens = []
- tokens.each_with_index do |t0, i|
- t1 = tokens[i + 1]
- if t1 && (t1tag = t1.get_tag(RepeaterDayPortion)) && t0.get_tag(RepeaterTime)
- if [:morning].include?(t1tag.type)
- t1.untag(RepeaterDayPortion)
- t1.tag(RepeaterDayPortion.new(:am))
- elsif [:afternoon, :evening, :night].include?(t1tag.type)
- t1.untag(RepeaterDayPortion)
- t1.tag(RepeaterDayPortion.new(:pm))
- end
+ # 5:00 in the morning -> 5:00 am
+ # 7:00 in the evening -> 7:00 pm
+
+ day_portion_index = nil
+ tokens.each_with_index do |t, i|
+ if t.get_tag(RepeaterDayPortion)
+ day_portion_index = i
+ break
+ end
+ end
+
+ time_index = nil
+ tokens.each_with_index do |t, i|
+ if t.get_tag(RepeaterTime)
+ time_index = i
+ break
+ end
+ end
+
+ if (day_portion_index && time_index)
+ t1 = tokens[day_portion_index]
+ t1tag = t1.get_tag(RepeaterDayPortion)
+
+ if [:morning].include?(t1tag.type)
+ puts '--morning->am' if Chronic.debug
+ t1.untag(RepeaterDayPortion)
+ t1.tag(RepeaterDayPortion.new(:am))
+ elsif [:afternoon, :evening, :night].include?(t1tag.type)
+ puts "--#{t1tag.type}->pm" if Chronic.debug
+ t1.untag(RepeaterDayPortion)
+ t1.tag(RepeaterDayPortion.new(:pm))
end
end
- #tokens = ttokens
+
+ # tokens.each_with_index do |t0, i|
+ # t1 = tokens[i + 1]
+ # if t1 && (t1tag = t1.get_tag(RepeaterDayPortion)) && t0.get_tag(RepeaterTime)
+ # if [:morning].include?(t1tag.type)
+ # puts '--morning->am' if Chronic.debug
+ # t1.untag(RepeaterDayPortion)
+ # t1.tag(RepeaterDayPortion.new(:am))
+ # elsif [:afternoon, :evening, :night].include?(t1tag.type)
+ # puts "--#{t1tag.type}->pm" if Chronic.debug
+ # t1.untag(RepeaterDayPortion)
+ # t1.tag(RepeaterDayPortion.new(:pm))
+ # end
+ # end
+ # end
# handle ambiguous times if :ambiguous_time_range is specified
if options[:ambiguous_time_range] != :none
View
1 lib/chronic/repeater.rb
@@ -33,6 +33,7 @@ def self.scan_for_month_names(token)
def self.scan_for_day_names(token)
scanner = {/^m[ou]n(day)?$/ => :monday,
/^t(ue|eu|oo|u|)s(day)?$/ => :tuesday,
+ /^tue$/ => :tuesday,
/^we(dnes|nds|nns)day$/ => :wednesday,
/^wed$/ => :wednesday,
/^th(urs|ers)day$/ => :thursday,
View
2 lib/chronic/repeaters/repeater_day_name.rb
@@ -34,7 +34,7 @@ def width
end
def to_s
- super << '-dayofweek-' << @type.to_s
+ super << '-dayname-' << @type.to_s
end
private
View
14 lib/chronic/repeaters/repeater_minute.rb
@@ -4,9 +4,19 @@ class Chronic::RepeaterMinute < Chronic::Repeater #:nodoc:
def next(pointer = :future)
super
- direction = pointer == :future ? 1 : -1
+ if !@current_minute_start
+ case pointer
+ when :future
+ @current_minute_start = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min + 1)
+ when :past
+ @current_minute_start = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min - 1)
+ end
+ else
+ direction = pointer == :future ? 1 : -1
+ @current_minute_start += direction * MINUTE_SECONDS
+ end
- raise 'not implemented'
+ Chronic::Span.new(@current_minute_start, @current_minute_start + MINUTE_SECONDS)
end
def this(pointer = :future)
View
4 lib/chronic/repeaters/repeater_month.rb
@@ -54,4 +54,8 @@ def offset_by(time, amount, pointer)
def width
MONTH_SECONDS
end
+
+ def to_s
+ super << '-month'
+ end
end
View
2 lib/chronic/repeaters/repeater_month_name.rb
@@ -70,7 +70,7 @@ def index
end
def to_s
- super << '-month-' << @type.to_s
+ super << '-monthname-' << @type.to_s
end
private
View
22 lib/chronic/time_zone.rb
@@ -0,0 +1,22 @@
+module Chronic
+ class TimeZone < Tag #:nodoc:
+ def self.scan(tokens)
+ tokens.each_index do |i|
+ if t = self.scan_for_all(tokens[i]) then tokens[i].tag(t); next end
+ end
+ tokens
+ end
+
+ def self.scan_for_all(token)
+ scanner = {/[PMCE][DS]T/i => :tz}
+ scanner.keys.each do |scanner_item|
+ return self.new(scanner[scanner_item]) if scanner_item =~ token.word
+ end
+ return nil
+ end
+
+ def to_s
+ 'timezone'
+ end
+ end
+end
View
44 test/test_parsing.rb
@@ -136,6 +136,15 @@ def test_parse_guess_dates
time = parse_now("2006-08-20 15:30.30")
assert_equal Time.local(2006, 8, 20, 15, 30, 30), time
+ # rdn_rm_rd_rt_rtz_ry
+
+ time = parse_now("Mon Apr 02 17:00:00 PDT 2007")
+ assert_equal Time.local(2007, 4, 2, 17), time
+
+ now = Time.now
+ time = parse_now(now.to_s)
+ assert_equal now.to_s, time.to_s
+
# rm_sd_rt
#time = parse_now("jan 5 13:00")
@@ -152,11 +161,18 @@ def test_parse_guess_dates
time = parse_now("1800-08-20")
assert_equal nil, time
end
+
+ def test_foo
+ Chronic.parse('two months ago this friday')
+ end
def test_parse_guess_r
time = parse_now("friday")
assert_equal Time.local(2006, 8, 18, 12), time
+ time = parse_now("tue")
+ assert_equal Time.local(2006, 8, 22, 12), time
+
time = parse_now("5")
assert_equal Time.local(2006, 8, 16, 17), time
@@ -214,6 +230,9 @@ def test_parse_guess_rrr
time = parse_now("sunday 6am")
assert_equal Time.local(2006, 8, 20, 6), time
+
+ time = parse_now("friday evening at 7")
+ assert_equal Time.local(2006, 8, 18, 19), time
end
def test_parse_guess_gr
@@ -313,6 +332,11 @@ def test_parse_guess_gr
time = parse_now("tonight")
assert_equal Time.local(2006, 8, 16, 22), time
+ # minute
+
+ time = parse_now("next minute")
+ assert_equal Time.local(2006, 8, 16, 14, 1, 30), time
+
# second
time = parse_now("this second")
@@ -358,8 +382,17 @@ def test_parse_guess_grr
time = parse_now("last week tuesday")
assert_equal Time.local(2006, 8, 8, 12), time
+
+ time = parse_now("tonight at 7")
+ assert_equal Time.local(2006, 8, 16, 19), time
+
+ time = parse_now("tonight 7")
+ assert_equal Time.local(2006, 8, 16, 19), time
+
+ time = parse_now("7 tonight")
+ assert_equal Time.local(2006, 8, 16, 19), time
end
-
+
def test_parse_guess_grrr
time = parse_now("today at 6:00pm")
assert_equal Time.local(2006, 8, 16, 18), time
@@ -372,6 +405,12 @@ def test_parse_guess_grrr
time = parse_now("yesterday at 4:00pm")
assert_equal Time.local(2006, 8, 15, 16), time
+
+ time = parse_now("tomorrow evening at 7")
+ assert_equal Time.local(2006, 8, 17, 19), time
+
+ time = parse_now("tomorrow morning at 5:30")
+ assert_equal Time.local(2006, 8, 17, 5, 30), time
end
def test_parse_guess_rgr
@@ -492,6 +531,9 @@ def test_parse_guess_o_r_s_r
time = parse_now("10th wednesday in november")
assert_equal nil, time
+
+ # time = parse_now("3rd wednesday in 2007")
+ # assert_equal Time.local(2007, 1, 20, 12), time
end
def test_parse_guess_o_r_g_r

0 comments on commit f4fef51

Please sign in to comment.
Something went wrong with that request. Please try again.