chronic-davispuh 0.10.2.v0.1da32066b3f46f2506b3471e39557497e34afa27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +3 -0
  5. data/HISTORY.md +243 -0
  6. data/LICENSE +21 -0
  7. data/README.md +185 -0
  8. data/Rakefile +68 -0
  9. data/chronic.gemspec +27 -0
  10. data/lib/chronic.rb +122 -0
  11. data/lib/chronic/arrow.rb +270 -0
  12. data/lib/chronic/date.rb +272 -0
  13. data/lib/chronic/definition.rb +208 -0
  14. data/lib/chronic/dictionary.rb +36 -0
  15. data/lib/chronic/handler.rb +44 -0
  16. data/lib/chronic/handlers/anchor.rb +65 -0
  17. data/lib/chronic/handlers/arrow.rb +84 -0
  18. data/lib/chronic/handlers/date.rb +270 -0
  19. data/lib/chronic/handlers/date_time.rb +72 -0
  20. data/lib/chronic/handlers/general.rb +130 -0
  21. data/lib/chronic/handlers/narrow.rb +54 -0
  22. data/lib/chronic/handlers/time.rb +167 -0
  23. data/lib/chronic/handlers/time_zone.rb +50 -0
  24. data/lib/chronic/objects/anchor_object.rb +263 -0
  25. data/lib/chronic/objects/arrow_object.rb +27 -0
  26. data/lib/chronic/objects/date_object.rb +164 -0
  27. data/lib/chronic/objects/date_time_object.rb +64 -0
  28. data/lib/chronic/objects/handler_object.rb +81 -0
  29. data/lib/chronic/objects/narrow_object.rb +85 -0
  30. data/lib/chronic/objects/time_object.rb +96 -0
  31. data/lib/chronic/objects/time_zone_object.rb +27 -0
  32. data/lib/chronic/parser.rb +154 -0
  33. data/lib/chronic/span.rb +32 -0
  34. data/lib/chronic/tag.rb +84 -0
  35. data/lib/chronic/tags/day_name.rb +34 -0
  36. data/lib/chronic/tags/day_portion.rb +33 -0
  37. data/lib/chronic/tags/day_special.rb +30 -0
  38. data/lib/chronic/tags/grabber.rb +29 -0
  39. data/lib/chronic/tags/keyword.rb +63 -0
  40. data/lib/chronic/tags/month_name.rb +39 -0
  41. data/lib/chronic/tags/ordinal.rb +52 -0
  42. data/lib/chronic/tags/pointer.rb +28 -0
  43. data/lib/chronic/tags/rational.rb +35 -0
  44. data/lib/chronic/tags/scalar.rb +101 -0
  45. data/lib/chronic/tags/season_name.rb +31 -0
  46. data/lib/chronic/tags/separator.rb +130 -0
  47. data/lib/chronic/tags/sign.rb +35 -0
  48. data/lib/chronic/tags/time_special.rb +34 -0
  49. data/lib/chronic/tags/time_zone.rb +56 -0
  50. data/lib/chronic/tags/unit.rb +174 -0
  51. data/lib/chronic/time.rb +141 -0
  52. data/lib/chronic/time_zone.rb +80 -0
  53. data/lib/chronic/token.rb +61 -0
  54. data/lib/chronic/token_group.rb +271 -0
  55. data/lib/chronic/tokenizer.rb +42 -0
  56. data/lib/chronic/version.rb +3 -0
  57. data/test/helper.rb +12 -0
  58. data/test/test_chronic.rb +190 -0
  59. data/test/test_daylight_savings.rb +98 -0
  60. data/test/test_handler.rb +113 -0
  61. data/test/test_parsing.rb +1520 -0
  62. data/test/test_span.rb +23 -0
  63. data/test/test_token.rb +31 -0
  64. metadata +218 -0
