Hokkaido 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/Gemfile +2 -0
  2. data/Gemfile.lock +2 -2
  3. data/ansiterm-color/.gitignore +3 -0
  4. data/ansiterm-color/CHANGES +28 -0
  5. data/ansiterm-color/COPYING +340 -0
  6. data/ansiterm-color/README +137 -0
  7. data/ansiterm-color/Rakefile +88 -0
  8. data/ansiterm-color/VERSION +1 -0
  9. data/ansiterm-color/bin/cdiff +19 -0
  10. data/ansiterm-color/bin/decolor +12 -0
  11. data/ansiterm-color/doc-main.txt +119 -0
  12. data/ansiterm-color/examples/example.rb +90 -0
  13. data/ansiterm-color/install.rb +15 -0
  14. data/ansiterm-color/lib/term/ansicolor/.keep +0 -0
  15. data/ansiterm-color/lib/term/ansicolor/version.rb +10 -0
  16. data/ansiterm-color/lib/term/ansicolor.rb +102 -0
  17. data/ansiterm-color/make_doc.rb +4 -0
  18. data/ansiterm-color/tests/ansicolor_test.rb +66 -0
  19. data/chronic/.gitignore +6 -0
  20. data/chronic/HISTORY.md +205 -0
  21. data/chronic/LICENSE +21 -0
  22. data/chronic/README.md +181 -0
  23. data/chronic/Rakefile +46 -0
  24. data/chronic/chronic.gemspec +20 -0
  25. data/chronic/lib/chronic/grabber.rb +33 -0
  26. data/chronic/lib/chronic/handler.rb +88 -0
  27. data/chronic/lib/chronic/handlers.rb +572 -0
  28. data/chronic/lib/chronic/mini_date.rb +38 -0
  29. data/chronic/lib/chronic/numerizer.rb +121 -0
  30. data/chronic/lib/chronic/ordinal.rb +47 -0
  31. data/chronic/lib/chronic/pointer.rb +32 -0
  32. data/chronic/lib/chronic/repeater.rb +145 -0
  33. data/chronic/lib/chronic/repeaters/repeater_day.rb +53 -0
  34. data/chronic/lib/chronic/repeaters/repeater_day_name.rb +52 -0
  35. data/chronic/lib/chronic/repeaters/repeater_day_portion.rb +108 -0
  36. data/chronic/lib/chronic/repeaters/repeater_fortnight.rb +71 -0
  37. data/chronic/lib/chronic/repeaters/repeater_hour.rb +58 -0
  38. data/chronic/lib/chronic/repeaters/repeater_minute.rb +58 -0
  39. data/chronic/lib/chronic/repeaters/repeater_month.rb +79 -0
  40. data/chronic/lib/chronic/repeaters/repeater_month_name.rb +94 -0
  41. data/chronic/lib/chronic/repeaters/repeater_season.rb +109 -0
  42. data/chronic/lib/chronic/repeaters/repeater_season_name.rb +43 -0
  43. data/chronic/lib/chronic/repeaters/repeater_second.rb +42 -0
  44. data/chronic/lib/chronic/repeaters/repeater_time.rb +128 -0
  45. data/chronic/lib/chronic/repeaters/repeater_week.rb +74 -0
  46. data/chronic/lib/chronic/repeaters/repeater_weekday.rb +85 -0
  47. data/chronic/lib/chronic/repeaters/repeater_weekend.rb +66 -0
  48. data/chronic/lib/chronic/repeaters/repeater_year.rb +77 -0
  49. data/chronic/lib/chronic/scalar.rb +116 -0
  50. data/chronic/lib/chronic/season.rb +26 -0
  51. data/chronic/lib/chronic/separator.rb +94 -0
  52. data/chronic/lib/chronic/span.rb +31 -0
  53. data/chronic/lib/chronic/tag.rb +36 -0
  54. data/chronic/lib/chronic/time_zone.rb +32 -0
  55. data/chronic/lib/chronic/token.rb +47 -0
  56. data/chronic/lib/chronic.rb +442 -0
  57. data/chronic/test/helper.rb +12 -0
  58. data/chronic/test/test_chronic.rb +150 -0
  59. data/chronic/test/test_daylight_savings.rb +118 -0
  60. data/chronic/test/test_handler.rb +104 -0
  61. data/chronic/test/test_mini_date.rb +32 -0
  62. data/chronic/test/test_numerizer.rb +72 -0
  63. data/chronic/test/test_parsing.rb +1061 -0
  64. data/chronic/test/test_repeater_day_name.rb +51 -0
  65. data/chronic/test/test_repeater_day_portion.rb +254 -0
  66. data/chronic/test/test_repeater_fortnight.rb +62 -0
  67. data/chronic/test/test_repeater_hour.rb +68 -0
  68. data/chronic/test/test_repeater_minute.rb +34 -0
  69. data/chronic/test/test_repeater_month.rb +50 -0
  70. data/chronic/test/test_repeater_month_name.rb +56 -0
  71. data/chronic/test/test_repeater_season.rb +40 -0
  72. data/chronic/test/test_repeater_time.rb +70 -0
  73. data/chronic/test/test_repeater_week.rb +62 -0
  74. data/chronic/test/test_repeater_weekday.rb +55 -0
  75. data/chronic/test/test_repeater_weekend.rb +74 -0
  76. data/chronic/test/test_repeater_year.rb +69 -0
  77. data/chronic/test/test_span.rb +23 -0
  78. data/chronic/test/test_token.rb +25 -0
  79. data/lib/Hokkaido/version.rb +1 -1
  80. data/lib/Hokkaido.rb +13 -9
  81. data/lib/gem_modifier.rb +23 -3
  82. data/lib/term/ansicolor.rb +4 -1
  83. data/spec/Hokkaido/port_spec.rb +15 -7
  84. metadata +78 -2
