nickel 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/License.txt +2 -2
- data/README.rdoc +24 -12
- data/Rakefile +22 -0
- data/lib/nickel/construct.rb +121 -0
- data/lib/nickel/construct_finder.rb +1145 -0
- data/lib/nickel/construct_interpreter.rb +345 -0
- data/lib/nickel/instance_from_hash.rb +13 -0
- data/lib/nickel/nlp.rb +73 -0
- data/lib/nickel/occurrence.rb +90 -0
- data/lib/nickel/query.rb +1143 -0
- data/lib/nickel/query_constants.rb +26 -0
- data/lib/nickel/ruby_ext/calling_method.rb +10 -0
- data/lib/nickel/ruby_ext/to_s2.rb +12 -0
- data/lib/nickel/zdate.rb +503 -0
- data/lib/nickel/ztime.rb +319 -0
- data/lib/nickel.rb +30 -34
- data/nickel.gemspec +30 -10
- data/{test → spec}/nickel_spec.rb +4 -4
- data/test/compare.rb +109 -0
- data/test/nlp_test.rb +813 -0
- data/test/nlp_tests_helper.rb +55 -0
- data/test/zdate_test.rb +43 -0
- data/test/ztime_test.rb +428 -0
- metadata +34 -22
@@ -0,0 +1,1145 @@
|
|
1
|
+
# Ruby Nickel Library
|
2
|
+
# Copyright (c) 2008-2011 Lou Zell, lzell11@gmail.com, http://hazelmade.com
|
3
|
+
# MIT License [http://www.opensource.org/licenses/mit-license.php]
|
4
|
+
|
5
|
+
module Nickel
|
6
|
+
|
7
|
+
class ConstructFinder
|
8
|
+
attr_reader :constructs, :components
|
9
|
+
|
10
|
+
def initialize(query, curdate, curtime)
|
11
|
+
# If query is a string (for debug), use it to initialize NLPQuery.
|
12
|
+
query.class == String && query = NLPQuery.new(query)
|
13
|
+
@curdate = curdate
|
14
|
+
@curtime = curtime
|
15
|
+
@components = query.split
|
16
|
+
@pos = 0 # iterator
|
17
|
+
@constructs = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
while @pos < @components.size
|
22
|
+
big_if_on_current_word
|
23
|
+
@pos += 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset_instance_vars
|
28
|
+
@day_index = nil
|
29
|
+
@month_index = nil
|
30
|
+
@week_num = nil
|
31
|
+
@date_array = nil
|
32
|
+
@length = nil
|
33
|
+
@time1 = nil
|
34
|
+
@time2 = nil
|
35
|
+
@date1 = nil
|
36
|
+
@date2 = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def big_if_on_current_word
|
40
|
+
reset_instance_vars
|
41
|
+
|
42
|
+
if match_every
|
43
|
+
if match_every_dayname then found_every_dayname # every tue
|
44
|
+
elsif match_every_day then found_every_day # every day
|
45
|
+
elsif match_every_other
|
46
|
+
if match_every_other_dayname then found_every_other_dayname # every other fri
|
47
|
+
elsif match_every_other_day then found_every_other_day # every other day
|
48
|
+
end
|
49
|
+
elsif match_every_3rd
|
50
|
+
if match_every_3rd_dayname then found_every_3rd_dayname # every third fri
|
51
|
+
elsif match_every_3rd_day then found_every_3rd_day # every third day
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
elsif match_repeats
|
56
|
+
if match_repeats_daily then found_repeats_daily # repeats daily
|
57
|
+
elsif match_repeats_altdaily then found_repeats_altdaily # repeats altdaily
|
58
|
+
elsif match_repeats_weekly_vague then found_repeats_weekly_vague # repeats weekly
|
59
|
+
elsif match_repeats_altweekly_vague then found_repeats_altweekly_vague # repeats altweekly
|
60
|
+
elsif match_repeats_monthly
|
61
|
+
if match_repeats_daymonthly then found_repeats_daymonthly # repeats monthly 1st fri
|
62
|
+
elsif match_repeats_datemonthly then found_repeats_datemonthly # repeats monthly 22nd
|
63
|
+
end
|
64
|
+
elsif match_repeats_altmonthly
|
65
|
+
if match_repeats_altmonthly_daymonthly then found_repeats_altmonthly_daymonthly # repeats altmonthly 1st fri
|
66
|
+
elsif match_repeats_altmonthly_datemonthly then found_repeats_altmonthly_datemonthly # repeats altmonthly 22nd
|
67
|
+
end
|
68
|
+
elsif match_repeats_threemonthly
|
69
|
+
if match_repeats_threemonthly_daymonthly then found_repeats_threemonthly_daymonthly # repeats threemonthly 1st fri
|
70
|
+
elsif match_repeats_threemonthly_datemonthly then found_repeats_threemonthly_datemonthly # repeats threemonthly 22nd
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
elsif match_for_x
|
75
|
+
if match_for_x_days then found_for_x_days # for 10 days
|
76
|
+
elsif match_for_x_weeks then found_for_x_weeks # for 10 weeks
|
77
|
+
elsif match_for_x_months then found_for_x_months # for 10 months
|
78
|
+
end
|
79
|
+
|
80
|
+
elsif match_this
|
81
|
+
if match_this_dayname then found_this_dayname # this fri
|
82
|
+
elsif match_this_week then found_this_week # this week
|
83
|
+
elsif match_this_month then found_this_month # this month (implies 9/1 to 9/30)
|
84
|
+
end # SHOULDN'T "this" HAVE "this weekend" ???
|
85
|
+
|
86
|
+
elsif match_next
|
87
|
+
if match_next_weekend then found_next_weekend # next weekend --- never hit?
|
88
|
+
elsif match_next_dayname then found_next_dayname # next tuesday
|
89
|
+
elsif match_next_x
|
90
|
+
if match_next_x_days then found_next_x_days # next 5 days --- shouldn't this be a wrapper?
|
91
|
+
elsif match_next_x_weeks then found_next_x_weeks # next 5 weeks --- shouldn't this be a wrapper?
|
92
|
+
elsif match_next_x_months then found_next_x_months # next 5 months --- shouldn't this be a wrapper?
|
93
|
+
elsif match_next_x_years then found_next_x_years # next 5 years --- shouldn't this be a wrapper?
|
94
|
+
end
|
95
|
+
elsif match_next_week then found_next_week
|
96
|
+
elsif match_next_month then found_next_month # next month (implies 10/1 to 10/31)
|
97
|
+
end
|
98
|
+
|
99
|
+
elsif match_week
|
100
|
+
if match_week_of_date then found_week_of_date # week of 1/2
|
101
|
+
elsif match_week_through_date then found_week_through_date # week through 1/2 (as in, week ending 1/2)
|
102
|
+
end
|
103
|
+
|
104
|
+
elsif match_x_weeks_from
|
105
|
+
if match_x_weeks_from_dayname then found_x_weeks_from_dayname # 5 weeks from tuesday
|
106
|
+
elsif match_x_weeks_from_this_dayname then found_x_weeks_from_this_dayname # 5 weeks from this tuesday
|
107
|
+
elsif match_x_weeks_from_next_dayname then found_x_weeks_from_next_dayname # 5 weeks from next tuesday
|
108
|
+
elsif match_x_weeks_from_tomorrow then found_x_weeks_from_tomorrow # 5 weeks from tomorrow
|
109
|
+
elsif match_x_weeks_from_now then found_x_weeks_from_now # 5 weeks from now
|
110
|
+
elsif match_x_weeks_from_yesterday then found_x_weeks_from_yesterday # 5 weeks from yesterday
|
111
|
+
end
|
112
|
+
|
113
|
+
elsif match_x_months_from
|
114
|
+
if match_x_months_from_dayname then found_x_months_from_dayname # 2 months from wed
|
115
|
+
elsif match_x_months_from_this_dayname then found_x_months_from_this_dayname # 2 months from this wed
|
116
|
+
elsif match_x_months_from_next_dayname then found_x_months_from_next_dayname # 2 months from next wed
|
117
|
+
elsif match_x_months_from_tomorrow then found_x_months_from_tomorrow # 2 months from tomorrow
|
118
|
+
elsif match_x_months_from_now then found_x_months_from_now # 2 months from now
|
119
|
+
elsif match_x_months_from_yesterday then found_x_months_from_yesterday # 2 months from yesterday
|
120
|
+
end
|
121
|
+
|
122
|
+
elsif match_x_days_from
|
123
|
+
if match_x_days_from_now then found_x_days_from_now # 5 days from now
|
124
|
+
elsif match_x_days_from_dayname then found_x_days_from_dayname # 5 days from monday
|
125
|
+
end
|
126
|
+
|
127
|
+
elsif match_x_dayname_from
|
128
|
+
if match_x_dayname_from_now then found_x_dayname_from_now # 2 fridays from now
|
129
|
+
elsif match_x_dayname_from_tomorrow then found_x_dayname_from_tomorrow # 2 fridays from tomorrow
|
130
|
+
elsif match_x_dayname_from_yesterday then found_x_dayname_from_yesterday # 2 fridays from yesterday
|
131
|
+
elsif match_x_dayname_from_this then found_x_dayname_from_this # 2 fridays from this one
|
132
|
+
elsif match_x_dayname_from_next then found_x_dayname_from_next # 2 fridays from next friday
|
133
|
+
end
|
134
|
+
|
135
|
+
elsif match_x_minutes_from_now then found_x_minutes_from_now # 5 minutes from now
|
136
|
+
elsif match_x_hours_from_now then found_x_hours_from_now # 5 hours from now
|
137
|
+
|
138
|
+
elsif match_ordinal_dayname
|
139
|
+
if match_ordinal_dayname_this_month then found_ordinal_dayname_this_month # 2nd friday this month
|
140
|
+
elsif match_ordinal_dayname_next_month then found_ordinal_dayname_next_month # 2nd friday next month
|
141
|
+
elsif match_ordinal_dayname_monthname then found_ordinal_dayname_monthname # 2nd friday december
|
142
|
+
end
|
143
|
+
|
144
|
+
elsif match_ordinal_this_month then found_ordinal_this_month # 28th this month
|
145
|
+
elsif match_ordinal_next_month then found_ordinal_next_month # 28th next month
|
146
|
+
|
147
|
+
elsif match_first_day
|
148
|
+
if match_first_day_this_month then found_first_day_this_month # first day this month
|
149
|
+
elsif match_first_day_next_month then found_first_day_next_month # first day next month
|
150
|
+
elsif match_first_day_monthname then found_first_day_monthname # first day january (well this is stupid, "first day of january" gets preprocessed into "1/1", so what is the point of this?)
|
151
|
+
end
|
152
|
+
|
153
|
+
elsif match_last_day
|
154
|
+
if match_last_day_this_month then found_last_day_this_month # last day this month
|
155
|
+
elsif match_last_day_next_month then found_last_day_next_month # last day next month
|
156
|
+
elsif match_last_day_monthname then found_last_day_monthname # last day november
|
157
|
+
end
|
158
|
+
|
159
|
+
elsif match_at
|
160
|
+
if match_at_time
|
161
|
+
if match_at_time_through_time then found_at_time_through_time # at 2 through 5pm
|
162
|
+
else found_at_time # at 2
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
elsif match_all_day then found_all_day # all day
|
167
|
+
|
168
|
+
elsif match_tomorrow
|
169
|
+
if match_tomorrow_through
|
170
|
+
if match_tomorrow_through_dayname then found_tomorrow_through_dayname # tomorrow through friday
|
171
|
+
elsif match_tomorrow_through_date then found_tomorrow_through_date # tomorrow through august 20th
|
172
|
+
end
|
173
|
+
else found_tomorrow # tomorrow
|
174
|
+
end
|
175
|
+
|
176
|
+
elsif match_now
|
177
|
+
if match_now_through
|
178
|
+
if match_now_through_dayname then found_now_through_dayname # today through friday
|
179
|
+
elsif match_now_through_following_dayname then found_now_through_following_dayname # REDUNDANT, PREPROCESS THIS OUT
|
180
|
+
elsif match_now_through_date then found_now_through_date # today through 10/1
|
181
|
+
elsif match_now_through_tomorrow then found_now_through_tomorrow # today through tomorrow
|
182
|
+
elsif match_now_through_next_dayname then found_now_through_next_dayname # today through next friday
|
183
|
+
end
|
184
|
+
else found_now # today
|
185
|
+
end
|
186
|
+
|
187
|
+
elsif match_dayname
|
188
|
+
if match_dayname_the_ordinal then found_dayname_the_ordinal # monday the 21st
|
189
|
+
elsif match_dayname_x_weeks_from_next then found_dayname_x_weeks_from_next # monday 2 weeks from next
|
190
|
+
elsif match_dayname_x_weeks_from_this then found_dayname_x_weeks_from_this # monday 2 weeks from this
|
191
|
+
else found_dayname # monday (also monday tuesday wed...)
|
192
|
+
end
|
193
|
+
|
194
|
+
elsif match_through_monthname then found_through_monthname # through december (implies through 11/30)
|
195
|
+
elsif match_monthname then found_monthname # december (implies 12/1 to 12/31)
|
196
|
+
|
197
|
+
# 5th constructor
|
198
|
+
elsif match_start then found_start
|
199
|
+
elsif match_through then found_through
|
200
|
+
|
201
|
+
elsif match_time # match time second to last
|
202
|
+
if match_time_through_time then found_time_through_time # 10 to 4
|
203
|
+
else found_time # 10
|
204
|
+
end
|
205
|
+
|
206
|
+
elsif match_date # match date last
|
207
|
+
if match_date_through_date then found_date_through_date # 5th through the 16th
|
208
|
+
else found_date # 5th
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end # end def big_if_on_current_word
|
212
|
+
|
213
|
+
def match_every
|
214
|
+
@components[@pos]=="every"
|
215
|
+
end
|
216
|
+
|
217
|
+
def match_every_dayname
|
218
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+1]) # if "every [day]"
|
219
|
+
end
|
220
|
+
|
221
|
+
def found_every_dayname
|
222
|
+
day_array=[@day_index]
|
223
|
+
j = 2
|
224
|
+
while @components[@pos+j] && ZDate.days_of_week.index(@components[@pos+j]) # if "every mon tue wed"
|
225
|
+
day_array << ZDate.days_of_week.index(@components[@pos+j])
|
226
|
+
j += 1
|
227
|
+
end
|
228
|
+
@constructs << RecurrenceConstruct.new(:repeats => :weekly, :repeats_on => day_array, :comp_start => @pos, :comp_end => @pos += (j - 1), :found_in => method_name)
|
229
|
+
end
|
230
|
+
|
231
|
+
def match_every_day
|
232
|
+
@components[@pos+1] == "day"
|
233
|
+
end
|
234
|
+
|
235
|
+
def found_every_day
|
236
|
+
@constructs << RecurrenceConstruct.new(:repeats => :daily, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
237
|
+
end
|
238
|
+
|
239
|
+
def match_every_other
|
240
|
+
@components[@pos+1] =~ /other|2nd/
|
241
|
+
end
|
242
|
+
|
243
|
+
def match_every_other_dayname
|
244
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+2]) # if "every other mon"
|
245
|
+
end
|
246
|
+
|
247
|
+
def found_every_other_dayname
|
248
|
+
day_array = [@day_index]
|
249
|
+
j = 3
|
250
|
+
while @components[@pos+j] && ZDate.days_of_week.index(@components[@pos+j]) #if "every other mon tue wed
|
251
|
+
day_array << ZDate.days_of_week.index(@components[@pos+j])
|
252
|
+
j += 1
|
253
|
+
end
|
254
|
+
@constructs << RecurrenceConstruct.new(:repeats => :altweekly, :repeats_on => day_array, :comp_start => @pos, :comp_end => @pos += (j - 1), :found_in => method_name)
|
255
|
+
end
|
256
|
+
|
257
|
+
def match_every_other_day
|
258
|
+
@components[@pos+2] == "day" ## if "every other day"
|
259
|
+
end
|
260
|
+
|
261
|
+
def found_every_other_day
|
262
|
+
@constructs << RecurrenceConstruct.new(:repeats => :altdaily, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
263
|
+
end
|
264
|
+
|
265
|
+
def match_every_3rd
|
266
|
+
@components[@pos+1] == "3rd"
|
267
|
+
end
|
268
|
+
|
269
|
+
def match_every_3rd_dayname
|
270
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+2]) # if "every 3rd tue"
|
271
|
+
end
|
272
|
+
|
273
|
+
def found_every_3rd_dayname
|
274
|
+
day_array = [@day_index]
|
275
|
+
j = 3
|
276
|
+
while @components[@pos+j] && ZDate.days_of_week.index(@components[@pos+j]) #if "every 3rd tue wed thu
|
277
|
+
day_array << ZDate.days_of_week.index(@components[@pos+j])
|
278
|
+
j += 1
|
279
|
+
end
|
280
|
+
@constructs << RecurrenceConstruct.new(:repeats => :threeweekly, :repeats_on => day_array, :comp_start => @pos, :comp_end => @pos += (j - i), :found_in => method_name)
|
281
|
+
end
|
282
|
+
|
283
|
+
def match_every_3rd_day
|
284
|
+
@components[@pos+2] == "day" ## if "every 3rd day"
|
285
|
+
end
|
286
|
+
|
287
|
+
def found_every_3rd_day
|
288
|
+
@constructs << RecurrenceConstruct.new(:repeats => :threedaily, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
289
|
+
end
|
290
|
+
|
291
|
+
def match_repeats
|
292
|
+
@components[@pos] == "repeats"
|
293
|
+
end
|
294
|
+
|
295
|
+
def match_repeats_daily
|
296
|
+
@components[@pos+1] == "daily"
|
297
|
+
end
|
298
|
+
|
299
|
+
def found_repeats_daily
|
300
|
+
@constructs << RecurrenceConstruct.new(:repeats => :daily, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
301
|
+
end
|
302
|
+
|
303
|
+
def match_repeats_altdaily
|
304
|
+
@components[@pos+1] == "altdaily"
|
305
|
+
end
|
306
|
+
|
307
|
+
def found_repeats_altdaily
|
308
|
+
@constructs << RecurrenceConstruct.new(:repeats => :altdaily, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
309
|
+
end
|
310
|
+
|
311
|
+
def match_repeats_weekly_vague
|
312
|
+
@components[@pos+1] == "weekly"
|
313
|
+
end
|
314
|
+
|
315
|
+
def found_repeats_weekly_vague
|
316
|
+
@constructs << RecurrenceConstruct.new(:repeats => :weekly, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
317
|
+
end
|
318
|
+
|
319
|
+
def match_repeats_altweekly_vague
|
320
|
+
@components[@pos+1] == "altweekly"
|
321
|
+
end
|
322
|
+
|
323
|
+
def found_repeats_altweekly_vague
|
324
|
+
@constructs << RecurrenceConstruct.new(:repeats => :altweekly, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
325
|
+
end
|
326
|
+
|
327
|
+
def match_repeats_monthly
|
328
|
+
@components[@pos+1] == "monthly"
|
329
|
+
end
|
330
|
+
|
331
|
+
def match_repeats_daymonthly
|
332
|
+
@components[@pos+2] && @components[@pos+3] && (@week_num = @components[@pos+2].to_i) && @week_num > 0 && @week_num <= 5 && (@day_index = ZDate.days_of_week.index(@components[@pos+3])) # "repeats monthly 2nd wed"
|
333
|
+
end
|
334
|
+
|
335
|
+
def found_repeats_daymonthly
|
336
|
+
rep_array = [[@week_num, @day_index]] # That is NOT a typo, not sure what I meant by that! maybe the nested array
|
337
|
+
j = 4
|
338
|
+
while @components[@pos+j] && @components[@pos+j+1] && (@week_num = @components[@pos+j].to_i) && @week_num > 0 && @week_num <= 5 && (@day_index = ZDate.days_of_week.index(@components[@pos+j+1]))
|
339
|
+
rep_array << [@week_num, @day_index]
|
340
|
+
j += 2
|
341
|
+
end
|
342
|
+
@constructs << RecurrenceConstruct.new(:repeats => :daymonthly, :repeats_on => rep_array, :comp_start => @pos, :comp_end => @pos += (j - 1), :found_in => method_name)
|
343
|
+
end
|
344
|
+
|
345
|
+
def match_repeats_datemonthly
|
346
|
+
@components[@pos+2] && @components[@pos+2].valid_dd? && @date_array = [@components[@pos+2].to_i] # repeats monthly 22nd
|
347
|
+
end
|
348
|
+
|
349
|
+
def found_repeats_datemonthly
|
350
|
+
j = 3
|
351
|
+
while @components[@pos+j] && @components[@pos+j].valid_dd?
|
352
|
+
@date_array << @components[@pos+j].to_i
|
353
|
+
j += 1
|
354
|
+
end
|
355
|
+
@constructs << RecurrenceConstruct.new(:repeats => :datemonthly, :repeats_on => @date_array, :comp_start => @pos, :comp_end => @pos += (j - 1), :found_in => method_name)
|
356
|
+
end
|
357
|
+
|
358
|
+
def match_repeats_altmonthly
|
359
|
+
@components[@pos+1] == "altmonthly"
|
360
|
+
end
|
361
|
+
|
362
|
+
def match_repeats_altmonthly_daymonthly
|
363
|
+
@components[@pos+2] && @components[@pos+3] && (@week_num = @components[@pos+2].to_i) && @week_num > 0 && @week_num <= 5 && (@day_index = ZDate.days_of_week.index(@components[@pos+3])) # "repeats altmonthly 2nd wed"
|
364
|
+
end
|
365
|
+
|
366
|
+
def found_repeats_altmonthly_daymonthly
|
367
|
+
rep_array = [[@week_num, @day_index]]
|
368
|
+
j = 4
|
369
|
+
while @components[@pos+j] && @components[@pos+j+1] && (@week_num = @components[@pos+j].to_i) && @week_num > 0 && @week_num <= 5 && (@day_index = ZDate.days_of_week.index(@components[@pos+j+1]))
|
370
|
+
rep_array << [@week_num, @day_index]
|
371
|
+
j += 2
|
372
|
+
end
|
373
|
+
@constructs << RecurrenceConstruct.new(:repeats => :altdaymonthly, :repeats_on => rep_array, :comp_start => @pos, :comp_end => @pos += (j - 1), :found_in => method_name)
|
374
|
+
end
|
375
|
+
|
376
|
+
def match_repeats_altmonthly_datemonthly
|
377
|
+
@components[@pos+2] && @components[@pos+2].valid_dd? && @date_array = [@components[@pos+2].to_i] # repeats altmonthly 22nd
|
378
|
+
end
|
379
|
+
|
380
|
+
def found_repeats_altmonthly_datemonthly
|
381
|
+
j = 3
|
382
|
+
while @components[@pos+j] && @components[@pos+j].valid_dd?
|
383
|
+
@date_array << @components[@pos+j].to_i
|
384
|
+
j += 1
|
385
|
+
end
|
386
|
+
@constructs << RecurrenceConstruct.new(:repeats => :altdatemonthly, :repeats_on => @date_array, :comp_start => @pos, :comp_end => @pos += (j - 1), :found_in => method_name)
|
387
|
+
end
|
388
|
+
|
389
|
+
def match_repeats_threemonthly
|
390
|
+
@components[@pos+1] == "threemonthly"
|
391
|
+
end
|
392
|
+
|
393
|
+
def match_repeats_threemonthly_daymonthly
|
394
|
+
@components[@pos+2] && @components[@pos+3] && (@week_num = @components[@pos+2].to_i) && @week_num > 0 && @week_num <= 5 && (@day_index = ZDate.days_of_week.index(@components[@pos+3])) # "repeats threemonthly 2nd wed"
|
395
|
+
end
|
396
|
+
|
397
|
+
def found_repeats_threemonthly_daymonthly
|
398
|
+
rep_array = [[@week_num, @day_index]] # That is NOT a typo
|
399
|
+
j = 4
|
400
|
+
while @components[@pos+j] && @components[@pos+j+1] && (@week_num = @components[@pos+j].to_i) && @week_num > 0 && @week_num <= 5 && (@day_index = ZDate.days_of_week.index(@components[@pos+j+1]))
|
401
|
+
rep_array << [@week_num, @day_index]
|
402
|
+
j += 2
|
403
|
+
end
|
404
|
+
@constructs << RecurrenceConstruct.new(:repeats => :threedaymonthly, :repeats_on => rep_array, :comp_start => @pos, :comp_end => @pos += (j - 1), :found_in => method_name)
|
405
|
+
end
|
406
|
+
|
407
|
+
def match_repeats_threemonthly_datemonthly
|
408
|
+
@components[@pos+2] && @components[@pos+2].valid_dd? && @date_array = [@components[@pos+2].to_i] # repeats threemonthly 22nd
|
409
|
+
end
|
410
|
+
|
411
|
+
def found_repeats_threemonthly_datemonthly
|
412
|
+
j = 3
|
413
|
+
while @components[@pos+j] && @components[@pos+j].valid_dd?
|
414
|
+
@date_array << @components[@pos+j].to_i
|
415
|
+
j += 1
|
416
|
+
end
|
417
|
+
@constructs << RecurrenceConstruct.new(:repeats => :threedatemonthly, :repeats_on => @date_array, :comp_start => @pos, :comp_end => @pos += (j - 1), :found_in => method_name)
|
418
|
+
end
|
419
|
+
|
420
|
+
def match_for_x
|
421
|
+
@components[@pos]=="for" && @components[@pos+1].digits_only? && @length = @components[@pos+1].to_i
|
422
|
+
end
|
423
|
+
|
424
|
+
def match_for_x_days
|
425
|
+
@components[@pos+2] =~ /days?/
|
426
|
+
end
|
427
|
+
|
428
|
+
def found_for_x_days
|
429
|
+
@constructs << WrapperConstruct.new(:wrapper_type => 2, :wrapper_length => @length, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
430
|
+
end
|
431
|
+
|
432
|
+
def match_for_x_weeks
|
433
|
+
@components[@pos+2] =~ /weeks?/
|
434
|
+
end
|
435
|
+
|
436
|
+
def found_for_x_weeks
|
437
|
+
@constructs << WrapperConstruct.new(:wrapper_type => 3, :wrapper_length => @length, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
438
|
+
end
|
439
|
+
|
440
|
+
def match_for_x_months
|
441
|
+
@components[@pos+2] =~ /months?/
|
442
|
+
end
|
443
|
+
|
444
|
+
def found_for_x_months
|
445
|
+
@constructs << WrapperConstruct.new(:wrapper_type => 4, :wrapper_length => @length, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
446
|
+
end
|
447
|
+
|
448
|
+
def match_this
|
449
|
+
@components[@pos]=="this"
|
450
|
+
end
|
451
|
+
|
452
|
+
def match_this_dayname
|
453
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+1])
|
454
|
+
end
|
455
|
+
|
456
|
+
def found_this_dayname
|
457
|
+
day_to_add = @curdate.this(@day_index)
|
458
|
+
@constructs << DateConstruct.new(:date => day_to_add, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
459
|
+
while @components[@pos+1] && @day_index = ZDate.days_of_week.index(@components[@pos+1])
|
460
|
+
# note @pos gets incremented on each pass
|
461
|
+
@constructs << DateConstruct.new(:date => day_to_add = day_to_add.this(@day_index), :comp_start => @pos + 1, :comp_end => @pos += 1, :found_in => method_name)
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
def match_this_week
|
466
|
+
@components[@pos+1] =~ /weeks?/
|
467
|
+
end
|
468
|
+
|
469
|
+
def found_this_week
|
470
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.add_days(7), :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
471
|
+
end
|
472
|
+
|
473
|
+
def match_this_month
|
474
|
+
@components[@pos+1] =~ /months?/
|
475
|
+
end
|
476
|
+
|
477
|
+
def found_this_month
|
478
|
+
date = NLP::use_date_correction ? @curdate : @curdate.beginning_of_month
|
479
|
+
@constructs << DateSpanConstruct.new(:start_date => date, :end_date => @curdate.end_of_month, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
480
|
+
end
|
481
|
+
|
482
|
+
|
483
|
+
def match_next
|
484
|
+
@components[@pos]=="next"
|
485
|
+
end
|
486
|
+
|
487
|
+
def match_next_weekend
|
488
|
+
@components[@pos+1]=="weekend" ## "next weekend"
|
489
|
+
end
|
490
|
+
|
491
|
+
def found_next_weekend
|
492
|
+
dsc = DateSpanConstruct.new(:start_date => @curdate.next(5), :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
493
|
+
dsc.end_date = dsc.start_date.add_days(1)
|
494
|
+
@constructs << dsc
|
495
|
+
end
|
496
|
+
|
497
|
+
def match_next_dayname
|
498
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+1]) ## if "next [day]"
|
499
|
+
end
|
500
|
+
|
501
|
+
def found_next_dayname
|
502
|
+
day_to_add = @curdate.next(@day_index)
|
503
|
+
@constructs << DateConstruct.new(:date => day_to_add, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
504
|
+
while @components[@pos+1] && @day_index = ZDate.days_of_week.index(@components[@pos+1])
|
505
|
+
# note @pos gets incremented on each pass
|
506
|
+
@constructs << DateConstruct.new(:date => day_to_add = day_to_add.this(@day_index), :comp_start => @pos + 1, :comp_end => @pos += 1, :found_in => method_name)
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
def match_next_x
|
511
|
+
@components[@pos+1] && @components[@pos+1].digits_only? && @length = @components[@pos+1].to_i
|
512
|
+
end
|
513
|
+
|
514
|
+
def match_next_x_days
|
515
|
+
@components[@pos+2] =~ /days?/ ## "next x days"
|
516
|
+
end
|
517
|
+
|
518
|
+
def found_next_x_days
|
519
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.add_days(@length), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
520
|
+
end
|
521
|
+
|
522
|
+
def match_next_x_weeks
|
523
|
+
@components[@pos+2] =~ /weeks?/ ## "next x weeks"
|
524
|
+
end
|
525
|
+
|
526
|
+
def found_next_x_weeks
|
527
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.add_weeks(@length), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
528
|
+
end
|
529
|
+
|
530
|
+
def match_next_x_months
|
531
|
+
@components[@pos+2] =~ /months?/ ## "next x months"
|
532
|
+
end
|
533
|
+
|
534
|
+
def found_next_x_months
|
535
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.add_months(@length), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
536
|
+
end
|
537
|
+
|
538
|
+
def match_next_x_years
|
539
|
+
@components[@pos+2] =~ /years?/ ## "next x years"
|
540
|
+
end
|
541
|
+
|
542
|
+
def found_next_x_years
|
543
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.add_years(@length), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
544
|
+
end
|
545
|
+
|
546
|
+
def match_next_week
|
547
|
+
@components[@pos+1] =~ /weeks?/
|
548
|
+
end
|
549
|
+
|
550
|
+
def found_next_week
|
551
|
+
sd = @curdate.add_days(7)
|
552
|
+
ed = sd.add_days(7)
|
553
|
+
@constructs << DateSpanConstruct.new(:start_date => sd, :end_date => ed, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
554
|
+
end
|
555
|
+
|
556
|
+
def match_next_month
|
557
|
+
# note it is important that all other uses of "next month" come after indicating words such as "every day next month"; otherwise they will be converted here
|
558
|
+
@components[@pos+1] =~ /months?/
|
559
|
+
end
|
560
|
+
|
561
|
+
def found_next_month
|
562
|
+
sd = @curdate.add_months(1).beginning_of_month
|
563
|
+
ed = sd.end_of_month
|
564
|
+
@constructs << DateSpanConstruct.new(:start_date => sd, :end_date => ed, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
565
|
+
end
|
566
|
+
|
567
|
+
def match_week
|
568
|
+
@components[@pos] == "week"
|
569
|
+
end
|
570
|
+
|
571
|
+
def match_week_of_date
|
572
|
+
@components[@pos+1] == "of" && @date1 = @components[@pos+2].interpret_date(@curdate)
|
573
|
+
end
|
574
|
+
|
575
|
+
def found_week_of_date
|
576
|
+
@constructs << DateSpanConstruct.new(:start_date => @date1, :end_date => @date1.add_days(7), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
577
|
+
end
|
578
|
+
|
579
|
+
def match_week_through_date
|
580
|
+
@components[@pos+1] == "through" && @date1 = @components[@pos+2].interpret_date(@curdate)
|
581
|
+
end
|
582
|
+
|
583
|
+
def found_week_through_date
|
584
|
+
@constructs << DateSpanConstruct.new(:start_date => @date1.sub_days(7), :end_date => @date1, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
585
|
+
end
|
586
|
+
|
587
|
+
def match_x_weeks_from
|
588
|
+
@components[@pos].digits_only? && @components[@pos+1] =~ /^weeks?$/ && @components[@pos+2] == "from" && @length = @components[@pos].to_i # if "x weeks from"
|
589
|
+
end
|
590
|
+
|
591
|
+
def match_x_weeks_from_dayname
|
592
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+3]) # if "x weeks from monday"
|
593
|
+
end
|
594
|
+
|
595
|
+
def found_x_weeks_from_dayname
|
596
|
+
@constructs << DateConstruct.new(:date => @curdate.x_weeks_from_day(@length, @day_index), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
597
|
+
end
|
598
|
+
|
599
|
+
# Reduntant, preprocess out!
|
600
|
+
def match_x_weeks_from_this_dayname
|
601
|
+
@components[@pos+3] == "this" && @day_index = ZDate.days_of_week.index(@components[@pos+4]) # if "x weeks from this monday"
|
602
|
+
end
|
603
|
+
|
604
|
+
# Reduntant, preprocess out!
|
605
|
+
def found_x_weeks_from_this_dayname
|
606
|
+
# this is the exact some construct as found_x_weeks_from_dayname, just position and comp_end has to increment by 1 more; pretty stupid, this should be caught in preprocessing
|
607
|
+
@constructs << DateConstruct.new(:date => @curdate.x_weeks_from_day(@length, @day_index), :comp_start => @pos, :comp_end => @pos += 4, :found_in => method_name)
|
608
|
+
end
|
609
|
+
|
610
|
+
def match_x_weeks_from_next_dayname
|
611
|
+
@components[@pos+3] == "next" && @day_index = ZDate.days_of_week.index(@components[@pos+4]) # if "x weeks from next monday"
|
612
|
+
end
|
613
|
+
|
614
|
+
def found_x_weeks_from_next_dayname
|
615
|
+
@constructs << DateConstruct.new(:date => @curdate.x_weeks_from_day(@length + 1, @day_index), :comp_start => @pos, :comp_end => @pos += 4, :found_in => method_name)
|
616
|
+
end
|
617
|
+
|
618
|
+
def match_x_weeks_from_tomorrow
|
619
|
+
@components[@pos+3] == "tomorrow" # if "x weeks from tomorrow"
|
620
|
+
end
|
621
|
+
|
622
|
+
def found_x_weeks_from_tomorrow
|
623
|
+
@constructs << DateConstruct.new(:date => @curdate.add_days(1).add_weeks(@length), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
624
|
+
end
|
625
|
+
|
626
|
+
def match_x_weeks_from_now
|
627
|
+
@components[@pos+3] =~ /\b(today)|(now)\b/ # if "x weeks from today"
|
628
|
+
end
|
629
|
+
|
630
|
+
def found_x_weeks_from_now
|
631
|
+
@constructs << DateConstruct.new(:date => @curdate.x_weeks_from_day(@length, @curdate.dayindex), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
632
|
+
end
|
633
|
+
|
634
|
+
def match_x_weeks_from_yesterday
|
635
|
+
@components[@pos+3] == "yesterday" # "x weeks from yesterday"
|
636
|
+
end
|
637
|
+
|
638
|
+
def found_x_weeks_from_yesterday
|
639
|
+
@constructs << DateConstruct.new(:date => @curdate.sub_days(1).add_weeks(@length), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
640
|
+
end
|
641
|
+
|
642
|
+
def match_x_months_from
|
643
|
+
@components[@pos].digits_only? && @components[@pos+1] =~ /^months?$/ && @components[@pos+2] == "from" && @length = @components[@pos].to_i # if "x months from"
|
644
|
+
end
|
645
|
+
|
646
|
+
def match_x_months_from_dayname
|
647
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+3]) # if "x months from monday"
|
648
|
+
end
|
649
|
+
|
650
|
+
def found_x_months_from_dayname
|
651
|
+
@constructs << DateConstruct.new(:date => @curdate.this(@day_index).add_months(@length), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
652
|
+
end
|
653
|
+
|
654
|
+
def match_x_months_from_this_dayname
|
655
|
+
@components[@pos+3] == "this" && @day_index = ZDate.days_of_week.index(@components[@pos+4]) # if "x months from this monday"
|
656
|
+
end
|
657
|
+
|
658
|
+
def found_x_months_from_this_dayname
|
659
|
+
@constructs << DateConstruct.new(:date => @curdate.this(@day_index).add_months(@length), :comp_start => @pos, :comp_end => @pos += 4, :found_in => method_name)
|
660
|
+
end
|
661
|
+
|
662
|
+
def match_x_months_from_next_dayname
|
663
|
+
@components[@pos+3] == "next" && @day_index = ZDate.days_of_week.index(@components[@pos+4]) # if "x months from next monday"
|
664
|
+
end
|
665
|
+
|
666
|
+
def found_x_months_from_next_dayname
|
667
|
+
@constructs << DateConstruct.new(:date => @curdate.next(@day_index).add_months(@length), :comp_start => @pos, :comp_end => @pos += 4, :found_in => method_name)
|
668
|
+
end
|
669
|
+
|
670
|
+
def match_x_months_from_tomorrow
|
671
|
+
@components[@pos+3] == "tomorrow" # if "x months from tomorrow"
|
672
|
+
end
|
673
|
+
|
674
|
+
def found_x_months_from_tomorrow
|
675
|
+
@constructs << DateConstruct.new(:date => @curdate.add_days(1).add_months(@length), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
676
|
+
end
|
677
|
+
|
678
|
+
def match_x_months_from_now
|
679
|
+
@components[@pos+3] =~ /\b(today)|(now)\b/ # if "x months from today"
|
680
|
+
end
|
681
|
+
|
682
|
+
def found_x_months_from_now
|
683
|
+
@constructs << DateConstruct.new(:date => @curdate.add_months(@length), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
684
|
+
end
|
685
|
+
|
686
|
+
def match_x_months_from_yesterday
|
687
|
+
@components[@pos+3] == "yesterday" # "x months from yesterday"
|
688
|
+
end
|
689
|
+
|
690
|
+
def found_x_months_from_yesterday
|
691
|
+
@constructs << DateConstruct.new(:date => @curdate.sub_days(1).add_months(@length), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
692
|
+
end
|
693
|
+
|
694
|
+
def match_x_days_from
|
695
|
+
@components[@pos].digits_only? && @components[@pos+1] =~ /^days?$/ && @components[@pos+2] == "from" && @length = @components[@pos].to_i # 3 days from
|
696
|
+
end
|
697
|
+
|
698
|
+
def match_x_days_from_now
|
699
|
+
@components[@pos+3] =~ /\b(now)|(today)\b/ # 3 days from today; 3 days from now
|
700
|
+
end
|
701
|
+
|
702
|
+
def found_x_days_from_now
|
703
|
+
@constructs << DateConstruct.new(:date => @curdate.add_days(@length), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
704
|
+
end
|
705
|
+
|
706
|
+
def match_x_days_from_dayname
|
707
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+3]) # 3 days from monday, why would someone do this?
|
708
|
+
end
|
709
|
+
|
710
|
+
def found_x_days_from_dayname
|
711
|
+
@constructs << DateConstruct.new(:date => @curdate.this(@day_index).add_days(@length), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
712
|
+
end
|
713
|
+
|
714
|
+
def match_x_dayname_from
|
715
|
+
@components[@pos].digits_only? && (@day_index = ZDate.days_of_week.index(@components[@pos+1])) && @components[@pos+2] == "from" && @length = @components[@pos].to_i # "2 tuesdays from"
|
716
|
+
end
|
717
|
+
|
718
|
+
def match_x_dayname_from_now
|
719
|
+
@components[@pos+3] =~ /\b(today)|(now)\b/ # if "2 tuesdays from now"
|
720
|
+
end
|
721
|
+
|
722
|
+
def found_x_dayname_from_now
|
723
|
+
# this isn't exactly intuitive. If someone says "two tuesday from now" and it is tuesday, they mean "in two weeks." If it is not tuesday, they mean "next tuesday"
|
724
|
+
d = (@days_index == @curdate.dayindex) ? @curdate.add_weeks(@length) : @curdate.x_weeks_from_day(@length - 1, @day_index)
|
725
|
+
@constructs << DateConstruct.new(:date => d, :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
726
|
+
end
|
727
|
+
|
728
|
+
def match_x_dayname_from_tomorrow
|
729
|
+
@components[@pos+3] == "tomorrow"
|
730
|
+
end
|
731
|
+
|
732
|
+
def found_x_dayname_from_tomorrow
|
733
|
+
# If someone says "two tuesday from tomorrow" and tomorrow is tuesday, they mean "two weeks from tomorrow." If it is not tuesday, this person does not make sense, but we can interpet it as "next tuesday"
|
734
|
+
tomorrow_index = (@curdate.dayindex + 1) % 7
|
735
|
+
d = (@days_index == tomorrow_index) ? @curdate.add_days(1).add_weeks(@length) : @curdate.x_weeks_from_day(@length - 1, @day_index)
|
736
|
+
@constructs << DateConstruct.new(:date => d, :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
737
|
+
end
|
738
|
+
|
739
|
+
def match_x_dayname_from_yesterday
|
740
|
+
@components[@pos+3] == "yesterday"
|
741
|
+
end
|
742
|
+
|
743
|
+
def found_x_dayname_from_yesterday
|
744
|
+
# If someone says "two tuesday from yesterday" and yesterday was tuesday, they mean "two weeks from yesterday." If it is not tuesday, this person does not make sense, but we can interpet it as "next tuesday"
|
745
|
+
yesterday_index = (@curdate.dayindex == 0 ? 6 : @curdate.dayindex - 1)
|
746
|
+
d = (@days_index == yesterday_index) ? @curdate.sub_days(1).add_weeks(@length) : @curdate.x_weeks_from_day(@length - 1, @day_index)
|
747
|
+
@constructs << DateConstruct.new(:date => d, :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
748
|
+
end
|
749
|
+
|
750
|
+
def match_x_dayname_from_this
|
751
|
+
@components[@pos+3] == "this" # "two tuesdays from this"
|
752
|
+
end
|
753
|
+
|
754
|
+
def found_x_dayname_from_this
|
755
|
+
dc = DateConstruct.new(:date => @curdate.this(@day_index).add_weeks(@length), :comp_start => @pos, :found_in => method_name)
|
756
|
+
if @components[@post+4] == "one" || ZDate.days_of_week.index(@components[@pos+4]) # talk about redundant (2 tuesdays from this one, 2 tuesdays from this tuesday)
|
757
|
+
dc.comp_end = @pos += 4
|
758
|
+
else
|
759
|
+
dc.comp_end = @pos += 3
|
760
|
+
end
|
761
|
+
@constructs << dc
|
762
|
+
end
|
763
|
+
|
764
|
+
def match_x_dayname_from_next
|
765
|
+
@components[@pos+3] == "next" # "two tuesdays from next"
|
766
|
+
end
|
767
|
+
|
768
|
+
def found_x_dayname_from_next
|
769
|
+
dc = DateConstruct.new(:date => @curdate.next(@day_index).add_weeks(@length), :comp_start => @pos, :found_in => method_name)
|
770
|
+
if @components[@post+4] == "one" || ZDate.days_of_week.index(@components[@pos+4]) # talk about redundant (2 tuesdays from next one, 2 tuesdays from next tuesday)
|
771
|
+
dc.comp_end = @pos += 4
|
772
|
+
else
|
773
|
+
dc.comp_end = @pos += 3
|
774
|
+
end
|
775
|
+
@constructs << dc
|
776
|
+
end
|
777
|
+
|
778
|
+
def match_x_minutes_from_now
|
779
|
+
@components[@pos].digits_only? && @components[@pos+1] =~ /minutes?/ && @components[@pos+2] == "from" && @components[@pos+3] =~ /^(today|now)$/ && @length = @components[@pos].to_i
|
780
|
+
end
|
781
|
+
|
782
|
+
def found_x_minutes_from_now
|
783
|
+
date = nil # define out of scope of block
|
784
|
+
time = @curtime.add_minutes(@length) {|days_to_increment| date = @curdate.add_days(days_to_increment)}
|
785
|
+
@constructs << DateConstruct.new(:date => date, :comp_start => @pos, :comp_end => @pos + 4, :found_in => method_name)
|
786
|
+
@constructs << TimeConstruct.new(:time => time, :comp_start => @pos, :comp_end => @pos += 4, :found_in => method_name)
|
787
|
+
end
|
788
|
+
|
789
|
+
def match_x_hours_from_now
|
790
|
+
@components[@pos].digits_only? && @components[@pos+1] =~ /hours?/ && @components[@pos+2] == "from" && @components[@pos+3] =~ /^(today|now)$/ && @length = @components[@pos].to_i
|
791
|
+
end
|
792
|
+
|
793
|
+
def found_x_hours_from_now
|
794
|
+
date = nil
|
795
|
+
time = @curtime.add_hours(@length) {|days_to_increment| date = @curdate.add_days(days_to_increment)}
|
796
|
+
@constructs << DateConstruct.new(:date => date, :comp_start => @pos, :comp_end => @pos + 4, :found_in => method_name)
|
797
|
+
@constructs << TimeConstruct.new(:time => time, :comp_start => @pos, :comp_end => @pos += 4, :found_in => method_name)
|
798
|
+
end
|
799
|
+
|
800
|
+
def match_ordinal_dayname
|
801
|
+
@components[@pos]=~/(1st|2nd|3rd|4th|5th)/ && (@day_index = ZDate.days_of_week.index(@components[@pos+1])) && @week_num = @components[@pos].to_i # last saturday
|
802
|
+
end
|
803
|
+
|
804
|
+
def match_ordinal_dayname_this_month
|
805
|
+
@components[@pos+2] == "this" && @components[@pos+3] == "month" # last saturday this month
|
806
|
+
end
|
807
|
+
|
808
|
+
def found_ordinal_dayname_this_month
|
809
|
+
@constructs << DateConstruct.new(:date => @curdate.ordinal_dayindex(@week_num, @day_index), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
810
|
+
end
|
811
|
+
|
812
|
+
def match_ordinal_dayname_next_month
|
813
|
+
@components[@pos+2] == "next" && @components[@pos+3] == "month" # 1st monday next month
|
814
|
+
end
|
815
|
+
|
816
|
+
def found_ordinal_dayname_next_month
|
817
|
+
@constructs << DateConstruct.new(:date => @curdate.add_months(1).ordinal_dayindex(@week_num, @day_index), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
818
|
+
end
|
819
|
+
|
820
|
+
def match_ordinal_dayname_monthname
|
821
|
+
@month_index = ZDate.months_of_year.index(@components[@pos+2]) # second friday december
|
822
|
+
end
|
823
|
+
|
824
|
+
def found_ordinal_dayname_monthname
|
825
|
+
@constructs << DateConstruct.new(:date => @curdate.jump_to_month(@month_index + 1).ordinal_dayindex(@week_num, @day_index), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
826
|
+
end
|
827
|
+
|
828
|
+
|
829
|
+
def match_ordinal_this_month
|
830
|
+
@components[@pos]=~/(0?[1-9]|[12][0-9]|3[01])(st|nd|rd|th)/ && @components[@pos+1] == 'this' && @components[@pos+2] = 'month' && @length = @components[@pos].to_i # 28th this month
|
831
|
+
end
|
832
|
+
|
833
|
+
def match_ordinal_next_month
|
834
|
+
@components[@pos]=~/(0?[1-9]|[12][0-9]|3[01])(st|nd|rd|th)/ && @components[@pos+1] == 'next' && @components[@pos+2] = 'month' && @length = @components[@pos].to_i # 28th next month
|
835
|
+
end
|
836
|
+
|
837
|
+
def found_ordinal_this_month
|
838
|
+
if NLP::use_date_correction && @curdate.day > @length
|
839
|
+
# e.g. it is the 30th of the month and a user types "1st of the month", they mean "first of next month"
|
840
|
+
date = @curdate.add_months(1).beginning_of_month.add_days(@length - 1)
|
841
|
+
else
|
842
|
+
date = @curdate.beginning_of_month.add_days(@length - 1)
|
843
|
+
end
|
844
|
+
@constructs << DateConstruct.new(:date => date, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
845
|
+
end
|
846
|
+
|
847
|
+
def found_ordinal_next_month
|
848
|
+
@constructs << DateConstruct.new(:date => @curdate.add_months(1).beginning_of_month.add_days(@length - 1), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
849
|
+
end
|
850
|
+
|
851
|
+
|
852
|
+
def match_first_day
|
853
|
+
@components[@pos] == "1st" && @components[@pos+1] == "day" # 1st day
|
854
|
+
end
|
855
|
+
|
856
|
+
def match_first_day_this_month
|
857
|
+
@components[@pos+2] == "this" && @components[@pos+3] == "month" # 1st day this month
|
858
|
+
end
|
859
|
+
|
860
|
+
def found_first_day_this_month
|
861
|
+
@constructs << DateConstruct.new(:date => @curdate.beginning_of_month, :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
862
|
+
end
|
863
|
+
|
864
|
+
def match_first_day_next_month
|
865
|
+
@components[@pos+2] == "next" && @components[@pos+3] == "month" # 1st day next month
|
866
|
+
end
|
867
|
+
|
868
|
+
def found_first_day_next_month
|
869
|
+
@constructs << DateConstruct.new(:date => @curdate.add_months(1).beginning_of_month, :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
870
|
+
end
|
871
|
+
|
872
|
+
def match_first_day_monthname
|
873
|
+
@month_index = ZDate.months_of_year.index(@components[@pos+2]) # 1st day december
|
874
|
+
end
|
875
|
+
|
876
|
+
def found_first_day_monthname
|
877
|
+
@constructs << DateConstruct.new(:date => @curdate.jump_to_month(@month_index + 1), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
878
|
+
end
|
879
|
+
|
880
|
+
def match_last_day
|
881
|
+
@components[@pos] == "last" && @components[@pos+1] == "day" # last day
|
882
|
+
end
|
883
|
+
|
884
|
+
def match_last_day_this_month
|
885
|
+
@components[@pos+2] == "this" && @components[@pos+3] == "month" # 1st day this month
|
886
|
+
end
|
887
|
+
|
888
|
+
def found_last_day_this_month
|
889
|
+
@constructs << DateConstruct.new(:date => @curdate.end_of_month, :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
890
|
+
end
|
891
|
+
|
892
|
+
def match_last_day_next_month
|
893
|
+
@components[@pos+2] == "next" && @components[@pos+3] == "month" # 1st day next month
|
894
|
+
end
|
895
|
+
|
896
|
+
def found_last_day_next_month
|
897
|
+
@constructs << DateConstruct.new(:date => @curdate.add_months(1).end_of_month, :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
898
|
+
end
|
899
|
+
|
900
|
+
def match_last_day_monthname
|
901
|
+
@month_index = ZDate.months_of_year.index(@components[@pos+2]) # 1st day december
|
902
|
+
end
|
903
|
+
|
904
|
+
def found_last_day_monthname
|
905
|
+
@constructs << DateConstruct.new(:date => @curdate.jump_to_month(@month_index + 1).end_of_month, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
906
|
+
end
|
907
|
+
|
908
|
+
def match_at
|
909
|
+
@components[@pos]=="at"
|
910
|
+
end
|
911
|
+
|
912
|
+
def match_at_time
|
913
|
+
@components[@pos+1] && @time1 = @components[@pos+1].interpret_time
|
914
|
+
end
|
915
|
+
|
916
|
+
def match_at_time_through_time
|
917
|
+
@components[@pos+2] =~ /^(to|until|through)$/ && @components[@pos+3] && @time2 = @components[@pos+3].interpret_time
|
918
|
+
end
|
919
|
+
|
920
|
+
def found_at_time_through_time
|
921
|
+
@constructs << TimeSpanConstruct.new(:start_time => @time1, :end_time => @time2, :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
922
|
+
end
|
923
|
+
|
924
|
+
def found_at_time
|
925
|
+
@constructs << TimeConstruct.new(:time => @time1, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
926
|
+
end
|
927
|
+
|
928
|
+
def match_all_day
|
929
|
+
@components[@pos]=="all" && @components[@pos+1]=="day" # all day
|
930
|
+
end
|
931
|
+
|
932
|
+
def found_all_day
|
933
|
+
@constructs << TimeConstruct.new(:time => nil, :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
934
|
+
end
|
935
|
+
|
936
|
+
def match_tomorrow
|
937
|
+
@components[@pos]=="tomorrow"
|
938
|
+
end
|
939
|
+
|
940
|
+
def match_tomorrow_through
|
941
|
+
@components[@pos+1]=="until" || @components[@pos+1] == "to" || @components[@pos+1] == "through" # "tomorrow through"
|
942
|
+
end
|
943
|
+
|
944
|
+
def match_tomorrow_through_dayname
|
945
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+2]) # tomorrow through thursday
|
946
|
+
end
|
947
|
+
|
948
|
+
def found_tomorrow_through_dayname
|
949
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate.add_days(1), :end_date => @curdate.add_days(1).this(@day_index), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
950
|
+
end
|
951
|
+
|
952
|
+
def match_tomorrow_through_date
|
953
|
+
@date1 = @components[@pos+2].interpret_date(@curdate) # tomorrow until 9/21
|
954
|
+
end
|
955
|
+
|
956
|
+
def found_tomorrow_through_date
|
957
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate.add_days(1), :end_date => @date1, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
958
|
+
end
|
959
|
+
|
960
|
+
def found_tomorrow
|
961
|
+
@constructs << DateConstruct.new(:date => @curdate.add_days(1), :comp_start => @pos, :comp_end => @pos, :found_in => method_name)
|
962
|
+
end
|
963
|
+
|
964
|
+
def match_now
|
965
|
+
@components[@pos]=="today" || @components[@pos]=="now"
|
966
|
+
end
|
967
|
+
|
968
|
+
def match_now_through
|
969
|
+
@components[@pos+1]=="until" || @components[@pos+1] == "to" || @components[@pos+1] == "through" # "today through"
|
970
|
+
end
|
971
|
+
|
972
|
+
def match_now_through_dayname
|
973
|
+
@day_index = ZDate.days_of_week.index(@components[@pos+2]) # today through thursday
|
974
|
+
end
|
975
|
+
|
976
|
+
def found_now_through_dayname
|
977
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.this(@day_index), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
978
|
+
end
|
979
|
+
|
980
|
+
# redundant!! preprocess this out of here!
|
981
|
+
def match_now_through_following_dayname
|
982
|
+
@components[@pos+2] =~ /following|this/ && @day_index = ZDate.days_of_week.index(@components[@pos+3]) # today through following friday
|
983
|
+
end
|
984
|
+
|
985
|
+
# redundant!! preprocess this out of here!
|
986
|
+
def found_now_through_following_dayname
|
987
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.this(@day_index), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
988
|
+
end
|
989
|
+
|
990
|
+
def match_now_through_date
|
991
|
+
@date1 = @components[@pos+2].interpret_date(@curdate) # now until 9/21
|
992
|
+
end
|
993
|
+
|
994
|
+
def found_now_through_date
|
995
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @date1, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
996
|
+
end
|
997
|
+
|
998
|
+
def match_now_through_tomorrow
|
999
|
+
@components[@pos+2]=="tomorrow"
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
def found_now_through_tomorrow
|
1003
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.add_days(1), :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
def match_now_through_next_dayname
|
1007
|
+
@components[@pos+2] == "next" && @day_index = ZDate.days_of_week.index(@components[@pos+3]) # Today through next friday
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
def found_now_through_next_dayname
|
1011
|
+
@constructs << DateSpanConstruct.new(:start_date => @curdate, :end_date => @curdate.next(@day_index), :comp_start => @pos, :comp_end => @pos += 3, :found_in => method_name)
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
def found_now
|
1015
|
+
@constructs << DateConstruct.new(:date => @curdate, :comp_start => @pos, :comp_end => @pos, :found_in => method_name)
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
def match_dayname
|
1019
|
+
@day_index = ZDate.days_of_week.index(@components[@pos])
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
def match_dayname_the_ordinal
|
1023
|
+
@components[@pos+1] == "the" && @date1 = @components[@pos+2].interpret_date(@curdate) # if "tue the 23rd"
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
def found_dayname_the_ordinal
|
1027
|
+
# user may have specified "monday the 2nd" while in the previous month, so first check if dayname matches date.dayname, if it doesn't increment by a month and check again
|
1028
|
+
if @date1.dayname == @components[@pos] || ((tmp = @date1.add_months(1)) && tmp.dayname == @components[@pos] && @date1 = tmp)
|
1029
|
+
@constructs << DateConstruct.new(:date => @date1, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
1030
|
+
end
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
def match_dayname_x_weeks_from_this
|
1034
|
+
@components[@pos+1] && @components[@pos+1].digits_only? && @components[@pos+2] =~ /\bweeks?\b/ && @components[@pos+3] =~ /\b(from)|(after)/ && @components[@pos+4] == "this" && @length = @components[@pos+1] # "monday two weeks from this
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
def found_dayname_x_weeks_from_this
|
1038
|
+
dc = DateConstruct.new(:date => @curdate.this(@dayindex).add_weeks(@length), :comp_start => @pos, :found_in => method_name)
|
1039
|
+
if ZDate.days_of_week.include?(@components[@pos+5]) #redundant
|
1040
|
+
dc.comp_end = @pos += 5
|
1041
|
+
else
|
1042
|
+
dc.comp_end = @pos += 4
|
1043
|
+
end
|
1044
|
+
@constructs << dc
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
def match_dayname_x_weeks_from_next
|
1048
|
+
@components[@pos+1] && @components[@pos+1].digits_only? && @components[@pos+2] =~ /\bweeks?\b/ && @components[@pos+3] =~ /\b(from)|(after)/ && @components[@pos+4] == "next" && @length = @components[@pos+1] # "monday two weeks from this
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
def found_dayname_x_weeks_from_next
|
1052
|
+
dc = DateConstruct.new(:date => @curdate.next(@dayindex).add_weeks(@length), :comp_start => @pos, :found_in => method_name)
|
1053
|
+
if ZDate.days_of_week.include?(@components[@pos+5]) #redundant
|
1054
|
+
dc.comp_end = @pos += 5
|
1055
|
+
else
|
1056
|
+
dc.comp_end = @pos += 4
|
1057
|
+
end
|
1058
|
+
@constructs << h
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
# redundant, same as found_this_dayname
|
1062
|
+
def found_dayname
|
1063
|
+
day_to_add = @curdate.this(@day_index)
|
1064
|
+
@constructs << DateConstruct.new(:date => day_to_add, :comp_start => @pos, :comp_end => @pos, :found_in => method_name)
|
1065
|
+
while @components[@pos+1] && @day_index = ZDate.days_of_week.index(@components[@pos+1])
|
1066
|
+
# note @pos gets incremented here:
|
1067
|
+
@constructs << DateConstruct.new(:date => day_to_add = day_to_add.this(@day_index), :comp_start => @pos + 1, :comp_end => @pos += 1, :found_in => method_name)
|
1068
|
+
end
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
def match_through_monthname
|
1072
|
+
@components[@pos] == "through" && @month_index = ZDate.months_of_year.index(@components[@pos+1])
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
def found_through_monthname
|
1076
|
+
# this is really a wrapper, we don't know when the start date is, so make sure @constructs gets wrapper first, as date constructs always have to appear after wrapper
|
1077
|
+
@constructs << WrapperConstruct.new(:wrapper_type => 1, :comp_start => @pos, :comp_end => @pos + 1, :found_in => method_name)
|
1078
|
+
@constructs << DateConstruct.new(:date => @curdate.jump_to_month(@month_index + 1).sub_days(1), :comp_start => @pos, :comp_end => @pos += 1, :found_in => method_name)
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
def match_monthname
|
1082
|
+
# note it is important that all other uses of monthname come after indicating words such as "the third day of december"; otherwise they will be converted here
|
1083
|
+
@month_index = ZDate.months_of_year.index(@components[@pos])
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
def found_monthname
|
1087
|
+
sd = @curdate.jump_to_month(@month_index + 1)
|
1088
|
+
ed = sd.end_of_month
|
1089
|
+
@constructs << DateSpanConstruct.new(:start_date => sd, :end_date => ed, :comp_start => @pos, :comp_end => @pos, :found_in => method_name)
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
|
1093
|
+
def match_start
|
1094
|
+
@components[@pos] == "start"
|
1095
|
+
end
|
1096
|
+
|
1097
|
+
def found_start
|
1098
|
+
#wrapper_type 0 is a start wrapper
|
1099
|
+
@constructs << WrapperConstruct.new(:wrapper_type => 0, :comp_start => @pos, :comp_end => @pos, :found_in => method_name)
|
1100
|
+
end
|
1101
|
+
|
1102
|
+
def match_through
|
1103
|
+
@components[@pos] == "through"
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
def found_through
|
1107
|
+
#wrapper_type 1 is an end wrapper
|
1108
|
+
@constructs << WrapperConstruct.new(:wrapper_type => 1, :comp_start => @pos, :comp_end => @pos, :found_in => method_name)
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
def match_time
|
1112
|
+
@time1 = @components[@pos].interpret_time
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
def match_time_through_time
|
1116
|
+
@components[@pos+1] =~ /^(to|through)$/ && @time2 = @components[@pos+2].interpret_time
|
1117
|
+
end
|
1118
|
+
|
1119
|
+
def found_time_through_time
|
1120
|
+
@constructs << TimeSpanConstruct.new(:start_time => @time1, :end_time => @time2, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
1121
|
+
end
|
1122
|
+
|
1123
|
+
def found_time
|
1124
|
+
@constructs << TimeConstruct.new(:time => @time1, :comp_start => @pos, :comp_end => @pos, :found_in => method_name)
|
1125
|
+
match = true
|
1126
|
+
end
|
1127
|
+
|
1128
|
+
def match_date
|
1129
|
+
@date1 = @components[@pos].interpret_date(@curdate)
|
1130
|
+
end
|
1131
|
+
|
1132
|
+
def match_date_through_date
|
1133
|
+
@components[@pos+1] =~ /^(through|to|until)$/ && @date2 = @components[@pos+2].interpret_date(@curdate)
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
def found_date_through_date
|
1137
|
+
@constructs << DateSpanConstruct.new(:start_date => @date1, :end_date => @date2, :comp_start => @pos, :comp_end => @pos += 2, :found_in => method_name)
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
def found_date
|
1141
|
+
@constructs << DateConstruct.new(:date => @date1, :comp_start => @pos, :comp_end => @pos, :found_in => method_name)
|
1142
|
+
end
|
1143
|
+
end # END class ConstructFinder
|
1144
|
+
end
|
1145
|
+
|