@@ -0,0 +1,42 @@
1
+ module Chronic
2
+ module Tokenizer
3
+ def self.char_type(char)
4
+ case char
5
+ when '.'
6
+ :period
7
+ when /[[:alpha:]]/
8
+ :letter
9
+ when /[[:digit:]]/
10
+ :digit
11
+ when /[[:space:]]/
12
+ :space
13
+ when /[[:punct:]]/
14
+ :punct
15
+ else
16
+ :other
17
+ end
18
+ end
19
+
20
+ # Proccess text to tokens
21
+ def self.tokenize(text)
22
+ tokens = []
23
+ index = 0
24
+ previos_index = 0
25
+ previos_type = nil
26
+ text.each_char do |char|
27
+ type = char_type(char)
28
+ if previos_type and type != previos_type
29
+ if not (previos_type == :letter and type == :period)
30
+ tokens << Token.new(text[previos_index...index], text, previos_index)
31
+ previos_index = index
32
+ end
33
+ end
34
+ previos_type = type
35
+ index += 1
36
+ end
37
+ tokens << Token.new(text[previos_index...index], text, previos_index)
38
+ tokens
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ module Chronic
2
+ VERSION = '0.10.2.v0.1da32066b3f46f2506b3471e39557497e34afa27'
3
+ end
@@ -0,0 +1,12 @@
1
+ unless defined? Chronic
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'chronic'
4
+ end
5
+
6
+ require 'minitest/autorun'
7
+
8
+ class TestCase < MiniTest::Test
9
+ def self.test(name, &block)
10
+ define_method("test_#{name.gsub(/\W/, '_')}", &block) if block
11
+ end
12
+ end
@@ -0,0 +1,190 @@
1
+ require 'helper'
2
+
3
+ class TestChronic < TestCase
4
+
5
+ def setup
6
+ # Wed Aug 16 14:00:00 UTC 2006
7
+ @now = Time.local(2006, 8, 16, 14, 0, 0, 0)
8
+ end
9
+
10
+ def test_pre_normalize
11
+ assert_equal Chronic::Parser.new.pre_normalize('three quarters'), Chronic::Parser.new.pre_normalize('3 quarters')
12
+ assert_equal Chronic::Parser.new.pre_normalize('one second'), Chronic::Parser.new.pre_normalize('1 second')
13
+ assert_equal Chronic::Parser.new.pre_normalize('third'), Chronic::Parser.new.pre_normalize('3rd')
14
+ assert_equal Chronic::Parser.new.pre_normalize('fourth'), Chronic::Parser.new.pre_normalize('4th')
15
+ end
16
+
17
+ def test_pre_normalize_numerized_string
18
+ string = 'two and a half years'
19
+ assert_equal Numerizer.numerize(string), Chronic::Parser.new.pre_normalize(string)
20
+ end
21
+
22
+ def test_post_normalize_am_pm_aliases
23
+ # affect wanted patterns
24
+
25
+ tokens = [Chronic::Token.new("5"), Chronic::Token.new("morning")]
26
+ tokens[0].tag(Chronic::ScalarHour.new("5", 1))
27
+ tokens[1].tag(Chronic::TimeSpecial.new(:morning))
28
+
29
+ assert_equal :morning, tokens[1].tags[0].type
30
+ assert_equal 2, tokens.size
31
+
32
+ # don't affect unwanted patterns
33
+
34
+ tokens = [Chronic::Token.new("friday"), Chronic::Token.new("morning")]
35
+ tokens[0].tag(Chronic::DayName.new(:friday))
36
+ tokens[1].tag(Chronic::TimeSpecial.new(:morning))
37
+
38
+ assert_equal :morning, tokens[1].tags[0].type
39
+
40
+ assert_equal 2, tokens.size
41
+ end
42
+
43
+ def test_guess
44
+ span = Chronic::Span.new(Time.local(2006, 8, 16, 0), Time.local(2006, 8, 17, 0))
45
+ assert_equal Time.local(2006, 8, 16, 12), Chronic::Parser.new.guess(span)
46
+
47
+ span = Chronic::Span.new(Time.local(2006, 8, 16, 0), Time.local(2006, 8, 17, 0, 0, 1))
48
+ assert_equal Time.local(2006, 8, 16, 12), Chronic::Parser.new.guess(span)
49
+
50
+ span = Chronic::Span.new(Time.local(2006, 11), Time.local(2006, 12))
51
+ assert_equal Time.local(2006, 11, 16), Chronic::Parser.new.guess(span)
52
+ end
53
+
54
+ def test_endian_definitions
55
+ middle = Chronic::EndianDefinitions.middle
56
+ little = Chronic::EndianDefinitions.little
57
+
58
+ assert_equal middle + little, Chronic::SpanDictionary.new.definitions[:endian]
59
+
60
+ defs = Chronic::SpanDictionary.new(:endian_precedence => :little).definitions
61
+ assert_equal little, defs[:endian]
62
+
63
+ defs = Chronic::SpanDictionary.new(:endian_precedence => [:little, :middle]).definitions
64
+ assert_equal little + middle, defs[:endian]
65
+
66
+ assert_raises(ArgumentError) do
67
+ Chronic::SpanDictionary.new(:endian_precedence => :invalid).definitions
68
+ end
69
+ end
70
+
71
+ def test_debug
72
+ require 'stringio'
73
+ $stdout = StringIO.new
74
+ Chronic.debug = true
75
+
76
+ Chronic.parse 'now'
77
+ assert $stdout.string.include?('now(timespecial-now)')
78
+ ensure
79
+ $stdout = STDOUT
80
+ Chronic.debug = false
81
+ end
82
+
83
+ # Chronic.construct
84
+
85
+ def test_normal
86
+ assert_equal Time.local(2006, 1, 2, 0, 0, 0), Chronic.construct(2006, 1, 2, 0, 0, 0)
87
+ assert_equal Time.local(2006, 1, 2, 3, 0, 0), Chronic.construct(2006, 1, 2, 3, 0, 0)
88
+ assert_equal Time.local(2006, 1, 2, 3, 4, 0), Chronic.construct(2006, 1, 2, 3, 4, 0)
89
+ assert_equal Time.local(2006, 1, 2, 3, 4, 5), Chronic.construct(2006, 1, 2, 3, 4, 5)
90
+ end
91
+
92
+ def test_second_overflow
93
+ assert_equal Time.local(2006, 1, 1, 0, 1, 30), Chronic.construct(2006, 1, 1, 0, 0, 90)
94
+ assert_equal Time.local(2006, 1, 1, 0, 5, 0), Chronic.construct(2006, 1, 1, 0, 0, 300)
95
+ end
96
+
97
+ def test_minute_overflow
98
+ assert_equal Time.local(2006, 1, 1, 1, 30), Chronic.construct(2006, 1, 1, 0, 90)
99
+ assert_equal Time.local(2006, 1, 1, 5), Chronic.construct(2006, 1, 1, 0, 300)
100
+ end
101
+
102
+ def test_hour_overflow
103
+ assert_equal Time.local(2006, 1, 2, 12), Chronic.construct(2006, 1, 1, 36)
104
+ assert_equal Time.local(2006, 1, 7), Chronic.construct(2006, 1, 1, 144)
105
+ end
106
+
107
+ def test_day_overflow
108
+ assert_equal Time.local(2006, 2, 1), Chronic.construct(2006, 1, 32)
109
+ assert_equal Time.local(2006, 3, 5), Chronic.construct(2006, 2, 33)
110
+ assert_equal Time.local(2004, 3, 4), Chronic.construct(2004, 2, 33)
111
+ assert_equal Time.local(2000, 3, 4), Chronic.construct(2000, 2, 33)
112
+ assert_equal Time.local(2006, 2, 26), Chronic.construct(2006, 1, 57)
113
+ end
114
+
115
+ def test_month_overflow
116
+ assert_equal Time.local(2006, 1), Chronic.construct(2005, 13)
117
+ assert_equal Time.local(2005, 12), Chronic.construct(2000, 72)
118
+ end
119
+
120
+ def test_time
121
+ org = Chronic.time_class
122
+ begin
123
+ Chronic.time_class = ::Time
124
+ assert_equal ::Time.new(2013, 8, 27, 20, 30, 40, '+05:30'), Chronic.construct(2013, 8, 27, 20, 30, 40, '+05:30')
125
+ assert_equal ::Time.new(2013, 8, 27, 20, 30, 40, '-08:00'), Chronic.construct(2013, 8, 27, 20, 30, 40, -28800)
126
+ ensure
127
+ Chronic.time_class = org
128
+ end
129
+ end
130
+
131
+ def test_date
132
+ org = Chronic.time_class
133
+ begin
134
+ Chronic.time_class = ::Date
135
+ assert_equal Date.new(2013, 8, 27), Chronic.construct(2013, 8, 27)
136
+ ensure
137
+ Chronic.time_class = org
138
+ end
139
+ end
140
+
141
+ def test_datetime
142
+ org = Chronic.time_class
143
+ begin
144
+ Chronic.time_class = ::DateTime
145
+ assert_equal DateTime.new(2013, 8, 27, 20, 30, 40, '+05:30'), Chronic.construct(2013, 8, 27, 20, 30, 40, '+05:30')
146
+ assert_equal DateTime.new(2013, 8, 27, 20, 30, 40, '-08:00'), Chronic.construct(2013, 8, 27, 20, 30, 40, -28800)
147
+ ensure
148
+ Chronic.time_class = org
149
+ end
150
+ end
151
+
152
+ def test_valid_options
153
+ options = {
154
+ :context => :future,
155
+ :now => nil,
156
+ :hours24 => nil,
157
+ :week_start => :sunday,
158
+ :guess => true,
159
+ :ambiguous_time_range => 6,
160
+ :endian_precedence => [:middle, :little],
161
+ :ambiguous_year_future_bias => 50
162
+ }
163
+ refute_nil Chronic.parse('now', options)
164
+ end
165
+
166
+ def test_invalid_options
167
+ assert_raises(ArgumentError) { Chronic.parse('now', foo: 'boo') }
168
+ assert_raises(ArgumentError) { Chronic.parse('now', time_class: Time) }
169
+ end
170
+
171
+ def test_activesupport
172
+ =begin
173
+ # ActiveSupport needs MiniTest '~> 4.2' which conflicts with '~> 5.0'
174
+ require 'active_support/time'
175
+ org = Chronic.time_class
176
+ org_zone = ::Time.zone
177
+ begin
178
+ ::Time.zone = "Tokyo"
179
+ Chronic.time_class = ::Time.zone
180
+ assert_equal Time.new(2013, 8, 27, 20, 30, 40, '+09:00'), Chronic.construct(2013, 8, 27, 20, 30, 40)
181
+ ::Time.zone = "Indiana (East)"
182
+ Chronic.time_class = ::Time.zone
183
+ assert_equal Time.new(2013, 8, 27, 20, 30, 40, -14400), Chronic.construct(2013, 8, 27, 20, 30, 40)
184
+ ensure
185
+ Chronic.time_class = org
186
+ ::Time.zone = org_zone
187
+ end
188
+ =end
189
+ end
190
+ end
@@ -0,0 +1,98 @@
1
+ require 'helper'
2
+
3
+ class TestDaylightSavings < TestCase
4
+
5
+ def setup
6
+ @begin_daylight_savings = Time.local(2008, 3, 9, 5, 0, 0, 0)
7
+ @end_daylight_savings = Time.local(2008, 11, 2, 5, 0, 0, 0)
8
+ end
9
+
10
+ def test_begin_past
11
+ # resolve to last night
12
+ t = Chronic.parse('9:00 PM', :guess => false, :context => :past, :now => @begin_daylight_savings)
13
+ assert_equal Time.local(2008, 3, 8, 21), t.begin
14
+
15
+ # resolve to this afternoon
16
+ t = Chronic.parse('9:00 PM', :guess => false, :context => :none, :now => Time.local(2008, 3, 9, 22, 0, 0, 0))
17
+ assert_equal Time.local(2008, 3, 9, 21), t.begin
18
+
19
+ # resolve to this morning
20
+ t = Chronic.parse('4:00 AM', :guess => false, :context => :none, :now => @begin_daylight_savings)
21
+ assert_equal Time.local(2008, 3, 9, 4), t.begin
22
+
23
+ # resolve to today
24
+ t = Chronic.parse('04:00', :guess => false, :context => :none, :now => @begin_daylight_savings)
25
+ assert_equal Time.local(2008, 3, 9, 4), t.begin
26
+
27
+ # resolve to yesterday
28
+ t = Chronic.parse('13:00', :guess => false, :context => :past, :now => @begin_daylight_savings)
29
+ assert_equal Time.local(2008, 3, 8, 13), t.begin
30
+ end
31
+
32
+ def test_begin_future
33
+ # resolve to this morning
34
+ t = Chronic.parse('9:00 AM', :guess => false, :now => @begin_daylight_savings)
35
+ assert_equal Time.local(2008, 3, 9, 9), t.begin
36
+
37
+ # resolve to this afternoon
38
+ t = Chronic.parse('9:00 PM', :guess => false, :now => Time.local(2008, 3, 9, 13, 0, 0, 0))
39
+ assert_equal Time.local(2008, 3, 9, 21), t.begin
40
+
41
+ # resolve to tomorrow
42
+ t = Chronic.parse('9:00', :guess => false, :now => Time.local(2008, 3, 9, 22, 0, 0, 0))
43
+ assert_equal Time.local(2008, 3, 10, 9), t.begin
44
+
45
+ # resolve to today
46
+ t = Chronic.parse('09:00', :guess => false, :now => @begin_daylight_savings)
47
+ assert_equal Time.local(2008, 3, 9, 9), t.begin
48
+
49
+ # resolve to tomorrow
50
+ t = Chronic.parse('04:00', :guess => false, :now => @begin_daylight_savings)
51
+ assert_equal Time.local(2008, 3, 10, 4), t.begin
52
+ end
53
+
54
+ def test_end_past
55
+ # resolve to last night
56
+ t = Chronic.parse('9:00 PM', :guess => false, :context => :past, :now => @end_daylight_savings)
57
+ assert_equal Time.local(2008, 11, 1, 21), t.begin
58
+
59
+ # resolve to this afternoon
60
+ t = Chronic.parse('9:00 PM', :guess => false, :context => :none, :now => Time.local(2008, 11, 2, 22, 0, 0, 0))
61
+ assert_equal Time.local(2008, 11, 2, 21), t.begin
62
+
63
+ # resolve to this morning
64
+ t = Chronic.parse('4:00', :guess => false, :context => :none, :now => @end_daylight_savings)
65
+ assert_equal Time.local(2008, 11, 2, 4), t.begin
66
+
67
+ # resolve to today
68
+ t = Chronic.parse('04:00', :guess => false, :context => :none, :now => @end_daylight_savings)
69
+ assert_equal Time.local(2008, 11, 2, 4), t.begin
70
+
71
+ # resolve to yesterday
72
+ t = Chronic.parse('13:00', :guess => false, :context => :past, :now => @end_daylight_savings)
73
+ assert_equal Time.local(2008, 11, 1, 13), t.begin
74
+ end
75
+
76
+ def test_end_future
77
+ # resolve to this morning
78
+ t = Chronic.parse('at 9:00', :guess => false, :now => @end_daylight_savings)
79
+ assert_equal Time.local(2008, 11, 2, 9), t.begin
80
+
81
+ # resolve to this afternoon
82
+ t = Chronic.parse('9:00 PM', :guess => false, :now => Time.local(2008, 11, 2, 13, 0, 0, 0))
83
+ assert_equal Time.local(2008, 11, 2, 21), t.begin
84
+
85
+ # resolve to tomorrow
86
+ t = Chronic.parse('9:00', :guess => false, :now => Time.local(2008, 11, 2, 22, 0, 0, 0))
87
+ assert_equal Time.local(2008, 11, 3, 9), t.begin
88
+
89
+ # resolve to today
90
+ t = Chronic.parse('09:00', :guess => false, :now => @end_daylight_savings)
91
+ assert_equal Time.local(2008, 11, 2, 9), t.begin
92
+
93
+ # resolve to tomorrow
94
+ t = Chronic.parse('04:00', :guess => false, :now => @end_daylight_savings)
95
+ assert_equal Time.local(2008, 11, 3, 4), t.begin
96
+ end
97
+
98
+ end
@@ -0,0 +1,113 @@
1
+ require_relative 'helper'
2
+
3
+ class TestHandler < TestCase
4
+
5
+ def setup
6
+ # Wed Aug 16 14:00:00 UTC 2006
7
+ @now = Time.local(2006, 8, 16, 14, 0, 0, 0)
8
+ end
9
+
10
+ def definitions
11
+ @definitions ||= Chronic::SpanDictionary.new.definitions
12
+ end
13
+
14
+ def test_handler_class_1
15
+ tokens = [Chronic::Token.new('friday')]
16
+ tokens[0].tag(Chronic::DayName.new(:friday))
17
+
18
+ assert Chronic::Handler.match(tokens, 0, [Chronic::DayName])
19
+
20
+ tokens << Chronic::Token.new('afternoon')
21
+ tokens[1].tag(Chronic::TimeSpecial.new(:afternoon))
22
+
23
+ assert !Chronic::Handler.match(tokens, 1, [Chronic::DayName])
24
+ end
25
+
26
+ def test_handler_class_2
27
+ tokens = [Chronic::Token.new('friday')]
28
+ tokens[0].tag(Chronic::DayName.new(:friday))
29
+
30
+ assert !Chronic::Handler.match(tokens, 0, [Chronic::TimeSpecial])
31
+
32
+ tokens << Chronic::Token.new('afternoon')
33
+ tokens[1].tag(Chronic::TimeSpecial.new(:afternoon))
34
+
35
+ assert Chronic::Handler.match(tokens, 1, [Chronic::TimeSpecial])
36
+
37
+ tokens << Chronic::Token.new('afternoon')
38
+ tokens[2].tag(Chronic::TimeSpecial.new(:afternoon))
39
+
40
+ assert Chronic::Handler.match(tokens, 1, [Chronic::TimeSpecial, Chronic::TimeSpecial])
41
+ end
42
+
43
+ def test_handler_class_3
44
+ tokens = [Chronic::Token.new('friday')]
45
+ tokens[0].tag(Chronic::DayName.new(:friday))
46
+
47
+ assert !Chronic::Handler.match(tokens, 0, [Chronic::DayName, Chronic::TimeSpecial])
48
+
49
+ tokens << Chronic::Token.new('afternoon')
50
+ tokens[1].tag(Chronic::TimeSpecial.new(:afternoon))
51
+
52
+ assert Chronic::Handler.match(tokens, 0, [Chronic::DayName, Chronic::TimeSpecial])
53
+ end
54
+
55
+ def test_handler_class_4
56
+ tokens = [Chronic::Token.new('may')]
57
+ tokens[0].tag(Chronic::MonthName.new(:may))
58
+
59
+ assert !Chronic::Handler.match(tokens, 0, [Chronic::MonthName, Chronic::ScalarDay])
60
+
61
+ tokens << Chronic::Token.new('27')
62
+ tokens[1].tag(Chronic::ScalarDay.new(27))
63
+
64
+ assert Chronic::Handler.match(tokens, 0, [Chronic::MonthName, Chronic::ScalarDay])
65
+ end
66
+
67
+ def test_handler_class_5
68
+ tokens = [Chronic::Token.new('friday')]
69
+ tokens[0].tag(Chronic::DayName.new(:friday))
70
+
71
+ assert !Chronic::Handler.match(tokens, 0, [Chronic::DayName, Chronic::ScalarHour])
72
+
73
+ tokens << Chronic::Token.new('5')
74
+ tokens[1].tag(Chronic::ScalarHour.new('5'))
75
+
76
+ assert Chronic::Handler.match(tokens, 0, [Chronic::DayName, Chronic::ScalarHour])
77
+
78
+ tokens << Chronic::Token.new('pm')
79
+ tokens[2].tag(Chronic::DayPortion.new(:pm))
80
+
81
+ assert Chronic::Handler.match(tokens, 0, [Chronic::DayName, Chronic::ScalarHour, Chronic::DayPortion])
82
+ end
83
+
84
+ def test_handler_class_6
85
+ tokens = [Chronic::Token.new('3'),
86
+ Chronic::Token.new('years'),
87
+ Chronic::Token.new('past')]
88
+
89
+ tokens[0].tag(Chronic::Scalar.new(3))
90
+ tokens[1].tag(Chronic::UnitYear.new(:year))
91
+ tokens[2].tag(Chronic::Pointer.new(:past))
92
+
93
+ assert Chronic::Handler.match(tokens, 0, [Chronic::Scalar, Chronic::UnitYear, Chronic::Pointer])
94
+ end
95
+
96
+ def test_handler_class_7
97
+ tokens = [Chronic::Token.new('at'),
98
+ Chronic::Token.new('14')]
99
+
100
+ tokens[0].tag(Chronic::SeparatorAt.new('at'))
101
+ tokens[1].tag(Chronic::Scalar.new(14))
102
+
103
+ assert Chronic::Handler.match(tokens, 0, [Chronic::SeparatorAt, Chronic::Scalar])
104
+
105
+ tokens = [Chronic::Token.new('on'),
106
+ Chronic::Token.new('15')]
107
+
108
+ tokens[0].tag(Chronic::SeparatorOn.new('on'))
109
+ tokens[1].tag(Chronic::Scalar.new(15))
110
+
111
+ assert Chronic::Handler.match(tokens, 0, [Chronic::SeparatorOn, Chronic::Scalar])
112
+ end
113
+ end