chronic 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.md +27 -0
- data/Manifest.txt +16 -5
- data/README.md +14 -8
- data/Rakefile +2 -8
- data/chronic.gemspec +8 -11
- data/lib/chronic.rb +21 -14
- data/lib/chronic/chronic.rb +38 -130
- data/lib/chronic/grabber.rb +11 -15
- data/lib/chronic/handlers.rb +63 -40
- data/lib/chronic/mini_date.rb +27 -0
- data/lib/chronic/numerizer.rb +120 -0
- data/lib/chronic/ordinal.rb +5 -10
- data/lib/chronic/pointer.rb +8 -10
- data/lib/chronic/repeater.rb +106 -109
- data/lib/chronic/repeaters/repeater_day.rb +43 -41
- data/lib/chronic/repeaters/repeater_day_name.rb +38 -36
- data/lib/chronic/repeaters/repeater_day_portion.rb +74 -73
- data/lib/chronic/repeaters/repeater_fortnight.rb +57 -55
- data/lib/chronic/repeaters/repeater_hour.rb +46 -44
- data/lib/chronic/repeaters/repeater_minute.rb +46 -44
- data/lib/chronic/repeaters/repeater_month.rb +52 -50
- data/lib/chronic/repeaters/repeater_month_name.rb +84 -80
- data/lib/chronic/repeaters/repeater_season.rb +97 -119
- data/lib/chronic/repeaters/repeater_season_name.rb +39 -39
- data/lib/chronic/repeaters/repeater_second.rb +32 -30
- data/lib/chronic/repeaters/repeater_time.rb +106 -101
- data/lib/chronic/repeaters/repeater_week.rb +60 -58
- data/lib/chronic/repeaters/repeater_weekday.rb +67 -58
- data/lib/chronic/repeaters/repeater_weekend.rb +54 -52
- data/lib/chronic/repeaters/repeater_year.rb +50 -48
- data/lib/chronic/scalar.rb +24 -16
- data/lib/chronic/separator.rb +15 -33
- data/lib/chronic/span.rb +31 -0
- data/lib/chronic/tag.rb +26 -0
- data/lib/chronic/time_zone.rb +7 -9
- data/lib/chronic/token.rb +35 -0
- data/test/helper.rb +5 -6
- data/test/test_Chronic.rb +5 -0
- data/test/test_Numerizer.rb +60 -39
- data/test/test_RepeaterHour.rb +4 -0
- data/test/test_parsing.rb +104 -13
- metadata +14 -20
- data/lib/chronic/numerizer/numerizer.rb +0 -97
data/lib/chronic/scalar.rb
CHANGED
@@ -1,53 +1,61 @@
|
|
1
1
|
module Chronic
|
2
2
|
|
3
3
|
class Scalar < Tag #:nodoc:
|
4
|
-
|
4
|
+
DAY_PORTIONS = %w( am pm morning afternoon evening night )
|
5
|
+
|
6
|
+
def self.scan(tokens, options)
|
5
7
|
# for each token
|
6
8
|
tokens.each_index do |i|
|
7
|
-
if t =
|
8
|
-
if t =
|
9
|
-
if t =
|
10
|
-
if t =
|
9
|
+
if t = scan_for_scalars(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
|
10
|
+
if t = scan_for_days(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
|
11
|
+
if t = scan_for_months(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
|
12
|
+
if t = scan_for_years(tokens[i], tokens[i + 1], options) then tokens[i].tag(t) end
|
11
13
|
end
|
12
|
-
tokens
|
13
14
|
end
|
14
15
|
|
15
16
|
def self.scan_for_scalars(token, post_token)
|
16
17
|
if token.word =~ /^\d*$/
|
17
|
-
unless post_token &&
|
18
|
+
unless post_token && DAY_PORTIONS.include?(post_token.word)
|
18
19
|
return Scalar.new(token.word.to_i)
|
19
20
|
end
|
20
21
|
end
|
21
|
-
return nil
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.scan_for_days(token, post_token)
|
25
25
|
if token.word =~ /^\d\d?$/
|
26
26
|
toi = token.word.to_i
|
27
|
-
unless toi > 31 || toi < 1 || (post_token &&
|
27
|
+
unless toi > 31 || toi < 1 || (post_token && DAY_PORTIONS.include?(post_token.word))
|
28
28
|
return ScalarDay.new(toi)
|
29
29
|
end
|
30
30
|
end
|
31
|
-
return nil
|
32
31
|
end
|
33
32
|
|
34
33
|
def self.scan_for_months(token, post_token)
|
35
34
|
if token.word =~ /^\d\d?$/
|
36
35
|
toi = token.word.to_i
|
37
|
-
unless toi > 12 || toi < 1 || (post_token &&
|
36
|
+
unless toi > 12 || toi < 1 || (post_token && DAY_PORTIONS.include?(post_token.word))
|
38
37
|
return ScalarMonth.new(toi)
|
39
38
|
end
|
40
39
|
end
|
41
|
-
return nil
|
42
40
|
end
|
43
41
|
|
44
|
-
def self.scan_for_years(token, post_token)
|
42
|
+
def self.scan_for_years(token, post_token, options)
|
45
43
|
if token.word =~ /^([1-9]\d)?\d\d?$/
|
46
|
-
unless post_token &&
|
47
|
-
|
44
|
+
unless post_token && DAY_PORTIONS.include?(post_token.word)
|
45
|
+
year = make_year(token.word.to_i, options[:ambiguous_year_future_bias])
|
46
|
+
return ScalarYear.new(year.to_i)
|
48
47
|
end
|
49
48
|
end
|
50
|
-
|
49
|
+
end
|
50
|
+
|
51
|
+
# Build a year from a 2 digit suffix
|
52
|
+
def self.make_year(year, bias)
|
53
|
+
return year if year.to_s.size > 2
|
54
|
+
start_year = Chronic.time_class.now.year - bias
|
55
|
+
century = (start_year / 100) * 100
|
56
|
+
full_year = century + year
|
57
|
+
full_year += 100 if full_year < start_year
|
58
|
+
full_year
|
51
59
|
end
|
52
60
|
|
53
61
|
def to_s
|
data/lib/chronic/separator.rb
CHANGED
@@ -1,56 +1,38 @@
|
|
1
1
|
module Chronic
|
2
2
|
|
3
3
|
class Separator < Tag #:nodoc:
|
4
|
-
def self.scan(tokens)
|
4
|
+
def self.scan(tokens, options)
|
5
5
|
tokens.each_index do |i|
|
6
|
-
if t =
|
7
|
-
if t =
|
8
|
-
if t =
|
9
|
-
if t =
|
10
|
-
if t =
|
6
|
+
if t = scan_for_commas(tokens[i]) then tokens[i].tag(t); next end
|
7
|
+
if t = scan_for_slash_or_dash(tokens[i]) then tokens[i].tag(t); next end
|
8
|
+
if t = scan_for_at(tokens[i]) then tokens[i].tag(t); next end
|
9
|
+
if t = scan_for_in(tokens[i]) then tokens[i].tag(t); next end
|
10
|
+
if t = scan_for_on(tokens[i]) then tokens[i].tag(t); next end
|
11
11
|
end
|
12
|
-
tokens
|
13
12
|
end
|
14
13
|
|
15
14
|
def self.scan_for_commas(token)
|
16
|
-
|
17
|
-
scanner.keys.each do |scanner_item|
|
18
|
-
return SeparatorComma.new(scanner[scanner_item]) if scanner_item =~ token.word
|
19
|
-
end
|
20
|
-
return nil
|
15
|
+
scan_for token, SeparatorComma, { /^,$/ => :comma }
|
21
16
|
end
|
22
17
|
|
23
18
|
def self.scan_for_slash_or_dash(token)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
return nil
|
19
|
+
scan_for token, SeparatorSlashOrDash,
|
20
|
+
{
|
21
|
+
/^-$/ => :dash,
|
22
|
+
/^\/$/ => :slash
|
23
|
+
}
|
30
24
|
end
|
31
25
|
|
32
26
|
def self.scan_for_at(token)
|
33
|
-
|
34
|
-
scanner.keys.each do |scanner_item|
|
35
|
-
return SeparatorAt.new(scanner[scanner_item]) if scanner_item =~ token.word
|
36
|
-
end
|
37
|
-
return nil
|
27
|
+
scan_for token, SeparatorAt, { /^(at|@)$/ => :at }
|
38
28
|
end
|
39
29
|
|
40
30
|
def self.scan_for_in(token)
|
41
|
-
|
42
|
-
scanner.keys.each do |scanner_item|
|
43
|
-
return SeparatorIn.new(scanner[scanner_item]) if scanner_item =~ token.word
|
44
|
-
end
|
45
|
-
return nil
|
31
|
+
scan_for token, SeparatorIn, { /^in$/ => :in }
|
46
32
|
end
|
47
33
|
|
48
34
|
def self.scan_for_on(token)
|
49
|
-
|
50
|
-
scanner.keys.each do |scanner_item|
|
51
|
-
return SeparatorOn.new(scanner[scanner_item]) if scanner_item =~ token.word
|
52
|
-
end
|
53
|
-
return nil
|
35
|
+
scan_for token, SeparatorOn, { /^on$/ => :on }
|
54
36
|
end
|
55
37
|
|
56
38
|
def to_s
|
data/lib/chronic/span.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Chronic
|
2
|
+
# A Span represents a range of time. Since this class extends
|
3
|
+
# Range, you can use #begin and #end to get the beginning and
|
4
|
+
# ending times of the span (they will be of class Time)
|
5
|
+
class Span < Range
|
6
|
+
# Returns the width of this span in seconds
|
7
|
+
def width
|
8
|
+
(self.end - self.begin).to_i
|
9
|
+
end
|
10
|
+
|
11
|
+
# Add a number of seconds to this span, returning the
|
12
|
+
# resulting Span
|
13
|
+
def +(seconds)
|
14
|
+
Span.new(self.begin + seconds, self.end + seconds)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Subtract a number of seconds to this span, returning the
|
18
|
+
# resulting Span
|
19
|
+
def -(seconds)
|
20
|
+
self + -seconds
|
21
|
+
end
|
22
|
+
|
23
|
+
# Prints this span in a nice fashion
|
24
|
+
def to_s
|
25
|
+
'(' << self.begin.to_s << '..' << self.end.to_s << ')'
|
26
|
+
end
|
27
|
+
|
28
|
+
alias :cover? :include? unless RUBY_VERSION =~ /^1.9/
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/lib/chronic/tag.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Chronic
|
2
|
+
# Tokens are tagged with subclassed instances of this class when
|
3
|
+
# they match specific criteria
|
4
|
+
class Tag #:nodoc:
|
5
|
+
attr_accessor :type
|
6
|
+
|
7
|
+
def initialize(type)
|
8
|
+
@type = type
|
9
|
+
end
|
10
|
+
|
11
|
+
def start=(s)
|
12
|
+
@now = s
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
private
|
17
|
+
|
18
|
+
def scan_for(token, klass, items={})
|
19
|
+
items.each do |item, symbol|
|
20
|
+
return klass.new(symbol) if item =~ token.word
|
21
|
+
end
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/chronic/time_zone.rb
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
module Chronic
|
2
2
|
class TimeZone < Tag #:nodoc:
|
3
|
-
def self.scan(tokens)
|
3
|
+
def self.scan(tokens, options)
|
4
4
|
tokens.each_index do |i|
|
5
|
-
if t =
|
5
|
+
if t = scan_for_all(tokens[i]) then tokens[i].tag(t); next end
|
6
6
|
end
|
7
|
-
tokens
|
8
7
|
end
|
9
8
|
|
10
9
|
def self.scan_for_all(token)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
return nil
|
10
|
+
scan_for token, self,
|
11
|
+
{
|
12
|
+
/[PMCE][DS]T/i => :tz,
|
13
|
+
/(tzminus)?\d{4}/ => :tz
|
14
|
+
}
|
17
15
|
end
|
18
16
|
|
19
17
|
def to_s
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Chronic
|
2
|
+
class Token #:nodoc:
|
3
|
+
attr_accessor :word, :tags
|
4
|
+
|
5
|
+
def initialize(word)
|
6
|
+
@word = word
|
7
|
+
@tags = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# Tag this token with the specified tag
|
11
|
+
def tag(new_tag)
|
12
|
+
@tags << new_tag
|
13
|
+
end
|
14
|
+
|
15
|
+
# Remove all tags of the given class
|
16
|
+
def untag(tag_class)
|
17
|
+
@tags.delete_if { |m| m.kind_of? tag_class }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Return true if this token has any tags
|
21
|
+
def tagged?
|
22
|
+
@tags.size > 0
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return the Tag that matches the given class
|
26
|
+
def get_tag(tag_class)
|
27
|
+
@tags.find { |m| m.kind_of? tag_class }
|
28
|
+
end
|
29
|
+
|
30
|
+
# Print this Token in a pretty way
|
31
|
+
def to_s
|
32
|
+
@word << '(' << @tags.join(', ') << ') '
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/test/helper.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
1
|
+
unless defined? Chronic
|
2
|
+
$:.unshift File.expand_path('../../lib')
|
3
|
+
require 'chronic'
|
4
|
+
end
|
2
5
|
|
3
|
-
|
4
|
-
$LOAD_PATH.unshift(File.join(dir, '..', 'lib'))
|
5
|
-
$LOAD_PATH.unshift(dir)
|
6
|
-
|
7
|
-
require 'chronic'
|
6
|
+
require 'test/unit'
|
data/test/test_Chronic.rb
CHANGED
@@ -7,6 +7,11 @@ class TestChronic < Test::Unit::TestCase
|
|
7
7
|
@now = Time.local(2006, 8, 16, 14, 0, 0, 0)
|
8
8
|
end
|
9
9
|
|
10
|
+
def test_pre_normalize_numerized_string
|
11
|
+
string = 'two and a half years'
|
12
|
+
assert_equal Chronic::Numerizer.numerize(string), Chronic.pre_normalize(string)
|
13
|
+
end
|
14
|
+
|
10
15
|
def test_post_normalize_am_pm_aliases
|
11
16
|
# affect wanted patterns
|
12
17
|
|
data/test/test_Numerizer.rb
CHANGED
@@ -3,49 +3,70 @@ require File.join(File.dirname(__FILE__), *%w[helper])
|
|
3
3
|
class ParseNumbersTest < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def test_straight_parsing
|
6
|
-
strings = {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
6
|
+
strings = {
|
7
|
+
'one' => 1,
|
8
|
+
'five' => 5,
|
9
|
+
'ten' => 10,
|
10
|
+
'eleven' => 11,
|
11
|
+
'twelve' => 12,
|
12
|
+
'thirteen' => 13,
|
13
|
+
'fourteen' => 14,
|
14
|
+
'fifteen' => 15,
|
15
|
+
'sixteen' => 16,
|
16
|
+
'seventeen' => 17,
|
17
|
+
'eighteen' => 18,
|
18
|
+
'nineteen' => 19,
|
19
|
+
'twenty' => 20,
|
20
|
+
'twenty seven' => 27,
|
21
|
+
'thirty-one' => 31,
|
22
|
+
'thirty-seven' => 37,
|
23
|
+
'thirty seven' => 37,
|
24
|
+
'fifty nine' => 59,
|
25
|
+
'forty two' => 42,
|
26
|
+
'fourty two' => 42,
|
27
|
+
# 'a hundred' => 100,
|
28
|
+
'one hundred' => 100,
|
29
|
+
'one hundred and fifty' => 150,
|
30
|
+
# 'one fifty' => 150,
|
31
|
+
'two-hundred' => 200,
|
32
|
+
'5 hundred' => 500,
|
33
|
+
'nine hundred and ninety nine' => 999,
|
34
|
+
'one thousand' => 1000,
|
35
|
+
'twelve hundred' => 1200,
|
36
|
+
'one thousand two hundred' => 1_200,
|
37
|
+
'seventeen thousand' => 17_000,
|
38
|
+
'twentyone-thousand-four-hundred-and-seventy-three' => 21_473,
|
39
|
+
'seventy four thousand and two' => 74_002,
|
40
|
+
'ninety nine thousand nine hundred ninety nine' => 99_999,
|
41
|
+
'100 thousand' => 100_000,
|
42
|
+
'two hundred fifty thousand' => 250_000,
|
43
|
+
'one million' => 1_000_000,
|
44
|
+
'one million two hundred fifty thousand and seven' => 1_250_007,
|
45
|
+
'one billion' => 1_000_000_000,
|
46
|
+
'one billion and one' => 1_000_000_001}
|
42
47
|
|
43
|
-
strings.
|
44
|
-
assert_equal
|
48
|
+
strings.each do |key, val|
|
49
|
+
assert_equal val, Chronic::Numerizer.numerize(key).to_i
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_ordinal_strings
|
54
|
+
{
|
55
|
+
'first' => '1st',
|
56
|
+
'second' => 'second',
|
57
|
+
'second day' => '2nd day',
|
58
|
+
'second of may' => '2nd of may',
|
59
|
+
'fifth' => '5th',
|
60
|
+
'twenty third' => '23rd',
|
61
|
+
'first day month two' => '1st day month 2'
|
62
|
+
}.each do |key, val|
|
63
|
+
# Use pre_normalize here instead of Numerizer directly because
|
64
|
+
# pre_normalize deals with parsing 'second' appropriately
|
65
|
+
assert_equal val, Chronic.pre_normalize(key)
|
45
66
|
end
|
46
67
|
end
|
47
68
|
|
48
69
|
def test_edges
|
49
|
-
assert_equal "27 Oct 2006 7:30am", Numerizer.numerize("27 Oct 2006 7:30am")
|
70
|
+
assert_equal "27 Oct 2006 7:30am", Chronic::Numerizer.numerize("27 Oct 2006 7:30am")
|
50
71
|
end
|
51
72
|
end
|
data/test/test_RepeaterHour.rb
CHANGED
@@ -45,6 +45,10 @@ class TestRepeaterHour < Test::Unit::TestCase
|
|
45
45
|
this_hour = hours.this(:past)
|
46
46
|
assert_equal Time.local(2006, 8, 16, 14), this_hour.begin
|
47
47
|
assert_equal Time.local(2006, 8, 16, 14, 30), this_hour.end
|
48
|
+
|
49
|
+
this_hour = hours.this(:none)
|
50
|
+
assert_equal Time.local(2006, 8, 16, 14), this_hour.begin
|
51
|
+
assert_equal Time.local(2006, 8, 16, 15), this_hour.end
|
48
52
|
end
|
49
53
|
|
50
54
|
def test_offset
|
data/test/test_parsing.rb
CHANGED
@@ -26,6 +26,20 @@ class TestParsing < Test::Unit::TestCase
|
|
26
26
|
time = parse_now("may 28 at 5:32.19pm", :context => :past)
|
27
27
|
assert_equal Time.local(2006, 5, 28, 17, 32, 19), time
|
28
28
|
|
29
|
+
# rm_sd for current month
|
30
|
+
|
31
|
+
time = parse_now("aug 3")
|
32
|
+
assert_equal Time.local(2006, 8, 3, 12), time
|
33
|
+
|
34
|
+
time = parse_now("aug 3", :context => :past)
|
35
|
+
assert_equal Time.local(2006, 8, 3, 12), time
|
36
|
+
|
37
|
+
time = parse_now("aug 20")
|
38
|
+
assert_equal Time.local(2006, 8, 20, 12), time
|
39
|
+
|
40
|
+
time = parse_now("aug 20", :context => :future)
|
41
|
+
assert_equal Time.local(2006, 8, 20, 12), time
|
42
|
+
|
29
43
|
# rm_sd_on
|
30
44
|
|
31
45
|
time = parse_now("5pm on may 28")
|
@@ -59,6 +73,9 @@ class TestParsing < Test::Unit::TestCase
|
|
59
73
|
time = parse_now("5:00 pm may 27th", :context => :past)
|
60
74
|
assert_equal Time.local(2006, 5, 27, 17), time
|
61
75
|
|
76
|
+
time = parse_now("05:00 pm may 27th", :context => :past)
|
77
|
+
assert_equal Time.local(2006, 5, 27, 17), time
|
78
|
+
|
62
79
|
time = parse_now("5pm on may 27th", :context => :past)
|
63
80
|
assert_equal Time.local(2006, 5, 27, 17), time
|
64
81
|
|
@@ -73,8 +90,46 @@ class TestParsing < Test::Unit::TestCase
|
|
73
90
|
time = parse_now("dec 79")
|
74
91
|
assert_equal Time.local(1979, 12, 16, 12), time
|
75
92
|
|
93
|
+
# rm_od_sy
|
94
|
+
|
95
|
+
time = parse_now("November 18th 2010")
|
96
|
+
assert_equal Time.local(2010, 11, 18, 12), time
|
97
|
+
|
98
|
+
time = parse_now("November 18th, 2010")
|
99
|
+
assert_equal Time.local(2010, 11, 18, 12), time
|
100
|
+
|
101
|
+
time = parse_now("November 18th 2010 midnight")
|
102
|
+
assert_equal Time.local(2010, 11, 19, 0), time
|
103
|
+
|
104
|
+
time = parse_now("November 18th 2010 at midnight")
|
105
|
+
assert_equal Time.local(2010, 11, 19, 0), time
|
106
|
+
|
107
|
+
time = parse_now("November 18th 2010 at 4")
|
108
|
+
assert_equal Time.local(2010, 11, 18, 16), time
|
109
|
+
|
110
|
+
time = parse_now("November 18th 2010 at 4", :ambiguous_time_range => :none)
|
111
|
+
assert_equal Time.local(2010, 11, 18, 4), time
|
112
|
+
|
113
|
+
time = parse_now("March 30th, 1979")
|
114
|
+
assert_equal Time.local(1979, 3, 30, 12), time
|
115
|
+
|
116
|
+
time = parse_now("March 30th 79")
|
117
|
+
assert_equal Time.local(1979, 3, 30, 12), time
|
118
|
+
|
119
|
+
time = parse_now("March 30th 79 4:30")
|
120
|
+
assert_equal Time.local(1979, 3, 30, 16, 30), time
|
121
|
+
|
122
|
+
time = parse_now("March 30th 79 at 4:30", :ambiguous_time_range => :none)
|
123
|
+
assert_equal Time.local(1979, 3, 30, 4, 30), time
|
124
|
+
|
76
125
|
# rm_sd_sy
|
77
126
|
|
127
|
+
time = parse_now("November 18, 2010")
|
128
|
+
assert_equal Time.local(2010, 11, 18, 12), time
|
129
|
+
|
130
|
+
time = parse_now("February 14, 2004")
|
131
|
+
assert_equal Time.local(2004, 2, 14, 12), time
|
132
|
+
|
78
133
|
time = parse_now("jan 3 2010")
|
79
134
|
assert_equal Time.local(2010, 1, 3, 12), time
|
80
135
|
|
@@ -170,7 +225,7 @@ class TestParsing < Test::Unit::TestCase
|
|
170
225
|
|
171
226
|
now = Time.now
|
172
227
|
time = parse_now(now.to_s)
|
173
|
-
assert_equal now.to_s, time.to_s
|
228
|
+
# assert_equal now.to_s, time.to_s
|
174
229
|
|
175
230
|
# rm_sd_rt
|
176
231
|
|
@@ -180,15 +235,26 @@ class TestParsing < Test::Unit::TestCase
|
|
180
235
|
# old dates
|
181
236
|
|
182
237
|
time = parse_now("may 40")
|
183
|
-
assert_equal Time.local(
|
238
|
+
assert_equal Time.local(2040, 5, 16, 12, 0, 0), time
|
184
239
|
|
185
240
|
time = parse_now("may 27 40")
|
186
|
-
assert_equal Time.local(
|
241
|
+
assert_equal Time.local(2040, 5, 27, 12, 0, 0), time
|
187
242
|
|
188
243
|
time = parse_now("1800-08-20")
|
189
244
|
assert_equal Time.local(1800, 8, 20, 12, 0, 0), time
|
190
245
|
end
|
191
246
|
|
247
|
+
def test_parse_two_digit_years
|
248
|
+
time = parse_now("may 97")
|
249
|
+
assert_equal Time.local(1997, 5, 16, 12), time
|
250
|
+
|
251
|
+
time = parse_now("may 1st 01")
|
252
|
+
assert_equal Time.local(2001, 5, 1, 12), time
|
253
|
+
|
254
|
+
time = parse_now("may 79", :ambiguous_year_future_bias => 10)
|
255
|
+
assert_equal Time.local(2079, 5, 16, 12), time
|
256
|
+
end
|
257
|
+
|
192
258
|
def test_parse_guess_r
|
193
259
|
time = parse_now("friday")
|
194
260
|
assert_equal Time.local(2006, 8, 18, 12), time
|
@@ -246,6 +312,9 @@ class TestParsing < Test::Unit::TestCase
|
|
246
312
|
time = parse_now("4:00 in the morning")
|
247
313
|
assert_equal Time.local(2006, 8, 16, 4), time
|
248
314
|
|
315
|
+
time = parse_now("0:10")
|
316
|
+
assert_equal Time.local(2006, 8, 17, 0, 10), time
|
317
|
+
|
249
318
|
time = parse_now("november 4")
|
250
319
|
assert_equal Time.local(2006, 11, 4, 12), time
|
251
320
|
|
@@ -325,17 +394,21 @@ class TestParsing < Test::Unit::TestCase
|
|
325
394
|
# day
|
326
395
|
|
327
396
|
time = parse_now("this day")
|
328
|
-
assert_equal Time.local(2006, 8, 16, 19
|
397
|
+
assert_equal Time.local(2006, 8, 16, 19), time
|
329
398
|
|
330
399
|
time = parse_now("this day", :context => :past)
|
331
400
|
assert_equal Time.local(2006, 8, 16, 7), time
|
332
401
|
|
333
402
|
time = parse_now("today")
|
334
|
-
assert_equal Time.local(2006, 8, 16, 19
|
403
|
+
assert_equal Time.local(2006, 8, 16, 19), time
|
335
404
|
|
336
405
|
time = parse_now("yesterday")
|
337
406
|
assert_equal Time.local(2006, 8, 15, 12), time
|
338
407
|
|
408
|
+
now = Time.parse("2011-05-27 23:10") # after 11pm
|
409
|
+
time = parse_now("yesterday", :now => now)
|
410
|
+
assert_equal Time.local(2011, 05, 26, 12), time
|
411
|
+
|
339
412
|
time = parse_now("tomorrow")
|
340
413
|
assert_equal Time.local(2006, 8, 17, 12), time
|
341
414
|
|
@@ -452,6 +525,10 @@ class TestParsing < Test::Unit::TestCase
|
|
452
525
|
|
453
526
|
time = parse_now("next monday at 12:01 pm")
|
454
527
|
assert_equal Time.local(2006, 8, 21, 12, 1), time
|
528
|
+
|
529
|
+
# with context
|
530
|
+
time = parse_now("sunday at 8:15pm", :context => :past)
|
531
|
+
assert_equal Time.local(2006, 8, 13, 20, 15), time
|
455
532
|
end
|
456
533
|
|
457
534
|
def test_parse_guess_rgr
|
@@ -578,12 +655,19 @@ class TestParsing < Test::Unit::TestCase
|
|
578
655
|
end
|
579
656
|
|
580
657
|
def test_parse_guess_o_r_g_r
|
581
|
-
time = parse_now("3rd month next year")
|
582
|
-
assert_equal Time.local(2007, 3
|
658
|
+
time = parse_now("3rd month next year", :guess => false)
|
659
|
+
assert_equal Time.local(2007, 3), time.begin
|
660
|
+
|
661
|
+
time = parse_now("3rd month next year", :guess => false)
|
662
|
+
assert_equal Time.local(2007, 3, 1), time.begin
|
583
663
|
|
584
664
|
time = parse_now("3rd thursday this september")
|
585
665
|
assert_equal Time.local(2006, 9, 21, 12), time
|
586
666
|
|
667
|
+
now = Time.parse("1/10/2010")
|
668
|
+
time = parse_now("3rd thursday this november", :now => now)
|
669
|
+
assert_equal Time.local(2010, 11, 18, 12), time
|
670
|
+
|
587
671
|
time = parse_now("4th day last week")
|
588
672
|
assert_equal Time.local(2006, 8, 9, 12), time
|
589
673
|
end
|
@@ -662,16 +746,16 @@ class TestParsing < Test::Unit::TestCase
|
|
662
746
|
assert_equal Time.local(2007, 6, 20), t.end
|
663
747
|
|
664
748
|
t = parse_now("this winter", :guess => false)
|
665
|
-
assert_equal Time.local(2006, 12, 22
|
749
|
+
assert_equal Time.local(2006, 12, 22), t.begin
|
666
750
|
assert_equal Time.local(2007, 3, 19), t.end
|
667
751
|
|
668
752
|
t = parse_now("last spring", :guess => false)
|
669
|
-
assert_equal Time.local(2006, 3, 20
|
753
|
+
assert_equal Time.local(2006, 3, 20), t.begin
|
670
754
|
assert_equal Time.local(2006, 6, 20), t.end
|
671
755
|
|
672
756
|
t = parse_now("last winter", :guess => false)
|
673
|
-
assert_equal Time.local(2005, 12, 22
|
674
|
-
assert_equal Time.local(2006, 3, 19
|
757
|
+
assert_equal Time.local(2005, 12, 22), t.begin
|
758
|
+
assert_equal Time.local(2006, 3, 19), t.end
|
675
759
|
|
676
760
|
t = parse_now("next spring", :guess => false)
|
677
761
|
assert_equal Time.local(2007, 3, 20), t.begin
|
@@ -694,8 +778,8 @@ class TestParsing < Test::Unit::TestCase
|
|
694
778
|
t1 = Chronic.parse('1st saturday in november', :now => Time.local(2007))
|
695
779
|
assert_equal Time.local(2007, 11, 3, 12), t1
|
696
780
|
|
697
|
-
t1 = Chronic.parse('1st sunday in november', :now => Time.local(2007))
|
698
|
-
assert_equal Time.local(2007, 11, 4,
|
781
|
+
# t1 = Chronic.parse('1st sunday in november', :now => Time.local(2007))
|
782
|
+
# assert_equal Time.local(2007, 11, 4, 12), t1
|
699
783
|
|
700
784
|
# Chronic.debug = true
|
701
785
|
#
|
@@ -703,6 +787,13 @@ class TestParsing < Test::Unit::TestCase
|
|
703
787
|
# assert_equal Time.local(2007, 11, 5, 11), t1
|
704
788
|
end
|
705
789
|
|
790
|
+
def test_now_changes
|
791
|
+
t1 = Chronic.parse("now")
|
792
|
+
sleep 0.1
|
793
|
+
t2 = Chronic.parse("now")
|
794
|
+
assert_not_equal t1, t2
|
795
|
+
end
|
796
|
+
|
706
797
|
private
|
707
798
|
def parse_now(string, options={})
|
708
799
|
Chronic.parse(string, {:now => TIME_2006_08_16_14_00_00 }.merge(options))
|