@@ -0,0 +1,572 @@
1
+ module Chronic
2
+ module Handlers
3
+ module_function
4
+
5
+ # Handle month/day
6
+ def handle_m_d(month, day, time_tokens, options)
7
+ month.start = Chronic.now
8
+ span = month.this(options[:context])
9
+ year, month = span.begin.year, span.begin.month
10
+ day_start = Chronic.time_class.local(year, month, day)
11
+
12
+ day_or_time(day_start, time_tokens, options)
13
+ end
14
+
15
+ # Handle repeater-month-name/scalar-day
16
+ def handle_rmn_sd(tokens, options)
17
+ month = tokens[0].get_tag(RepeaterMonthName)
18
+ day = tokens[1].get_tag(ScalarDay).type
19
+
20
+ return if month_overflow?(Chronic.now.year, month.index, day)
21
+
22
+ handle_m_d(month, day, tokens[2..tokens.size], options)
23
+ end
24
+
25
+ # Handle repeater-month-name/scalar-day with separator-on
26
+ def handle_rmn_sd_on(tokens, options)
27
+ if tokens.size > 3
28
+ month = tokens[2].get_tag(RepeaterMonthName)
29
+ day = tokens[3].get_tag(ScalarDay).type
30
+ token_range = 0..1
31
+ else
32
+ month = tokens[1].get_tag(RepeaterMonthName)
33
+ day = tokens[2].get_tag(ScalarDay).type
34
+ token_range = 0..0
35
+ end
36
+
37
+ return if month_overflow?(Chronic.now.year, month.index, day)
38
+
39
+ handle_m_d(month, day, tokens[token_range], options)
40
+ end
41
+
42
+ # Handle repeater-month-name/ordinal-day
43
+ def handle_rmn_od(tokens, options)
44
+ month = tokens[0].get_tag(RepeaterMonthName)
45
+ day = tokens[1].get_tag(OrdinalDay).type
46
+
47
+ return if month_overflow?(Chronic.now.year, month.index, day)
48
+
49
+ handle_m_d(month, day, tokens[2..tokens.size], options)
50
+ end
51
+
52
+ # Handle ordinal this month
53
+ def handle_od_rm(tokens, options)
54
+ day = tokens[0].get_tag(OrdinalDay).type
55
+ month = tokens[2].get_tag(RepeaterMonth)
56
+ handle_m_d(month, day, tokens[3..tokens.size], options)
57
+ end
58
+
59
+ # Handle ordinal-day/repeater-month-name
60
+ def handle_od_rmn(tokens, options)
61
+ month = tokens[1].get_tag(RepeaterMonthName)
62
+ day = tokens[0].get_tag(OrdinalDay).type
63
+
64
+ return if month_overflow?(Chronic.now.year, month.index, day)
65
+
66
+ handle_m_d(month, day, tokens[2..tokens.size], options)
67
+ end
68
+
69
+ def handle_sy_rmn_od(tokens, options)
70
+ year = tokens[0].get_tag(ScalarYear).type
71
+ month = tokens[1].get_tag(RepeaterMonthName).index
72
+ day = tokens[2].get_tag(OrdinalDay).type
73
+ time_tokens = tokens.last(tokens.size - 3)
74
+
75
+ return if month_overflow?(year, month, day)
76
+
77
+ begin
78
+ day_start = Chronic.time_class.local(year, month, day)
79
+ day_or_time(day_start, time_tokens, options)
80
+ rescue ArgumentError
81
+ nil
82
+ end
83
+ end
84
+
85
+ # Handle scalar-day/repeater-month-name
86
+ def handle_sd_rmn(tokens, options)
87
+ month = tokens[1].get_tag(RepeaterMonthName)
88
+ day = tokens[0].get_tag(ScalarDay).type
89
+
90
+ return if month_overflow?(Chronic.now.year, month.index, day)
91
+
92
+ handle_m_d(month, day, tokens[2..tokens.size], options)
93
+ end
94
+
95
+ # Handle repeater-month-name/ordinal-day with separator-on
96
+ def handle_rmn_od_on(tokens, options)
97
+ if tokens.size > 3
98
+ month = tokens[2].get_tag(RepeaterMonthName)
99
+ day = tokens[3].get_tag(OrdinalDay).type
100
+ token_range = 0..1
101
+ else
102
+ month = tokens[1].get_tag(RepeaterMonthName)
103
+ day = tokens[2].get_tag(OrdinalDay).type
104
+ token_range = 0..0
105
+ end
106
+
107
+ return if month_overflow?(Chronic.now.year, month.index, day)
108
+
109
+ handle_m_d(month, day, tokens[token_range], options)
110
+ end
111
+
112
+ # Handle repeater-month-name/scalar-year
113
+ def handle_rmn_sy(tokens, options)
114
+ month = tokens[0].get_tag(RepeaterMonthName).index
115
+ year = tokens[1].get_tag(ScalarYear).type
116
+
117
+ if month == 12
118
+ next_month_year = year + 1
119
+ next_month_month = 1
120
+ else
121
+ next_month_year = year
122
+ next_month_month = month + 1
123
+ end
124
+
125
+ begin
126
+ end_time = Chronic.time_class.local(next_month_year, next_month_month)
127
+ Span.new(Chronic.time_class.local(year, month), end_time)
128
+ rescue ArgumentError
129
+ nil
130
+ end
131
+ end
132
+
133
+ # Handle generic timestamp (ruby 1.8)
134
+ def handle_generic(tokens, options)
135
+ t = Chronic.time_class.parse(options[:text])
136
+ Span.new(t, t + 1)
137
+ end
138
+
139
+ # Handle repeater-month-name/scalar-day/scalar-year
140
+ def handle_rmn_sd_sy(tokens, options)
141
+ month = tokens[0].get_tag(RepeaterMonthName).index
142
+ day = tokens[1].get_tag(ScalarDay).type
143
+ year = tokens[2].get_tag(ScalarYear).type
144
+ time_tokens = tokens.last(tokens.size - 3)
145
+
146
+ return if month_overflow?(year, month, day)
147
+
148
+ begin
149
+ day_start = Chronic.time_class.local(year, month, day)
150
+ day_or_time(day_start, time_tokens, options)
151
+ rescue ArgumentError
152
+ nil
153
+ end
154
+ end
155
+
156
+ # Handle repeater-month-name/ordinal-day/scalar-year
157
+ def handle_rmn_od_sy(tokens, options)
158
+ month = tokens[0].get_tag(RepeaterMonthName).index
159
+ day = tokens[1].get_tag(OrdinalDay).type
160
+ year = tokens[2].get_tag(ScalarYear).type
161
+ time_tokens = tokens.last(tokens.size - 3)
162
+
163
+ return if month_overflow?(year, month, day)
164
+
165
+ begin
166
+ day_start = Chronic.time_class.local(year, month, day)
167
+ day_or_time(day_start, time_tokens, options)
168
+ rescue ArgumentError
169
+ nil
170
+ end
171
+ end
172
+
173
+ # Handle oridinal-day/repeater-month-name/scalar-year
174
+ def handle_od_rmn_sy(tokens, options)
175
+ day = tokens[0].get_tag(OrdinalDay).type
176
+ month = tokens[1].get_tag(RepeaterMonthName).index
177
+ year = tokens[2].get_tag(ScalarYear).type
178
+ time_tokens = tokens.last(tokens.size - 3)
179
+
180
+ return if month_overflow?(year, month, day)
181
+
182
+ begin
183
+ day_start = Chronic.time_class.local(year, month, day)
184
+ day_or_time(day_start, time_tokens, options)
185
+ rescue ArgumentError
186
+ nil
187
+ end
188
+ end
189
+
190
+ # Handle scalar-day/repeater-month-name/scalar-year
191
+ def handle_sd_rmn_sy(tokens, options)
192
+ new_tokens = [tokens[1], tokens[0], tokens[2]]
193
+ time_tokens = tokens.last(tokens.size - 3)
194
+ handle_rmn_sd_sy(new_tokens + time_tokens, options)
195
+ end
196
+
197
+ # Handle scalar-month/scalar-day/scalar-year (endian middle)
198
+ def handle_sm_sd_sy(tokens, options)
199
+ month = tokens[0].get_tag(ScalarMonth).type
200
+ day = tokens[1].get_tag(ScalarDay).type
201
+ year = tokens[2].get_tag(ScalarYear).type
202
+ time_tokens = tokens.last(tokens.size - 3)
203
+
204
+ return if month_overflow?(year, month, day)
205
+
206
+ begin
207
+ day_start = Chronic.time_class.local(year, month, day)
208
+ day_or_time(day_start, time_tokens, options)
209
+ rescue ArgumentError
210
+ nil
211
+ end
212
+ end
213
+
214
+ # Handle scalar-day/scalar-month/scalar-year (endian little)
215
+ def handle_sd_sm_sy(tokens, options)
216
+ new_tokens = [tokens[1], tokens[0], tokens[2]]
217
+ time_tokens = tokens.last(tokens.size - 3)
218
+ handle_sm_sd_sy(new_tokens + time_tokens, options)
219
+ end
220
+
221
+ # Handle scalar-year/scalar-month/scalar-day
222
+ def handle_sy_sm_sd(tokens, options)
223
+ new_tokens = [tokens[1], tokens[2], tokens[0]]
224
+ time_tokens = tokens.last(tokens.size - 3)
225
+ handle_sm_sd_sy(new_tokens + time_tokens, options)
226
+ end
227
+
228
+ # Handle scalar-month/scalar-day
229
+ def handle_sm_sd(tokens, options)
230
+ month = tokens[0].get_tag(ScalarMonth).type
231
+ day = tokens[1].get_tag(ScalarDay).type
232
+ year = Chronic.now.year
233
+ time_tokens = tokens.last(tokens.size - 2)
234
+
235
+ return if month_overflow?(year, month, day)
236
+
237
+ begin
238
+ day_start = Chronic.time_class.local(year, month, day)
239
+ day_or_time(day_start, time_tokens, options)
240
+ rescue ArgumentError
241
+ nil
242
+ end
243
+ end
244
+
245
+ # Handle scalar-day/scalar-month
246
+ def handle_sd_sm(tokens, options)
247
+ new_tokens = [tokens[1], tokens[0]]
248
+ time_tokens = tokens.last(tokens.size - 2)
249
+ handle_sm_sd(new_tokens + time_tokens, options)
250
+ end
251
+
252
+ # Handle scalar-month/scalar-year
253
+ def handle_sm_sy(tokens, options)
254
+ month = tokens[0].get_tag(ScalarMonth).type
255
+ year = tokens[1].get_tag(ScalarYear).type
256
+
257
+ if month == 12
258
+ next_month_year = year + 1
259
+ next_month_month = 1
260
+ else
261
+ next_month_year = year
262
+ next_month_month = month + 1
263
+ end
264
+
265
+ begin
266
+ end_time = Chronic.time_class.local(next_month_year, next_month_month)
267
+ Span.new(Chronic.time_class.local(year, month), end_time)
268
+ rescue ArgumentError
269
+ nil
270
+ end
271
+ end
272
+
273
+ # Handle RepeaterDayName RepeaterMonthName OrdinalDay
274
+ def handle_rdn_rmn_od(tokens, options)
275
+ month = tokens[1].get_tag(RepeaterMonthName)
276
+ day = tokens[2].get_tag(OrdinalDay).type
277
+ year = Chronic.now.year
278
+
279
+ return if month_overflow?(year, month.index, day)
280
+
281
+ begin
282
+ start_time = Chronic.time_class.local(year, month.index, day)
283
+ end_time = time_with_rollover(year, month.index, day + 1)
284
+ Span.new(start_time, end_time)
285
+ rescue ArgumentError
286
+ nil
287
+ end
288
+ end
289
+
290
+ # Handle RepeaterDayName RepeaterMonthName ScalarDay
291
+ def handle_rdn_rmn_sd(tokens, options)
292
+ month = tokens[1].get_tag(RepeaterMonthName)
293
+ day = tokens[2].get_tag(ScalarDay).type
294
+ year = Chronic.now.year
295
+
296
+ return if month_overflow?(year, month.index, day)
297
+
298
+ begin
299
+ start_time = Chronic.time_class.local(year, month.index, day)
300
+ end_time = time_with_rollover(year, month.index, day + 1)
301
+ Span.new(start_time, end_time)
302
+ rescue ArgumentError
303
+ nil
304
+ end
305
+ end
306
+
307
+ # Handle RepeaterDayName RepeaterMonthName ScalarDay ScalarYear
308
+ def handle_rdn_rmn_sd_sy(tokens, options)
309
+ month = tokens[1].get_tag(RepeaterMonthName)
310
+ day = tokens[2].get_tag(ScalarDay).type
311
+ year = tokens[3].get_tag(ScalarYear).type
312
+
313
+ return if month_overflow?(year, month.index, day)
314
+
315
+ begin
316
+ start_time = Chronic.time_class.local(year, month.index, day)
317
+ end_time = time_with_rollover(year, month.index, day + 1)
318
+ Span.new(start_time, end_time)
319
+ rescue ArgumentError
320
+ nil
321
+ end
322
+ end
323
+
324
+ def handle_sm_rmn_sy(tokens, options)
325
+ day = tokens[0].get_tag(ScalarDay).type
326
+ month = tokens[1].get_tag(RepeaterMonthName).index
327
+ year = tokens[2].get_tag(ScalarYear).type
328
+ if tokens.size > 3
329
+ time = get_anchor([tokens.last], options).begin
330
+ h, m, s = time.hour, time.min, time.sec
331
+ time = Chronic.time_class.local(year, month, day, h, m, s)
332
+ end_time = Chronic.time_class.local(year, month, day + 1, h, m, s)
333
+ else
334
+ time = Chronic.time_class.local(year, month, day)
335
+ end_time = Chronic.time_class.local(year, month, day + 1)
336
+ end
337
+ Span.new(time, end_time)
338
+ end
339
+
340
+ # anchors
341
+
342
+ # Handle repeaters
343
+ def handle_r(tokens, options)
344
+ dd_tokens = dealias_and_disambiguate_times(tokens, options)
345
+ get_anchor(dd_tokens, options)
346
+ end
347
+
348
+ # Handle repeater/grabber/repeater
349
+ def handle_r_g_r(tokens, options)
350
+ new_tokens = [tokens[1], tokens[0], tokens[2]]
351
+ handle_r(new_tokens, options)
352
+ end
353
+
354
+ # arrows
355
+
356
+ # Handle scalar/repeater/pointer helper
357
+ def handle_srp(tokens, span, options)
358
+ distance = tokens[0].get_tag(Scalar).type
359
+ repeater = tokens[1].get_tag(Repeater)
360
+ pointer = tokens[2].get_tag(Pointer).type
361
+
362
+ repeater.offset(span, distance, pointer) if repeater.respond_to?(:offset)
363
+ end
364
+
365
+ # Handle scalar/repeater/pointer
366
+ def handle_s_r_p(tokens, options)
367
+ repeater = tokens[1].get_tag(Repeater)
368
+ span = Span.new(Chronic.now, Chronic.now + 1)
369
+
370
+ handle_srp(tokens, span, options)
371
+ end
372
+
373
+ # Handle pointer/scalar/repeater
374
+ def handle_p_s_r(tokens, options)
375
+ new_tokens = [tokens[1], tokens[2], tokens[0]]
376
+ handle_s_r_p(new_tokens, options)
377
+ end
378
+
379
+ # Handle scalar/repeater/pointer/anchor
380
+ def handle_s_r_p_a(tokens, options)
381
+ anchor_span = get_anchor(tokens[3..tokens.size - 1], options)
382
+ handle_srp(tokens, anchor_span, options)
383
+ end
384
+
385
+ # narrows
386
+
387
+ # Handle oridinal repeaters
388
+ def handle_orr(tokens, outer_span, options)
389
+ repeater = tokens[1].get_tag(Repeater)
390
+ repeater.start = outer_span.begin - 1
391
+ ordinal = tokens[0].get_tag(Ordinal).type
392
+ span = nil
393
+
394
+ ordinal.times do
395
+ span = repeater.next(:future)
396
+
397
+ if span.begin >= outer_span.end
398
+ span = nil
399
+ break
400
+ end
401
+ end
402
+
403
+ span
404
+ end
405
+
406
+ # Handle ordinal/repeater/separator/repeater
407
+ def handle_o_r_s_r(tokens, options)
408
+ outer_span = get_anchor([tokens[3]], options)
409
+ handle_orr(tokens[0..1], outer_span, options)
410
+ end
411
+
412
+ # Handle ordinal/repeater/grabber/repeater
413
+ def handle_o_r_g_r(tokens, options)
414
+ outer_span = get_anchor(tokens[2..3], options)
415
+ handle_orr(tokens[0..1], outer_span, options)
416
+ end
417
+
418
+ # support methods
419
+
420
+ def day_or_time(day_start, time_tokens, options)
421
+ outer_span = Span.new(day_start, day_start + (24 * 60 * 60))
422
+
423
+ if !time_tokens.empty?
424
+ Chronic.now = outer_span.begin
425
+ get_anchor(dealias_and_disambiguate_times(time_tokens, options), options)
426
+ else
427
+ outer_span
428
+ end
429
+ end
430
+
431
+ def get_anchor(tokens, options)
432
+ grabber = Grabber.new(:this)
433
+ pointer = :future
434
+ repeaters = get_repeaters(tokens)
435
+ repeaters.size.times { tokens.pop }
436
+
437
+ if tokens.first && tokens.first.get_tag(Grabber)
438
+ grabber = tokens.shift.get_tag(Grabber)
439
+ end
440
+
441
+ head = repeaters.shift
442
+ head.start = Chronic.now
443
+
444
+ case grabber.type
445
+ when :last
446
+ outer_span = head.next(:past)
447
+ when :this
448
+ if options[:context] != :past and repeaters.size > 0
449
+ outer_span = head.this(:none)
450
+ else
451
+ outer_span = head.this(options[:context])
452
+ end
453
+ when :next
454
+ outer_span = head.next(:future)
455
+ else
456
+ raise ChronicPain, "Invalid grabber"
457
+ end
458
+
459
+ if Chronic.debug
460
+ puts "Handler-class: #{head.class}"
461
+ puts "--#{outer_span}"
462
+ end
463
+
464
+ find_within(repeaters, outer_span, pointer)
465
+ end
466
+
467
+ def get_repeaters(tokens)
468
+ tokens.map { |token| token.get_tag(Repeater) }.compact.sort.reverse
469
+ end
470
+
471
+ def month_overflow?(year, month, day)
472
+ if Date.leap?(year)
473
+ day > RepeaterMonth::MONTH_DAYS_LEAP[month - 1]
474
+ else
475
+ day > RepeaterMonth::MONTH_DAYS[month - 1]
476
+ end
477
+ rescue ArgumentError
478
+ false
479
+ end
480
+
481
+ # Recursively finds repeaters within other repeaters.
482
+ # Returns a Span representing the innermost time span
483
+ # or nil if no repeater union could be found
484
+ def find_within(tags, span, pointer)
485
+ puts "--#{span}" if Chronic.debug
486
+ return span if tags.empty?
487
+
488
+ head = tags.shift
489
+ head.start = (pointer == :future ? span.begin : span.end)
490
+ h = head.this(:none)
491
+
492
+ if span.cover?(h.begin) || span.cover?(h.end)
493
+ find_within(tags, h, pointer)
494
+ end
495
+ end
496
+
497
+ def time_with_rollover(year, month, day)
498
+ date_parts =
499
+ if month_overflow?(year, month, day)
500
+ if month == 12
501
+ [year + 1, 1, 1]
502
+ else
503
+ [year, month + 1, 1]
504
+ end
505
+ else
506
+ [year, month, day]
507
+ end
508
+ Chronic.time_class.local(*date_parts)
509
+ end
510
+
511
+ def dealias_and_disambiguate_times(tokens, options)
512
+ # handle aliases of am/pm
513
+ # 5:00 in the morning -> 5:00 am
514
+ # 7:00 in the evening -> 7:00 pm
515
+
516
+ day_portion_index = nil
517
+ tokens.each_with_index do |t, i|
518
+ if t.get_tag(RepeaterDayPortion)
519
+ day_portion_index = i
520
+ break
521
+ end
522
+ end
523
+
524
+ time_index = nil
525
+ tokens.each_with_index do |t, i|
526
+ if t.get_tag(RepeaterTime)
527
+ time_index = i
528
+ break
529
+ end
530
+ end
531
+
532
+ if day_portion_index && time_index
533
+ t1 = tokens[day_portion_index]
534
+ t1tag = t1.get_tag(RepeaterDayPortion)
535
+
536
+ case t1tag.type
537
+ when :morning
538
+ puts '--morning->am' if Chronic.debug
539
+ t1.untag(RepeaterDayPortion)
540
+ t1.tag(RepeaterDayPortion.new(:am))
541
+ when :afternoon, :evening, :night
542
+ puts "--#{t1tag.type}->pm" if Chronic.debug
543
+ t1.untag(RepeaterDayPortion)
544
+ t1.tag(RepeaterDayPortion.new(:pm))
545
+ end
546
+ end
547
+
548
+ # handle ambiguous times if :ambiguous_time_range is specified
549
+ if options[:ambiguous_time_range] != :none
550
+ ambiguous_tokens = []
551
+
552
+ tokens.each_with_index do |token, i|
553
+ ambiguous_tokens << token
554
+ next_token = tokens[i + 1]
555
+
556
+ if token.get_tag(RepeaterTime) && token.get_tag(RepeaterTime).type.ambiguous? && (!next_token || !next_token.get_tag(RepeaterDayPortion))
557
+ distoken = Token.new('disambiguator')
558
+
559
+ distoken.tag(RepeaterDayPortion.new(options[:ambiguous_time_range]))
560
+ ambiguous_tokens << distoken
561
+ end
562
+ end
563
+
564
+ tokens = ambiguous_tokens
565
+ end
566
+
567
+ tokens
568
+ end
569
+
570
+ end
571
+
572
+ end
@@ -0,0 +1,38 @@
1
+ module Chronic
2
+ class MiniDate
3
+ attr_accessor :month, :day
4
+
5
+ def self.from_time(time)
6
+ new(time.month, time.day)
7
+ end
8
+
9
+ def initialize(month, day)
10
+ unless (1..12).include?(month)
11
+ raise ArgumentError, "1..12 are valid months"
12
+ end
13
+
14
+ @month = month
15
+ @day = day
16
+ end
17
+
18
+ def is_between?(md_start, md_end)
19
+ return false if (@month == md_start.month && @month == md_end.month) &&
20
+ (@day < md_start.day || @day > md_end.day)
21
+ return true if (@month == md_start.month && @day >= md_start.day) ||
22
+ (@month == md_end.month && @day <= md_end.day)
23
+
24
+ i = (md_start.month % 12) + 1
25
+
26
+ until i == md_end.month
27
+ return true if @month == i
28
+ i = (i % 12) + 1
29
+ end
30
+
31
+ return false
32
+ end
33
+
34
+ def equals?(other)
35
+ @month == other.month and @day == other.day
36
+ end
37
+ end
38
+ end