todo_time_patterns 0.0.0

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.
@@ -0,0 +1,36 @@
1
+ require_relative 'todo_time_patterns/parser'
2
+ require_relative 'todo_time_patterns/time_patterns_finder'
3
+
4
+ class TodoTimePatterns
5
+ def self.parse(input)
6
+ parser = TimePatterns::Parser.new
7
+ tokens = parser.parse input
8
+
9
+ time_patterns_finder = TimePatterns::TimePatternsFinder.new
10
+ tokens_with_time_patterns = time_patterns_finder.find_and_update tokens
11
+
12
+ result = generate_result(tokens_with_time_patterns, input)
13
+
14
+ result
15
+ end
16
+
17
+ def self.generate_result(tokens, input)
18
+ time_token = tokens.find {|token| token.to_s == "{ending_form}"}
19
+
20
+ unless time_token.nil?
21
+ time_token = tokens.find {|token| token.to_s == "{ending_form}"}
22
+ to_remove = input.slice(time_token.start_index, time_token.end_index - time_token.start_index + 1)
23
+
24
+ {
25
+ hours: time_token.hours,
26
+ minutes: time_token.minutes,
27
+ interval: time_token.interval,
28
+ result_string: input.sub(to_remove, "").sub(" ", " ").strip
29
+ }
30
+ else
31
+ nil
32
+ end
33
+ end
34
+
35
+ private_class_method :generate_result
36
+ end
@@ -0,0 +1,7 @@
1
+ module TimePatterns
2
+ module TokensStringRepresentation
3
+ def to_s
4
+ self.each_with_object("") { |token, result| result << token.to_s }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,47 @@
1
+ require_relative 'parser_helpers'
2
+ require_relative 'tokens'
3
+ require_relative 'helper_modules'
4
+
5
+ module TimePatterns
6
+ class Parser
7
+ def initialize
8
+ @parser_checks = {
9
+ letter?: WordToken,
10
+ number?: NumberToken,
11
+ symbol?: SymbToken,
12
+ unknown?: UnknownToken
13
+ }
14
+ end
15
+
16
+ def parse(input)
17
+
18
+ i = 0
19
+ buffer = ""
20
+ tokens = []
21
+
22
+ while input[i]
23
+ break if input[i] == nil
24
+
25
+ while input[i] == " "
26
+ i += 1
27
+ end
28
+
29
+ @parser_checks.each do |check_method, check_class|
30
+ token_start_index = i
31
+ while input[i] != nil and input[i] != " " and input[i].send check_method
32
+ buffer << input[i]
33
+ i += 1
34
+ end
35
+
36
+ unless buffer.empty?
37
+ tokens << (check_class.new buffer, token_start_index)
38
+ buffer = ""
39
+ end
40
+ end
41
+ end
42
+
43
+ tokens.extend(TokensStringRepresentation)
44
+ tokens
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ class String
2
+ def letter?
3
+ ('a'..'z').include?(self) or ('A'..'Z').include?(self)
4
+ end
5
+
6
+ def number?
7
+ true if Integer(self) rescue false
8
+ end
9
+
10
+ def symbol?
11
+ [':', '#'].include?(self)
12
+ end
13
+
14
+ def unknown?
15
+ not letter? and not number?
16
+ end
17
+ end
@@ -0,0 +1,148 @@
1
+ require_relative 'helper_modules'
2
+
3
+ module TimePatterns
4
+ class TimePattern
5
+ def initialize(pattern_array, token_class)
6
+ @pattern = pattern_array.join
7
+ @number_of_pattern_tokens = pattern_array.length
8
+ @token_class = token_class
9
+ end
10
+
11
+ def find_and_update(tokens)
12
+ return tokens unless tokens.to_s.include? @pattern
13
+
14
+ tokens_clone = tokens.clone
15
+ tokens.each_cons(@number_of_pattern_tokens) do |tokens_set|
16
+ break unless tokens_set.length == @number_of_pattern_tokens
17
+
18
+ tokens_set.extend(TokensStringRepresentation)
19
+
20
+ if tokens_set.to_s == @pattern
21
+ next unless valid? tokens_set
22
+
23
+ time_token = @token_class.new tokens_set
24
+ substitute_tokens tokens_set, time_token, tokens_clone
25
+ end
26
+ end
27
+
28
+ tokens_clone
29
+ end
30
+
31
+ private
32
+ def substitute_tokens(old, new, tokens)
33
+ index = tokens.index old[0]
34
+ tokens.delete_if {|token| old.include? token}
35
+ tokens.insert index, new
36
+ end
37
+ end
38
+
39
+ class TimeWithModifierPattern < TimePattern
40
+ def initialize
41
+ super(%w[{number} {word}], TimeToken)
42
+ end
43
+
44
+ def valid?(tokens_pair)
45
+ hour, modifier = tokens_pair.map { |token| token.value }
46
+ (0..12).include?(hour) and ["am", "pm"].include?(modifier) and not
47
+ (hour == 0 and modifier == "pm")
48
+ end
49
+ end
50
+
51
+ class ClassicTimePattern < TimePattern
52
+ def initialize
53
+ super(%w[{number} {symbol} {number}], TimeToken)
54
+ end
55
+
56
+ def valid?(tokens_triplet)
57
+ hour, colon, minutes = tokens_triplet.map { |token| token.value }
58
+ (0..23).include?(hour) and (0..59).include?(minutes) and colon == ":"
59
+ end
60
+ end
61
+
62
+ class ClassicTimeWithModifierPattern < TimePattern
63
+ def initialize
64
+ super(%w[{number} {symbol} {number} {word}], TimeToken)
65
+ end
66
+
67
+ def valid?(tokens_quadruple)
68
+ hour, colon, minutes, modifier = tokens_quadruple.map { |token| token.value }
69
+ (0..12).include?(hour) and (0..59).include?(minutes) and colon == ":" and ["am", "pm"].include?(modifier)
70
+ end
71
+ end
72
+
73
+ class ComplexIntervalPattern < TimePattern
74
+ def initialize
75
+ super(%w[{number} {word} {number} {word}], IntervalToken)
76
+ end
77
+
78
+ def valid?(tokens_quadruple)
79
+ tokens = tokens_quadruple.each_slice(2).to_a
80
+ interval_pair_valid?(tokens[0], true) and interval_pair_valid?(tokens[1], false)
81
+ end
82
+
83
+ private
84
+ def interval_pair_valid?(tokens_pair, for_hours)
85
+ modifier = tokens_pair[1].value
86
+
87
+ if for_hours and %w[h hour hours].include? modifier
88
+ hours = tokens_pair[0].value
89
+ (0..23).include? hours
90
+ elsif not for_hours and %w[m min mins minutes].include? modifier
91
+ minutes = tokens_pair[0].value
92
+ (0..59).include? minutes
93
+ else
94
+ false
95
+ end
96
+ end
97
+ end
98
+
99
+ class SimpleIntervalPattern < TimePattern
100
+ def initialize
101
+ super(%w[{number} {word}], IntervalToken)
102
+ end
103
+
104
+ def valid?(tokens_pair)
105
+ modifier = tokens_pair[1].value
106
+
107
+ if %w[h hour hours].include? modifier
108
+ hours = tokens_pair[0].value
109
+ (0..23).include? hours
110
+ elsif %w[m min mins minutes].include? modifier
111
+ minutes = tokens_pair[0].value
112
+ (0..59).include? minutes
113
+ else
114
+ false
115
+ end
116
+ end
117
+ end
118
+
119
+ class TimeEndingPattern < TimePattern
120
+ def initialize
121
+ super(%w[{word} {time}], TimeEndingToken)
122
+ end
123
+
124
+ def valid?(tokens_pair)
125
+ tokens_pair.first.value == "at"
126
+ end
127
+ end
128
+
129
+ class IntervalEndingPattern < TimePattern
130
+ def initialize
131
+ super(%w[{word} {time} {word} {interval}], IntervalEndingToken)
132
+ end
133
+
134
+ def valid?(tokens_quadruple)
135
+ tokens_quadruple[0].value == "at" and tokens_quadruple[2].value == "for"
136
+ end
137
+ end
138
+
139
+ class IntervalTimeEndingPattern < TimePattern
140
+ def initialize
141
+ super(%w[{word} {time} {word} {time}], IntervalTimeEndingToken)
142
+ end
143
+
144
+ def valid?(tokens_quadruple)
145
+ tokens_quadruple[0].value == "from" and tokens_quadruple[2].value == "to"
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'helper_modules'
2
+ require_relative 'tokens'
3
+ require_relative 'time_patterns'
4
+
5
+ module TimePatterns
6
+ class TimePatternsFinder
7
+ def find_and_update(tokens)
8
+ tokens_with_time = find_and_update_time tokens
9
+ tokens_with_intervals = find_and_update_intervals tokens_with_time
10
+ result = find_and_update_ending_forms tokens_with_intervals
11
+
12
+ result
13
+ end
14
+
15
+ private
16
+ def find_and_update_time(tokens)
17
+ patterns = [ClassicTimeWithModifierPattern.new, ClassicTimePattern.new,
18
+ TimeWithModifierPattern.new]
19
+ patterns.each { |pattern| tokens = pattern.find_and_update tokens }
20
+
21
+ tokens
22
+ end
23
+
24
+ def find_and_update_intervals(tokens)
25
+ patterns = [ComplexIntervalPattern.new, SimpleIntervalPattern.new]
26
+ patterns.each { |pattern| tokens = pattern.find_and_update tokens }
27
+
28
+ tokens
29
+ end
30
+
31
+ def find_and_update_ending_forms(tokens)
32
+ patterns = [IntervalEndingPattern.new, IntervalTimeEndingPattern.new,
33
+ TimeEndingPattern.new]
34
+ patterns.each { |pattern| tokens = pattern.find_and_update tokens }
35
+
36
+ tokens
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,266 @@
1
+ require_relative 'helper_modules'
2
+
3
+ module TimePatterns
4
+ class WordToken
5
+ attr_reader :value
6
+ attr_reader :start_index
7
+
8
+ def initialize(value, start_index)
9
+ @value = value
10
+ @start_index = start_index
11
+ end
12
+
13
+ def to_s
14
+ "{word}"
15
+ end
16
+ end
17
+
18
+ class NumberToken
19
+ attr_reader :value
20
+ attr_reader :start_index
21
+
22
+ def initialize(value, start_index)
23
+ @value = Integer(value)
24
+ @start_index = start_index
25
+ end
26
+
27
+ def to_s
28
+ "{number}"
29
+ end
30
+ end
31
+
32
+ class SymbToken
33
+ attr_reader :value
34
+ attr_reader :start_index
35
+
36
+ def initialize(value, start_index)
37
+ @value = value
38
+ @start_index = start_index
39
+ end
40
+
41
+ def to_s
42
+ "{symbol}"
43
+ end
44
+ end
45
+
46
+ class UnknownToken
47
+ attr_reader :value
48
+ attr_reader :start_index
49
+
50
+ def initialize(value, start_index)
51
+ @value = value
52
+ @start_index = start_index
53
+ end
54
+
55
+ def to_s
56
+ "{unknown}"
57
+ end
58
+ end
59
+
60
+ class TimeToken
61
+ attr_reader :start_index
62
+ attr_reader :end_index
63
+
64
+ attr_reader :hours
65
+ attr_reader :minutes
66
+
67
+ def initialize(values)
68
+ @values = values
69
+ @values.extend(TokensStringRepresentation)
70
+
71
+ set_start_and_end_indexes values
72
+ set_hours_and_minutes values
73
+ end
74
+
75
+ def to_s
76
+ "{time}"
77
+ end
78
+
79
+ private
80
+ def set_start_and_end_indexes(values)
81
+ @start_index = values.first.start_index
82
+ @end_index = values.last.start_index + values.last.value.to_s.length - 1
83
+ end
84
+
85
+ def set_hours_and_minutes(values)
86
+ pattern = values.join
87
+
88
+ case pattern
89
+ when "{number}{word}" then set_time_values(values[0].value, 0, values[1].value)
90
+ when "{number}{symbol}{number}" then set_time_values(values[0].value, values[2].value)
91
+ when "{number}{symbol}{number}{word}" then set_time_values(values[0].value, values[2].value, values[3].value)
92
+ end
93
+ end
94
+
95
+ def set_time_values(hours, minutes, modifier = "am")
96
+ #3pm
97
+ #17:00
98
+ #13:00pm
99
+
100
+ if modifier == "am"
101
+ if hours == 12
102
+ @hours = 0
103
+ else
104
+ @hours = hours
105
+ end
106
+ elsif modifier == "pm"
107
+ if hours == 12
108
+ @hours = 12
109
+ else
110
+ @hours = hours + 12
111
+ end
112
+ end
113
+
114
+ @minutes = minutes
115
+ end
116
+ end
117
+
118
+ class IntervalToken
119
+ attr_reader :start_index
120
+ attr_reader :end_index
121
+ attr_reader :minutes
122
+
123
+ def initialize(values)
124
+ @values = values
125
+ @values.extend(TokensStringRepresentation)
126
+
127
+ set_start_and_end_indexes values
128
+ set_minutes values
129
+ end
130
+
131
+ def to_s
132
+ "{interval}"
133
+ end
134
+
135
+ private
136
+ def set_start_and_end_indexes(values)
137
+ @start_index = values.first.start_index
138
+ @end_index = values.last.start_index + values.last.value.to_s.length - 1
139
+ end
140
+
141
+ def set_minutes(values)
142
+ #1h 30mins
143
+ #20mins
144
+ #1 hour
145
+
146
+ pattern = values.join
147
+
148
+ @minutes = 0
149
+ if pattern == "{number}{word}"
150
+ if %w[h hour hours].include? values[1].value
151
+ @minutes = values[0].value * 60
152
+ else
153
+ @minutes = values[0].value
154
+ end
155
+ elsif pattern == "{number}{word}{number}{word}"
156
+ hours = values[0].value
157
+ @minutes = values[2].value + hours * 60
158
+ end
159
+ end
160
+ end
161
+
162
+ class TimeEndingToken
163
+ attr_reader :start_index
164
+ attr_reader :end_index
165
+ attr_reader :hours
166
+ attr_reader :minutes
167
+ attr_reader :interval
168
+
169
+ def initialize(values)
170
+ @interval = 0
171
+ @values = values
172
+ @values.extend(TokensStringRepresentation)
173
+
174
+ set_start_and_end_indexes values
175
+ set_minutes values
176
+ end
177
+
178
+ def to_s
179
+ "{ending_form}"
180
+ end
181
+
182
+ private
183
+ def set_start_and_end_indexes(values)
184
+ @start_index = values.first.start_index
185
+ @end_index = values.last.end_index
186
+ end
187
+
188
+ def set_minutes(values)
189
+ time = values[1]
190
+ @minutes = time.minutes
191
+ @hours = time.hours
192
+ end
193
+ end
194
+
195
+ class IntervalEndingToken
196
+ attr_reader :start_index
197
+ attr_reader :end_index
198
+ attr_reader :minutes
199
+ attr_reader :hours
200
+ attr_reader :interval
201
+
202
+ def initialize(values)
203
+ @values = values
204
+ @values.extend(TokensStringRepresentation)
205
+
206
+ set_start_and_end_indexes values
207
+ set_time_and_interval values
208
+ end
209
+
210
+ def set_start_and_end_indexes(values)
211
+ @start_index = values.first.start_index
212
+ @end_index = values.last.end_index
213
+ end
214
+
215
+ def set_time_and_interval(values)
216
+ time = values[1]
217
+ @minutes = time.minutes
218
+ @hours = time.hours
219
+
220
+ @interval = values[3].minutes
221
+ end
222
+
223
+ def to_s
224
+ "{ending_form}"
225
+ end
226
+ end
227
+
228
+ class IntervalTimeEndingToken
229
+ attr_reader :start_index
230
+ attr_reader :end_index
231
+ attr_reader :minutes
232
+ attr_reader :hours
233
+ attr_reader :interval
234
+
235
+ def initialize(values)
236
+ @values = values
237
+ @values.extend(TokensStringRepresentation)
238
+
239
+ set_start_and_end_indexes values
240
+ set_time_and_interval values
241
+ end
242
+
243
+ def set_start_and_end_indexes(values)
244
+ @start_index = values.first.start_index
245
+ @end_index = values.last.end_index
246
+ end
247
+
248
+ def set_time_and_interval(values)
249
+ first_time = values[1]
250
+ second_time = values[3]
251
+
252
+ first_time_minutes = first_time.hours * 60 + first_time.minutes
253
+ second_time_minutes = second_time.hours * 60 + second_time.minutes
254
+
255
+ raise "Second time in interval is less than the first one" if first_time_minutes > second_time_minutes
256
+
257
+ @hours = first_time.hours
258
+ @minutes = first_time.minutes
259
+ @interval = second_time_minutes - first_time_minutes
260
+ end
261
+
262
+ def to_s
263
+ "{ending_form}"
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../lib/todo_time_patterns'
2
+
3
+ pattern = ARGV[0]
4
+ result = TodoTimePatterns.parse pattern
5
+ puts result
@@ -0,0 +1,18 @@
1
+ require 'minitest/autorun'
2
+
3
+ require_relative '../lib/todo_time_patterns/parser'
4
+
5
+ class ParserTests < MiniTest::Unit::TestCase
6
+ def test_parse_input_into_tokens
7
+ input = "Buy bread at 17:00"
8
+ expected_tokens = "{word}{word}{word}{number}{symbol}{number}"
9
+
10
+ parser = TimePatterns::Parser.new
11
+ tokens = parser.parse input
12
+
13
+ indexes = tokens.map { |t| t.start_index }
14
+
15
+ assert_equal(expected_tokens, tokens.to_s)
16
+ assert_equal([0, 4, 10, 13, 15, 16], indexes)
17
+ end
18
+ end
@@ -0,0 +1,39 @@
1
+ require 'minitest/autorun'
2
+
3
+ require_relative '../lib/todo_time_patterns/parser'
4
+ require_relative '../lib/todo_time_patterns/time_patterns_finder'
5
+
6
+ class TimePatternsFinderTests < MiniTest::Unit::TestCase
7
+ def setup
8
+ @parser = TimePatterns::Parser.new
9
+ @patterns_finder = TimePatterns::TimePatternsFinder.new
10
+ end
11
+
12
+ def test_simple_form
13
+ input = "Meet Sergii at 4pm"
14
+
15
+ tokens = @parser.parse input
16
+ result = @patterns_finder.find_and_update tokens
17
+
18
+ assert_equal("{word}{word}{ending_form}", result.to_s)
19
+ end
20
+
21
+ def test_interval
22
+ input = "Meet Sergii at 4pm for 2 hours 30mins"
23
+
24
+ tokens = @parser.parse input
25
+ result = @patterns_finder.find_and_update tokens
26
+
27
+ assert_equal("{word}{word}{ending_form}", result.to_s)
28
+ assert_equal(150, result.last.interval)
29
+ end
30
+
31
+ def test_interval_with_time
32
+ input = "Meet Sergii from 4pm to 18:23"
33
+
34
+ tokens = @parser.parse input
35
+ result = @patterns_finder.find_and_update tokens
36
+
37
+ assert_equal("{word}{word}{ending_form}", result.to_s)
38
+ end
39
+ end
@@ -0,0 +1,200 @@
1
+ require 'minitest/autorun'
2
+
3
+ require_relative '../lib/todo_time_patterns/parser'
4
+ require_relative '../lib/todo_time_patterns/time_patterns'
5
+
6
+ class TimePatternsTests < MiniTest::Unit::TestCase
7
+ def setup
8
+ @modifiers = %w[am pm]
9
+ @hour_postfixes = %w[h hour hours]
10
+ @minute_postfixes = %w[m min mins minutes]
11
+ @parser = TimePatterns::Parser.new
12
+ end
13
+
14
+ def test_time_with_modifier_pattern
15
+ @modifiers.each do |modifier|
16
+ input = "Buy bread at 12#{modifier}"
17
+ tokens = @parser.parse input
18
+
19
+ pattern = TimePatterns::TimeWithModifierPattern.new
20
+ result = pattern.find_and_update tokens
21
+
22
+ assert_equal("{word}{word}{word}{time}", result.to_s)
23
+ end
24
+ end
25
+
26
+ def test_time_with_modifier_pattern_and_invalid_entry
27
+ @modifiers.each do |modifier|
28
+ input = "Buy bread at 17 #{modifier}"
29
+
30
+ tokens = @parser.parse input
31
+
32
+ pattern = TimePatterns::TimeWithModifierPattern.new
33
+ result = pattern.find_and_update tokens
34
+
35
+ assert_equal("{word}{word}{word}{number}{word}", result.to_s)
36
+ end
37
+ end
38
+
39
+ def test_classic_time_pattern
40
+ input = "Buy bread at 17:00"
41
+
42
+ tokens = @parser.parse input
43
+
44
+ pattern = TimePatterns::ClassicTimePattern.new
45
+ result = pattern.find_and_update tokens
46
+
47
+ assert_equal("{word}{word}{word}{time}", result.to_s)
48
+ end
49
+
50
+ def test_classic_time_pattern_and_invalid_entry
51
+ input = "Buy bread at 25:00"
52
+
53
+ tokens = @parser.parse input
54
+
55
+ pattern = TimePatterns::ClassicTimePattern.new
56
+ result = pattern.find_and_update tokens
57
+
58
+ assert_equal("{word}{word}{word}{number}{symbol}{number}", result.to_s)
59
+ end
60
+
61
+ def test_classic_time_with_modifier_pattern
62
+ @modifiers.each do |modifier|
63
+ input = "Buy bread at 7:10#{modifier}"
64
+
65
+ tokens = @parser.parse input
66
+
67
+ pattern = TimePatterns::ClassicTimeWithModifierPattern.new
68
+ result = pattern.find_and_update tokens
69
+
70
+ assert_equal("{word}{word}{word}{time}", result.to_s)
71
+ end
72
+ end
73
+
74
+ def test_classic_time_with_modifier_pattern_and_invalid_entry
75
+ @modifiers.each do |modifier|
76
+ input = "Buy bread at 17:39 #{modifier}"
77
+
78
+ tokens = @parser.parse input
79
+
80
+ pattern = TimePatterns::ClassicTimeWithModifierPattern.new
81
+ result = pattern.find_and_update tokens
82
+
83
+ assert_equal("{word}{word}{word}{number}{symbol}{number}{word}", result.to_s)
84
+ end
85
+ end
86
+
87
+ def test_simple_interval_pattern
88
+ @modifiers.each do |modifier|
89
+ @minute_postfixes.each do |minutes|
90
+ input = "Meeting at 1#{modifier} for 30#{minutes}"
91
+
92
+ tokens = @parser.parse input
93
+
94
+ pattern = TimePatterns::SimpleIntervalPattern.new
95
+ result = pattern.find_and_update tokens
96
+
97
+ assert_equal("{word}{word}{number}{word}{word}{interval}", result.to_s)
98
+ end
99
+ end
100
+ end
101
+
102
+ def test_simple_interval_values
103
+ input = "Meeting with Pixel at 1pm for 1 hour"
104
+
105
+ tokens = @parser.parse input
106
+
107
+ pattern = TimePatterns::SimpleIntervalPattern.new
108
+ result = pattern.find_and_update tokens
109
+
110
+ assert_equal(60, result.last.minutes)
111
+ end
112
+
113
+ def test_simple_interval_pattern_invalid_entry
114
+ input = "Meeting at 1pm for 30hours"
115
+
116
+ tokens = @parser.parse input
117
+
118
+ pattern = TimePatterns::SimpleIntervalPattern.new
119
+ result = pattern.find_and_update tokens
120
+
121
+ assert_equal("{word}{word}{number}{word}{word}{number}{word}", result.to_s)
122
+ end
123
+
124
+ def test_complex_interval_pattern
125
+ @hour_postfixes.each do |hours|
126
+ @minute_postfixes.each do |minutes|
127
+ input = "Breakfast for 1#{hours} 23#{minutes}"
128
+
129
+ tokens = @parser.parse input
130
+
131
+ pattern = TimePatterns::ComplexIntervalPattern.new
132
+ result = pattern.find_and_update tokens
133
+
134
+ assert_equal("{word}{word}{interval}", result.to_s)
135
+ end
136
+ end
137
+ end
138
+
139
+ def test_complex_interval_pattern_invalid_entry
140
+ input = "Breakfast for 1m 23m"
141
+
142
+ parser = TimePatterns::Parser.new
143
+ tokens = parser.parse input
144
+
145
+ pattern = TimePatterns::ComplexIntervalPattern.new
146
+ result = pattern.find_and_update tokens
147
+
148
+ assert_equal("{word}{word}{number}{word}{number}{word}", result.to_s)
149
+ end
150
+
151
+ def test_simple_time_ending
152
+ input = "Breakfast at 17:00"
153
+
154
+ parser = TimePatterns::Parser.new
155
+ tokens = parser.parse input
156
+
157
+ pattern = TimePatterns::ClassicTimePattern.new
158
+ result = pattern.find_and_update tokens
159
+
160
+ ending_pattern = TimePatterns::TimeEndingPattern.new
161
+ ending_result = ending_pattern.find_and_update result
162
+
163
+ assert_equal("{word}{ending_form}", ending_result.to_s)
164
+ end
165
+
166
+ def test_interval_ending
167
+ input = "Breakfast at 4pm for 1h 30mins"
168
+
169
+ parser = TimePatterns::Parser.new
170
+ tokens = parser.parse input
171
+
172
+ pattern = TimePatterns::TimeWithModifierPattern.new
173
+ result = pattern.find_and_update tokens
174
+ interval_pattern = TimePatterns::ComplexIntervalPattern.new
175
+ result = interval_pattern.find_and_update result
176
+
177
+ ending_pattern = TimePatterns::IntervalEndingPattern.new
178
+ ending_result = ending_pattern.find_and_update result
179
+
180
+ assert_equal("{word}{ending_form}", ending_result.to_s)
181
+ end
182
+
183
+ def test_interval_with_time_ending
184
+ input = "Breakfast from 4:00 to 9:43pm"
185
+
186
+ parser = TimePatterns::Parser.new
187
+ tokens = parser.parse input
188
+
189
+ pattern = TimePatterns::ClassicTimeWithModifierPattern.new
190
+ result = pattern.find_and_update tokens
191
+
192
+ pattern = TimePatterns::ClassicTimePattern.new
193
+ result = pattern.find_and_update result
194
+
195
+ ending_pattern = TimePatterns::IntervalTimeEndingPattern.new
196
+ ending_result = ending_pattern.find_and_update result
197
+
198
+ assert_equal("{word}{ending_form}", ending_result.to_s)
199
+ end
200
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: todo_time_patterns
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ivan Bokii
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-22 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! " Todo time patterns is a small library that helps you to parse
15
+ different\n time patterns in strings like:\n - meet bob at 4pm\n -
16
+ meeting at 13:34\n - watch Adventure Times at 3:34pm\n - Go shopping at
17
+ 2pm for 2h\n - Pay your tech. debt at 2pm for 35mins to Mafia\n - Sleep
18
+ well from 1am to 8:00\n\n etc.\n"
19
+ email: bokiyis@gmail.com
20
+ executables: []
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - lib/todo_time_patterns/helper_modules.rb
25
+ - lib/todo_time_patterns/parser.rb
26
+ - lib/todo_time_patterns/parser_helpers.rb
27
+ - lib/todo_time_patterns/time_patterns.rb
28
+ - lib/todo_time_patterns/time_patterns_finder.rb
29
+ - lib/todo_time_patterns/tokens.rb
30
+ - lib/todo_time_patterns.rb
31
+ - tests/console_test.rb
32
+ - tests/parser_tests.rb
33
+ - tests/time_patterns_finder_tests.rb
34
+ - tests/time_patterns_tests.rb
35
+ homepage: https://github.com/spkenny/todo_time_patterns
36
+ licenses: []
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 1.8.21
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: Library that helps you to parse date patterns in strings like 'meet Bob at
59
+ 5:45pm'
60
+ test_files: []