hizuke 0.0.4 → 0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +1 -1
- data/README.md +3 -0
- data/Rakefile +6 -6
- data/hizuke.gemspec +21 -18
- data/lib/hizuke/constants.rb +86 -0
- data/lib/hizuke/date_calculator.rb +458 -0
- data/lib/hizuke/parser.rb +67 -500
- data/lib/hizuke/pattern_matcher.rb +495 -0
- data/lib/hizuke/version.rb +2 -2
- data/lib/hizuke.rb +31 -4
- metadata +5 -2
@@ -0,0 +1,495 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hizuke
|
4
|
+
# Module for working with time patterns
|
5
|
+
module TimePatternMatcher
|
6
|
+
include Constants
|
7
|
+
|
8
|
+
# Extract time references from the text
|
9
|
+
# @param text [String] the original text
|
10
|
+
# @return [Array] an array containing the extracted time and clean text
|
11
|
+
def extract_time_references(text)
|
12
|
+
clean_text = text
|
13
|
+
extracted_time = nil
|
14
|
+
|
15
|
+
# Try each type of time pattern
|
16
|
+
result = try_word_time_patterns(clean_text) ||
|
17
|
+
try_numeric_time_pattern(clean_text)
|
18
|
+
|
19
|
+
extracted_time, clean_text = result if result
|
20
|
+
|
21
|
+
[extracted_time, clean_text]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Try to match word-based time patterns
|
25
|
+
# @param text [String] the original text
|
26
|
+
# @return [Array, nil] an array containing the extracted time and clean text, or nil if no match
|
27
|
+
def try_word_time_patterns(text)
|
28
|
+
match_noon_pattern(text) ||
|
29
|
+
match_midnight_pattern(text) ||
|
30
|
+
match_morning_pattern(text) ||
|
31
|
+
match_evening_pattern(text)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Match the noon pattern in the text
|
35
|
+
# @param text [String] the original text
|
36
|
+
# @return [Array, nil] an array containing the extracted time and clean text, or nil if no match
|
37
|
+
def match_noon_pattern(text)
|
38
|
+
match_and_process(text, NOON_PATTERN) do
|
39
|
+
TimeOfDay.new(12, 0, 0)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Match the midnight pattern in the text
|
44
|
+
# @param text [String] the original text
|
45
|
+
# @return [Array, nil] an array containing the extracted time and clean text, or nil if no match
|
46
|
+
def match_midnight_pattern(text)
|
47
|
+
match_and_process(text, MIDNIGHT_PATTERN) do
|
48
|
+
TimeOfDay.new(0, 0, 0)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Match the morning pattern in the text
|
53
|
+
# @param text [String] the original text
|
54
|
+
# @return [Array, nil] an array containing the extracted time and clean text, or nil if no match
|
55
|
+
def match_morning_pattern(text)
|
56
|
+
match_and_process(text, MORNING_PATTERN) do
|
57
|
+
config = Hizuke.configuration
|
58
|
+
TimeOfDay.new(config.morning_time[:hour], config.morning_time[:min], 0)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Match the evening pattern in the text
|
63
|
+
# @param text [String] the original text
|
64
|
+
# @return [Array, nil] an array containing the extracted time and clean text, or nil if no match
|
65
|
+
def match_evening_pattern(text)
|
66
|
+
match_and_process(text, EVENING_PATTERN) do
|
67
|
+
config = Hizuke.configuration
|
68
|
+
TimeOfDay.new(config.evening_time[:hour], config.evening_time[:min], 0)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Match a pattern and process it with the given block
|
73
|
+
# @param text [String] the original text
|
74
|
+
# @param pattern [Regexp] the pattern to match
|
75
|
+
# @yield a block that creates a TimeOfDay object
|
76
|
+
# @return [Array, nil] an array containing the extracted time and clean text, or nil if no match
|
77
|
+
def match_and_process(text, pattern)
|
78
|
+
return nil unless (match = text.match(pattern))
|
79
|
+
|
80
|
+
time = yield
|
81
|
+
clean_text = text.gsub(match[0], '').strip
|
82
|
+
[time, clean_text]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Try to match numeric time pattern
|
86
|
+
# @param text [String] the original text
|
87
|
+
# @return [Array, nil] an array containing the extracted time and clean text, or nil if no match
|
88
|
+
def try_numeric_time_pattern(text)
|
89
|
+
if (time_match = text.match(TIME_PATTERN))
|
90
|
+
extracted_time = process_time_match(time_match)
|
91
|
+
# Remove the time expression from the text
|
92
|
+
clean_text = text.gsub(time_match[0], '').strip
|
93
|
+
return [extracted_time, clean_text]
|
94
|
+
end
|
95
|
+
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
|
99
|
+
# Process a time match and create a TimeOfDay object
|
100
|
+
# @param time_match [MatchData] the regex match data
|
101
|
+
# @return [TimeOfDay] the created time of day object
|
102
|
+
def process_time_match(time_match)
|
103
|
+
hour = parse_hour(time_match[1])
|
104
|
+
min = parse_minute(time_match[2])
|
105
|
+
sec = parse_second(time_match[3])
|
106
|
+
|
107
|
+
# Adjust for AM/PM
|
108
|
+
hour = adjust_hour_for_meridiem(hour, time_match[4])
|
109
|
+
|
110
|
+
TimeOfDay.new(hour, min, sec)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Parse hour from match data
|
114
|
+
# @param hour_str [String, nil] the hour part of the match
|
115
|
+
# @return [Integer] the parsed hour
|
116
|
+
def parse_hour(hour_str)
|
117
|
+
hour_str.to_i
|
118
|
+
end
|
119
|
+
|
120
|
+
# Parse minute from match data
|
121
|
+
# @param min_str [String, nil] the minute part of the match
|
122
|
+
# @return [Integer] the parsed minute
|
123
|
+
def parse_minute(min_str)
|
124
|
+
min_str ? min_str.to_i : 0
|
125
|
+
end
|
126
|
+
|
127
|
+
# Parse second from match data
|
128
|
+
# @param sec_str [String, nil] the second part of the match
|
129
|
+
# @return [Integer] the parsed second
|
130
|
+
def parse_second(sec_str)
|
131
|
+
sec_str ? sec_str.to_i : 0
|
132
|
+
end
|
133
|
+
|
134
|
+
# Adjust hour based on AM/PM designation
|
135
|
+
# @param hour [Integer] the hour to adjust
|
136
|
+
# @param meridiem [String, nil] the meridiem designation (am/pm)
|
137
|
+
# @return [Integer] the adjusted hour
|
138
|
+
def adjust_hour_for_meridiem(hour, meridiem)
|
139
|
+
if meridiem&.downcase == 'pm' && hour < 12
|
140
|
+
hour + 12
|
141
|
+
elsif meridiem&.downcase == 'am' && hour == 12
|
142
|
+
0
|
143
|
+
else
|
144
|
+
hour
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Module for handling day of week patterns
|
150
|
+
module DayOfWeekPatternMatcher
|
151
|
+
include Constants
|
152
|
+
|
153
|
+
# Check for day of week patterns (this Monday, next Tuesday, last Friday, etc.)
|
154
|
+
# @param text [String] the text to check
|
155
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
156
|
+
def check_day_of_week_patterns(text)
|
157
|
+
# Try each day of week pattern
|
158
|
+
check_this_day_pattern(text) ||
|
159
|
+
check_next_day_pattern(text) ||
|
160
|
+
check_last_day_pattern(text)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Check for "this [day]" pattern
|
164
|
+
# @param text [String] the text to check
|
165
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
166
|
+
def check_this_day_pattern(text)
|
167
|
+
if (match = text.match(THIS_DAY_PATTERN))
|
168
|
+
day_name = match[1].downcase
|
169
|
+
day_value = DAYS_OF_WEEK[day_name]
|
170
|
+
date = calculate_this_day(day_value)
|
171
|
+
clean_text = text.gsub(match[0], '').strip
|
172
|
+
return Result.new(clean_text, date)
|
173
|
+
end
|
174
|
+
|
175
|
+
nil
|
176
|
+
end
|
177
|
+
|
178
|
+
# Check for "next [day]" pattern
|
179
|
+
# @param text [String] the text to check
|
180
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
181
|
+
def check_next_day_pattern(text)
|
182
|
+
if (match = text.match(NEXT_DAY_PATTERN))
|
183
|
+
day_name = match[1].downcase
|
184
|
+
day_value = DAYS_OF_WEEK[day_name]
|
185
|
+
date = calculate_next_day(day_value)
|
186
|
+
clean_text = text.gsub(match[0], '').strip
|
187
|
+
return Result.new(clean_text, date)
|
188
|
+
end
|
189
|
+
|
190
|
+
nil
|
191
|
+
end
|
192
|
+
|
193
|
+
# Check for "last [day]" pattern
|
194
|
+
# @param text [String] the text to check
|
195
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
196
|
+
def check_last_day_pattern(text)
|
197
|
+
if (match = text.match(LAST_DAY_PATTERN))
|
198
|
+
day_name = match[1].downcase
|
199
|
+
day_value = DAYS_OF_WEEK[day_name]
|
200
|
+
date = calculate_last_day(day_value)
|
201
|
+
clean_text = text.gsub(match[0], '').strip
|
202
|
+
return Result.new(clean_text, date)
|
203
|
+
end
|
204
|
+
|
205
|
+
nil
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Module for dynamic date patterns (in X days, X days ago, etc.)
|
210
|
+
module DynamicPatternMatcher
|
211
|
+
include Constants
|
212
|
+
|
213
|
+
# Check for dynamic date patterns like "in X days" or "X days ago"
|
214
|
+
# @param text [String] the text to check
|
215
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
216
|
+
def check_dynamic_patterns(text)
|
217
|
+
# Try each pattern type
|
218
|
+
check_days_patterns(text) ||
|
219
|
+
check_weeks_patterns(text) ||
|
220
|
+
check_months_patterns(text) ||
|
221
|
+
check_years_patterns(text)
|
222
|
+
end
|
223
|
+
|
224
|
+
# Check for days-related patterns
|
225
|
+
# @param text [String] the text to check
|
226
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
227
|
+
def check_days_patterns(text)
|
228
|
+
check_in_x_days_pattern(text) || check_x_days_ago_pattern(text)
|
229
|
+
end
|
230
|
+
|
231
|
+
# Check for "in X days" pattern
|
232
|
+
# @param text [String] the text to check
|
233
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
234
|
+
def check_in_x_days_pattern(text)
|
235
|
+
if (match = text.match(IN_X_DAYS_PATTERN))
|
236
|
+
days = match[1].to_i
|
237
|
+
date = Date.today + days
|
238
|
+
clean_text = text.gsub(match[0], '').strip
|
239
|
+
return Result.new(clean_text, date)
|
240
|
+
end
|
241
|
+
nil
|
242
|
+
end
|
243
|
+
|
244
|
+
# Check for "X days ago" pattern
|
245
|
+
# @param text [String] the text to check
|
246
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
247
|
+
def check_x_days_ago_pattern(text)
|
248
|
+
if (match = text.match(X_DAYS_AGO_PATTERN))
|
249
|
+
days = match[1].to_i
|
250
|
+
date = Date.today - days
|
251
|
+
clean_text = text.gsub(match[0], '').strip
|
252
|
+
return Result.new(clean_text, date)
|
253
|
+
end
|
254
|
+
nil
|
255
|
+
end
|
256
|
+
|
257
|
+
# Check for weeks-related patterns
|
258
|
+
# @param text [String] the text to check
|
259
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
260
|
+
def check_weeks_patterns(text)
|
261
|
+
check_in_x_weeks_pattern(text) || check_x_weeks_ago_pattern(text)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Check for "in X weeks" pattern
|
265
|
+
# @param text [String] the text to check
|
266
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
267
|
+
def check_in_x_weeks_pattern(text)
|
268
|
+
if (match = text.match(IN_X_WEEKS_PATTERN))
|
269
|
+
weeks = match[1].to_i
|
270
|
+
date = Date.today + (weeks * 7)
|
271
|
+
clean_text = text.gsub(match[0], '').strip
|
272
|
+
return Result.new(clean_text, date)
|
273
|
+
end
|
274
|
+
nil
|
275
|
+
end
|
276
|
+
|
277
|
+
# Check for "X weeks ago" pattern
|
278
|
+
# @param text [String] the text to check
|
279
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
280
|
+
def check_x_weeks_ago_pattern(text)
|
281
|
+
if (match = text.match(X_WEEKS_AGO_PATTERN))
|
282
|
+
weeks = match[1].to_i
|
283
|
+
date = Date.today - (weeks * 7)
|
284
|
+
clean_text = text.gsub(match[0], '').strip
|
285
|
+
return Result.new(clean_text, date)
|
286
|
+
end
|
287
|
+
nil
|
288
|
+
end
|
289
|
+
|
290
|
+
# Check for months-related patterns
|
291
|
+
# @param text [String] the text to check
|
292
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
293
|
+
def check_months_patterns(text)
|
294
|
+
check_in_x_months_pattern(text) || check_x_months_ago_pattern(text)
|
295
|
+
end
|
296
|
+
|
297
|
+
# Check for "in X months" pattern
|
298
|
+
# @param text [String] the text to check
|
299
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
300
|
+
def check_in_x_months_pattern(text)
|
301
|
+
if (match = text.match(IN_X_MONTHS_PATTERN))
|
302
|
+
months = match[1].to_i
|
303
|
+
date = Date.today >> months
|
304
|
+
clean_text = text.gsub(match[0], '').strip
|
305
|
+
return Result.new(clean_text, date)
|
306
|
+
end
|
307
|
+
nil
|
308
|
+
end
|
309
|
+
|
310
|
+
# Check for "X months ago" pattern
|
311
|
+
# @param text [String] the text to check
|
312
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
313
|
+
def check_x_months_ago_pattern(text)
|
314
|
+
if (match = text.match(X_MONTHS_AGO_PATTERN))
|
315
|
+
months = match[1].to_i
|
316
|
+
date = Date.today << months
|
317
|
+
clean_text = text.gsub(match[0], '').strip
|
318
|
+
return Result.new(clean_text, date)
|
319
|
+
end
|
320
|
+
nil
|
321
|
+
end
|
322
|
+
|
323
|
+
# Check for years-related patterns
|
324
|
+
# @param text [String] the text to check
|
325
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
326
|
+
def check_years_patterns(text)
|
327
|
+
check_in_x_years_pattern(text) || check_x_years_ago_pattern(text)
|
328
|
+
end
|
329
|
+
|
330
|
+
# Check for "in X years" pattern
|
331
|
+
# @param text [String] the text to check
|
332
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
333
|
+
def check_in_x_years_pattern(text)
|
334
|
+
if (match = text.match(IN_X_YEARS_PATTERN))
|
335
|
+
years = match[1].to_i
|
336
|
+
date = Date.new(Date.today.year + years, Date.today.month, Date.today.day)
|
337
|
+
clean_text = text.gsub(match[0], '').strip
|
338
|
+
return Result.new(clean_text, date)
|
339
|
+
end
|
340
|
+
nil
|
341
|
+
end
|
342
|
+
|
343
|
+
# Check for "X years ago" pattern
|
344
|
+
# @param text [String] the text to check
|
345
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
346
|
+
def check_x_years_ago_pattern(text)
|
347
|
+
if (match = text.match(X_YEARS_AGO_PATTERN))
|
348
|
+
years = match[1].to_i
|
349
|
+
date = Date.new(Date.today.year - years, Date.today.month, Date.today.day)
|
350
|
+
clean_text = text.gsub(match[0], '').strip
|
351
|
+
return Result.new(clean_text, date)
|
352
|
+
end
|
353
|
+
nil
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# Module for compound date expressions and keywords
|
358
|
+
module DateKeywordMatcher
|
359
|
+
include Constants
|
360
|
+
|
361
|
+
# Try different parsing strategies to find a date reference
|
362
|
+
# @param clean_text [String] the text without time references
|
363
|
+
# @return [Hizuke::Result, nil] the parsing result or nil if no date reference is found
|
364
|
+
def try_parsing_strategies(clean_text)
|
365
|
+
# Check for dynamic patterns first (in X days, X days ago)
|
366
|
+
result = check_dynamic_patterns(clean_text)
|
367
|
+
return result if result
|
368
|
+
|
369
|
+
# Check for day of week patterns (this Monday, next Tuesday, etc.)
|
370
|
+
result = check_day_of_week_patterns(clean_text)
|
371
|
+
return result if result
|
372
|
+
|
373
|
+
# Try to find compound date expressions (like "next week")
|
374
|
+
result = check_compound_date_expressions(clean_text)
|
375
|
+
return result if result
|
376
|
+
|
377
|
+
# Try to find single-word date references
|
378
|
+
result = check_single_word_date_references(clean_text)
|
379
|
+
return result if result
|
380
|
+
|
381
|
+
# If no date reference was found, return nil instead of today's date
|
382
|
+
nil
|
383
|
+
end
|
384
|
+
|
385
|
+
# Check for compound date expressions like "next week"
|
386
|
+
# @param clean_text [String] the text to check
|
387
|
+
# @return [Hizuke::Result, nil] the result or nil if no match
|
388
|
+
def check_compound_date_expressions(clean_text)
|
389
|
+
compound_matches = find_compound_matches(clean_text)
|
390
|
+
|
391
|
+
# If we found compound matches, handle them specially
|
392
|
+
return nil if compound_matches.empty?
|
393
|
+
|
394
|
+
# Use the first match (in case there are multiple)
|
395
|
+
match_key, indices = compound_matches.min_by { |_, v| v[0] }
|
396
|
+
|
397
|
+
process_compound_match(clean_text, match_key, indices)
|
398
|
+
end
|
399
|
+
|
400
|
+
# Process a compound date expression match
|
401
|
+
# @param clean_text [String] the text to check
|
402
|
+
# @param match_key [String] the matched keyword
|
403
|
+
# @param indices [Array<Integer>] the start and end indices of the match
|
404
|
+
# @return [Hizuke::Result] the result
|
405
|
+
def process_compound_match(clean_text, match_key, indices)
|
406
|
+
# Calculate date based on the keyword
|
407
|
+
date_value = DATE_KEYWORDS[match_key]
|
408
|
+
date = calculate_date(date_value)
|
409
|
+
|
410
|
+
# Remove the date expression from the text
|
411
|
+
final_text = clean_text.dup
|
412
|
+
final_text.slice!(indices[0]..indices[1])
|
413
|
+
|
414
|
+
Result.new(final_text.strip, date)
|
415
|
+
end
|
416
|
+
|
417
|
+
# Find compound date expressions in the text
|
418
|
+
# @param clean_text [String] the text to check
|
419
|
+
# @return [Hash] a hash of matches and their indices
|
420
|
+
def find_compound_matches(clean_text)
|
421
|
+
compound_matches = {}
|
422
|
+
|
423
|
+
find_compound_keywords.each do |compound_key|
|
424
|
+
next unless clean_text.downcase.include?(compound_key)
|
425
|
+
|
426
|
+
start_idx = clean_text.downcase.index(compound_key)
|
427
|
+
end_idx = start_idx + compound_key.length - 1
|
428
|
+
compound_matches[compound_key] = [start_idx, end_idx]
|
429
|
+
end
|
430
|
+
|
431
|
+
compound_matches
|
432
|
+
end
|
433
|
+
|
434
|
+
# Find compound keywords (containing spaces)
|
435
|
+
# @return [Array<String>] array of compound keywords
|
436
|
+
def find_compound_keywords
|
437
|
+
DATE_KEYWORDS.keys.select { |k| k.include?(' ') }
|
438
|
+
end
|
439
|
+
|
440
|
+
# Check for single-word date references
|
441
|
+
# @param clean_text [String] the text to check
|
442
|
+
# @return [Hizuke::Result, nil] the parsing result or nil if no keyword found
|
443
|
+
def check_single_word_date_references(clean_text)
|
444
|
+
# Split the text into words
|
445
|
+
words = clean_text.split
|
446
|
+
|
447
|
+
# Find the matching date keyword
|
448
|
+
date_match = find_date_keyword_match(words)
|
449
|
+
|
450
|
+
# If no reference was found, return nil
|
451
|
+
return nil unless date_match
|
452
|
+
|
453
|
+
# Calculate the date based on the keyword
|
454
|
+
date = calculate_date(date_match[:value])
|
455
|
+
|
456
|
+
# Create the clean text by removing the date keyword
|
457
|
+
final_text = remove_date_keyword_from_text(words, date_match[:index])
|
458
|
+
|
459
|
+
Result.new(final_text, date)
|
460
|
+
end
|
461
|
+
|
462
|
+
# Find a date keyword match in the words
|
463
|
+
# @param words [Array<String>] the words to check
|
464
|
+
# @return [Hash, nil] a hash with the index and value of the match or nil if no match
|
465
|
+
def find_date_keyword_match(words)
|
466
|
+
words.each_with_index do |word, index|
|
467
|
+
clean_word = word.downcase.gsub(/[^a-z]/, '')
|
468
|
+
next unless DATE_KEYWORDS.key?(clean_word)
|
469
|
+
|
470
|
+
return { index: index, value: DATE_KEYWORDS[clean_word] }
|
471
|
+
end
|
472
|
+
|
473
|
+
nil
|
474
|
+
end
|
475
|
+
|
476
|
+
# Remove the date keyword from the text
|
477
|
+
# @param words [Array<String>] the words array
|
478
|
+
# @param index [Integer] the index of the keyword to remove
|
479
|
+
# @return [String] the text without the keyword
|
480
|
+
def remove_date_keyword_from_text(words, index)
|
481
|
+
clean_words = words.dup
|
482
|
+
clean_words.delete_at(index)
|
483
|
+
clean_words.join(' ').strip
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
# Main module for pattern matching in text
|
488
|
+
module PatternMatcher
|
489
|
+
include Constants
|
490
|
+
include TimePatternMatcher
|
491
|
+
include DayOfWeekPatternMatcher
|
492
|
+
include DynamicPatternMatcher
|
493
|
+
include DateKeywordMatcher
|
494
|
+
end
|
495
|
+
end
|
data/lib/hizuke/version.rb
CHANGED
data/lib/hizuke.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative 'hizuke/version'
|
4
|
+
require_relative 'hizuke/parser'
|
5
5
|
|
6
|
-
# Hizuke is a simple date parser that extracts dates from
|
6
|
+
# Hizuke is a simple date parser that extracts dates from tex
|
7
7
|
# containing time references like "yesterday", "today", and "tomorrow".
|
8
8
|
#
|
9
9
|
# Example:
|
@@ -11,15 +11,42 @@ require_relative "hizuke/parser"
|
|
11
11
|
# result.text # => "wash car"
|
12
12
|
# result.date # => <Date: 2023-04-01>
|
13
13
|
module Hizuke
|
14
|
+
# Configuration class to hold Hizuke settings
|
15
|
+
class Configuration
|
16
|
+
attr_accessor :morning_time, :evening_time
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@morning_time = { hour: 8, min: 0 }
|
20
|
+
@evening_time = { hour: 20, min: 0 }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the current configuration
|
25
|
+
# @return [Hizuke::Configuration] the current configuration
|
26
|
+
def self.configuration
|
27
|
+
@configuration ||= Configuration.new
|
28
|
+
end
|
29
|
+
|
30
|
+
# Configure Hizuke settings
|
31
|
+
# @yield [config] Gives the configuration object to the block
|
32
|
+
# @return [Hizuke::Configuration] the updated configuration
|
33
|
+
def self.configure
|
34
|
+
yield(configuration)
|
35
|
+
configuration
|
36
|
+
end
|
37
|
+
|
14
38
|
# Parse text containing time references and extract both
|
15
39
|
# the clean text and the date.
|
16
40
|
#
|
17
41
|
# @param text [String] the text to parse
|
18
42
|
# @return [Hizuke::Result] the parsing result containing text and date
|
19
43
|
def self.parse(text)
|
44
|
+
raise ParseError, 'Cannot parse nil input' if text.nil?
|
45
|
+
raise ParseError, 'Cannot parse empty input' if text.empty?
|
46
|
+
|
20
47
|
Parser.parse(text)
|
21
48
|
end
|
22
49
|
|
23
50
|
# Error raised when parsing fails
|
24
51
|
class ParseError < StandardError; end
|
25
|
-
end
|
52
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hizuke
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juraj Maťaše
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -69,7 +69,10 @@ files:
|
|
69
69
|
- Rakefile
|
70
70
|
- hizuke.gemspec
|
71
71
|
- lib/hizuke.rb
|
72
|
+
- lib/hizuke/constants.rb
|
73
|
+
- lib/hizuke/date_calculator.rb
|
72
74
|
- lib/hizuke/parser.rb
|
75
|
+
- lib/hizuke/pattern_matcher.rb
|
73
76
|
- lib/hizuke/version.rb
|
74
77
|
homepage: https://github.com/majur/hizuke
|
75
78
|
licenses:
|