Hokkaido 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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