tickle 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -12,6 +12,8 @@ Tickle is a natural language parser for recurring events.
12
12
 
13
13
  Tickle is designed to be a compliment of Chronic and can interpret things such as "every 2 days, every Sunday, Sundays, Weekly, etc."
14
14
 
15
+ In a lot of ways Tickle is actually an enhancement of Chronic, handling a lot of things that Chronic can't, such as commas and US Holidays (yup - you can do Tickle.parse('Christmas Eve'))
16
+
15
17
  Tickle has one main method, "Tickle.parse," which returns the next time the event should occur, at which point you simply call Tickle.parse again.
16
18
 
17
19
  == INSTALLATION
@@ -37,10 +39,10 @@ You can parse strings containing a natural language interval using the Tickle.pa
37
39
  You can either pass a string prefixed with the word "every, each or 'on the'" or simply the time frame.
38
40
 
39
41
  Tickle.parse returns a hash containing the following keys:
40
- * next = the next occurrence of the event. This is NEVER today as its always the next date in the future.
41
- * starting = the date all calculations as based on. If not passed as an option, the start date is right now.
42
- * until = the last date you want this event to run until.
43
- * expression = this is the natural language expression to store to run through tickle later to get the next occurrence.
42
+ * next = the next occurrence of the event. This is NEVER today as its always the next date in the future.
43
+ * starting = the date all calculations as based on. If not passed as an option, the start date is right now.
44
+ * until = the last date you want this event to run until.
45
+ * expression = this is the natural language expression to store to run through tickle later to get the next occurrence.
44
46
 
45
47
  Tickle returns nil if it cannot parse the string cannot be parsed.
46
48
 
@@ -51,15 +53,15 @@ Tickle HEAVILY uses chronic for parsing but mostly the start and until phrases.
51
53
  There are two ways to pass options: natural language or an options hash.
52
54
 
53
55
  NATURAL LANGUAGE:
54
- * Pass a start date with the word "starting, start, stars" (e.g. Tickle.parse('every 3 days starting next friday'))
55
- * Pass an end date with the word "until, end, ends, ending" (e.g. Tickle.parse('every 3 days until next friday'))
56
- * Pass both at the same time (e.g. "starting May 5th repeat every other week until December 1")
56
+ * Pass a start date with the word "starting, start, stars" (e.g. Tickle.parse('every 3 days starting next friday'))
57
+ * Pass an end date with the word "until, end, ends, ending" (e.g. Tickle.parse('every 3 days until next friday'))
58
+ * Pass both at the same time (e.g. "starting May 5th repeat every other week until December 1")
57
59
 
58
60
  OPTIONS HASH
59
61
  Valid options are:
60
- * start - must be a valid date or Chronic date expression. (e.g. Tickle.parse('every other day', {:start => Date.new(2010,8,1) }))
61
- * until - must be a valid date or Chronic date expression. (e.g. Tickle.parse('every other day', {:until => Date.new(2010,10,1) }))
62
- * next_only - legacy switch to ONLY return the next occurrence as a date and not return a hash
62
+ * start - must be a valid date or Chronic date expression. (e.g. Tickle.parse('every other day', {:start => Date.new(2010,8,1) }))
63
+ * until - must be a valid date or Chronic date expression. (e.g. Tickle.parse('every other day', {:until => Date.new(2010,10,1) }))
64
+ * next_only - legacy switch to ONLY return the next occurrence as a date and not return a hash
63
65
 
64
66
  === SUPER IMPORTANT NOTE ABOUT NEXT OCCURRENCE & START DATE
65
67
 
@@ -306,6 +308,87 @@ OPTIONS HASH
306
308
  Tickle.parse('3 months', {:until=>2010-10-09 00:00:00 -0400})
307
309
  #=> {:next=>2010-08-09 20:57:36 -0400, :expression=>"3 months", :starting=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400}
308
310
 
311
+ US HOLIDAYS
312
+
313
+ Tickle.parse('New Years Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
314
+ #=> {:next=>2021-01-01 12:00:00 -0500, :expression=>"january 1, 2021", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
315
+
316
+ Tickle.parse('Inauguration', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
317
+ #=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"january 20", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
318
+
319
+ Tickle.parse('Martin Luther King Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
320
+ #=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"third monday in january", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
321
+
322
+ Tickle.parse('MLK', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
323
+ #=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"third monday in january", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
324
+
325
+ Tickle.parse('Presidents Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
326
+ #=> {:next=>2020-02-17 12:00:00 -0500, :expression=>"third monday in february", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
327
+
328
+ Tickle.parse('Memorial Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
329
+ #=> {:next=>2020-05-25 12:00:00 -0400, :expression=>"4th monday of may", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
330
+
331
+ Tickle.parse('Independence Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
332
+ #=> {:next=>2020-07-04 12:00:00 -0400, :expression=>"july 4, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
333
+
334
+ Tickle.parse('Labor Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
335
+ #=> {:next=>2020-09-07 12:00:00 -0400, :expression=>"first monday in september", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
336
+
337
+ Tickle.parse('Columbus Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
338
+ #=> {:next=>2020-10-12 12:00:00 -0400, :expression=>"second monday in october", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
339
+
340
+ Tickle.parse('Veterans Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
341
+ #=> {:next=>2020-11-11 12:00:00 -0500, :expression=>"november 11, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
342
+
343
+ Tickle.parse('Christmas', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
344
+ #=> {:next=>2020-12-25 12:00:00 -0500, :expression=>"december 25, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
345
+
346
+ Tickle.parse('Super Bowl Sunday', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
347
+ #=> {:next=>2020-02-02 12:00:00 -0500, :expression=>"first sunday in february", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
348
+
349
+ Tickle.parse('Groundhog Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
350
+ #=> {:next=>2020-02-02 12:00:00 -0500, :expression=>"february 2, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
351
+
352
+ Tickle.parse('Valentines Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
353
+ #=> {:next=>2020-02-14 12:00:00 -0500, :expression=>"february 14, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
354
+
355
+ Tickle.parse('Saint Patricks day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
356
+ #=> {:next=>2020-03-17 12:00:00 -0400, :expression=>"march 17, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
357
+
358
+ Tickle.parse('April Fools Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
359
+ #=> {:next=>2020-04-01 12:00:00 -0400, :expression=>"april 1, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
360
+
361
+ Tickle.parse('Earth Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
362
+ #=> {:next=>2020-04-22 12:00:00 -0400, :expression=>"april 22, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
363
+
364
+ Tickle.parse('Arbor Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
365
+ #=> {:next=>2020-04-24 12:00:00 -0400, :expression=>"fourth friday in april", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
366
+
367
+ Tickle.parse('Cinco De Mayo', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
368
+ #=> {:next=>2020-05-05 12:00:00 -0400, :expression=>"may 5, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
369
+
370
+ Tickle.parse('Mothers Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
371
+ #=> {:next=>2020-05-10 12:00:00 -0400, :expression=>"second sunday in may", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
372
+
373
+ Tickle.parse('Flag Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
374
+ #=> {:next=>2020-06-14 12:00:00 -0400, :expression=>"june 14, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
375
+
376
+ Tickle.parse('Fathers Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
377
+ #=> {:next=>2020-06-21 12:00:00 -0400, :expression=>"third sunday in june", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
378
+
379
+ Tickle.parse('Halloween', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
380
+ #=> {:next=>2020-10-31 12:00:00 -0400, :expression=>"october 31, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
381
+
382
+ Tickle.parse('Christmas Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
383
+ #=> {:next=>2020-12-25 12:00:00 -0500, :expression=>"december 25, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
384
+
385
+ Tickle.parse('Christmas Eve', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
386
+ #=> {:next=>2020-12-24 12:00:00 -0500, :expression=>"december 24, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
387
+
388
+ Tickle.parse('Kwanzaa', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
389
+ #=> {:next=>2021-01-01 12:00:00 -0500, :expression=>"january 1, 2021", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
390
+
391
+
309
392
  == USING IN APP
310
393
 
311
394
  To use in your app, we recommend adding two attributes to your database model:
@@ -340,14 +423,13 @@ As always, BIG shout-out to the RVM Master himself, Wayne Seguin, for putting up
340
423
 
341
424
 
342
425
  == Note on Patches/Pull Requests
343
-
344
- * Fork the project.
345
- * Make your feature addition or bug fix.
346
- * Add tests for it. This is important so I don't break it in a
347
- future version unintentionally.
348
- * Commit, do not mess with rakefile, version, or history.
349
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
350
- * Send me a pull request. Bonus points for time-based branches.
426
+ * Fork the project.
427
+ * Make your feature addition or bug fix.
428
+ * Add tests for it. This is important so I don't break it in a
429
+ future version unintentionally.
430
+ * Commit, do not mess with rakefile, version, or history.
431
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
432
+ * Send me a pull request. Bonus points for time-based branches.
351
433
 
352
434
  == Copyright
353
435
 
data/SCENARIOS.rdoc CHANGED
@@ -1,15 +1,317 @@
1
- every 2 weeks => word 'week' found plus a number so the interval = number * 7 and start_date = today
2
- every second tuesday => => day of week found WITH number (ordinal converted to 2). interval = 30 with start_date = Chronic.parse(Ordinal Number Day Of Week 'in' Start Date Month)
3
- every sunday => day of week found without number. interval = 7, start_date = next day of week occurrence
4
- every other day => word 'day' found with word 'other.' interval = 2, start_date = today
5
- every fourth thursday => day of week found WITH number (ordinal converted to 4). interval = 30 with start_date = next occurrence of 'event' as parsed by chronic
6
- on the 15th of each month => 'each month' becomes interval = 30, number found + start month through chronic equals start date
7
- on the 15th of November => month found with number. interval = 365, start_date = Chronic.parse(month + number)
8
- on the second monday in April => month, day and number found. interval = 365, start_date = Chronic.parse(ordinal number form of number, day of week, month)
9
- every November 15th => month found with number. interval = 365, start_date = Chronic.parse(month + number)
10
- every day => word 'day' found without a number. interval = 1. start_day = today
11
- every week => word 'week' found without a number. interval = 7. start_day = today
12
- every month => word 'month' found without a number. interval = 30. start_day = today
1
+ === EXAMPLES
13
2
 
3
+ require 'rubygems'
4
+ require 'tickle'
14
5
 
6
+ SIMPLE
7
+ Tickle.parse('day')
8
+ #=> {:next=>2010-05-10 20:57:36 -0400, :expression=>"day", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
9
+
10
+ Tickle.parse('day')
11
+ #=> {:next=>2010-05-10 20:57:36 -0400, :expression=>"day", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
12
+
13
+ Tickle.parse('week')
14
+ #=> {:next=>2010-05-16 20:57:36 -0400, :expression=>"week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
15
+
16
+ Tickle.parse('month')
17
+ #=> {:next=>2010-06-09 20:57:36 -0400, :expression=>"month", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
18
+
19
+ Tickle.parse('year')
20
+ #=> {:next=>2011-05-09 20:57:36 -0400, :expression=>"year", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
21
+
22
+ Tickle.parse('daily')
23
+ #=> {:next=>2010-05-10 20:57:36 -0400, :expression=>"daily", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
24
+
25
+ Tickle.parse('weekly')
26
+ #=> {:next=>2010-05-16 20:57:36 -0400, :expression=>"weekly", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
27
+
28
+ Tickle.parse('monthly')
29
+ #=> {:next=>2010-06-09 20:57:36 -0400, :expression=>"monthly", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
30
+
31
+ Tickle.parse('yearly')
32
+ #=> {:next=>2011-05-09 20:57:36 -0400, :expression=>"yearly", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
33
+
34
+ Tickle.parse('3 days')
35
+ #=> {:next=>2010-05-12 20:57:36 -0400, :expression=>"3 days", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
36
+
37
+ Tickle.parse('3 weeks')
38
+ #=> {:next=>2010-05-30 20:57:36 -0400, :expression=>"3 weeks", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
39
+
40
+ Tickle.parse('3 months')
41
+ #=> {:next=>2010-08-09 20:57:36 -0400, :expression=>"3 months", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
42
+
43
+ Tickle.parse('3 years')
44
+ #=> {:next=>2013-05-09 20:57:36 -0400, :expression=>"3 years", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
45
+
46
+ Tickle.parse('other day')
47
+ #=> {:next=>2010-05-11 20:57:36 -0400, :expression=>"other day", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
48
+
49
+ Tickle.parse('other week')
50
+ #=> {:next=>2010-05-23 20:57:36 -0400, :expression=>"other week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
51
+
52
+ Tickle.parse('other month')
53
+ #=> {:next=>2010-07-09 20:57:36 -0400, :expression=>"other month", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
54
+
55
+ Tickle.parse('other year')
56
+ #=> {:next=>2012-05-09 20:57:36 -0400, :expression=>"other year", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
57
+
58
+ Tickle.parse('Monday')
59
+ #=> {:next=>2010-05-10 12:00:00 -0400, :expression=>"monday", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
60
+
61
+ Tickle.parse('Wednesday')
62
+ #=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"wednesday", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
63
+
64
+ Tickle.parse('Friday')
65
+ #=> {:next=>2010-05-14 12:00:00 -0400, :expression=>"friday", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
66
+
67
+ Tickle.parse('February', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
68
+ #=> {:next=>2021-02-01 12:00:00 -0500, :expression=>"february", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
69
+
70
+ Tickle.parse('May', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
71
+ #=> {:next=>2020-05-01 12:00:00 -0400, :expression=>"may", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
72
+
73
+ Tickle.parse('june', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
74
+ #=> {:next=>2020-06-01 12:00:00 -0400, :expression=>"june", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
75
+
76
+ Tickle.parse('beginning of the week')
77
+ #=> {:next=>2010-05-16 12:00:00 -0400, :expression=>"beginning of the week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
78
+
79
+ Tickle.parse('middle of the week')
80
+ #=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"middle of the week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
81
+
82
+ Tickle.parse('end of the week')
83
+ #=> {:next=>2010-05-15 12:00:00 -0400, :expression=>"end of the week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
84
+
85
+ Tickle.parse('beginning of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
86
+ #=> {:next=>2020-05-01 00:00:00 -0400, :expression=>"beginning of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
87
+
88
+ Tickle.parse('middle of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
89
+ #=> {:next=>2020-04-15 00:00:00 -0400, :expression=>"middle of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
90
+
91
+ Tickle.parse('end of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
92
+ #=> {:next=>2020-04-30 00:00:00 -0400, :expression=>"end of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
93
+
94
+ Tickle.parse('beginning of the year', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
95
+ #=> {:next=>2021-01-01 00:00:00 -0500, :expression=>"beginning of the year", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
96
+
97
+ Tickle.parse('middle of the year', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
98
+ #=> {:next=>2020-06-15 00:00:00 -0400, :expression=>"middle of the year", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
99
+
100
+ Tickle.parse('end of the year', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
101
+ #=> {:next=>2020-12-31 00:00:00 -0500, :expression=>"end of the year", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
102
+
103
+ Tickle.parse('the 3rd of May', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
104
+ #=> {:next=>2020-05-03 00:00:00 -0400, :expression=>"the 3rd of may", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
105
+
106
+ Tickle.parse('the 3rd of February', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
107
+ #=> {:next=>2021-02-03 00:00:00 -0500, :expression=>"the 3rd of february", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
108
+
109
+ Tickle.parse('the 3rd of February 2022', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
110
+ #=> {:next=>2022-02-03 00:00:00 -0500, :expression=>"the 3rd of february 2022", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
111
+
112
+ Tickle.parse('the 3rd of Feb 2022', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
113
+ #=> {:next=>2022-02-03 00:00:00 -0500, :expression=>"the 3rd of feb 2022", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
114
+
115
+ Tickle.parse('the 4th of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
116
+ #=> {:next=>2020-04-04 00:00:00 -0400, :expression=>"the 4th of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
117
+
118
+ Tickle.parse('the 10th of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
119
+ #=> {:next=>2020-04-10 00:00:00 -0400, :expression=>"the 10th of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
120
+
121
+ Tickle.parse('the tenth of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
122
+ #=> {:next=>2020-04-10 00:00:00 -0400, :expression=>"the tenth of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
123
+
124
+ Tickle.parse('first', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
125
+ #=> {:next=>2020-05-01 00:00:00 -0400, :expression=>"first", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
126
+
127
+ Tickle.parse('the first of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
128
+ #=> {:next=>2020-05-01 00:00:00 -0400, :expression=>"the first of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
129
+
130
+ Tickle.parse('the thirtieth', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
131
+ #=> {:next=>2020-04-30 00:00:00 -0400, :expression=>"the thirtieth", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
132
+
133
+ Tickle.parse('the fifth', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
134
+ #=> {:next=>2020-04-05 00:00:00 -0400, :expression=>"the fifth", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
135
+
136
+ Tickle.parse('the 1st Wednesday of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
137
+ #=> {:next=>2020-05-01 00:00:00 -0400, :expression=>"the 1st wednesday of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
138
+
139
+ Tickle.parse('the 3rd Sunday of May', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
140
+ #=> {:next=>2020-05-17 12:00:00 -0400, :expression=>"the 3rd sunday of may", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
141
+
142
+ Tickle.parse('the 3rd Sunday of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
143
+ #=> {:next=>2020-04-19 12:00:00 -0400, :expression=>"the 3rd sunday of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
144
+
145
+ Tickle.parse('the 23rd of June', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
146
+ #=> {:next=>2020-06-23 00:00:00 -0400, :expression=>"the 23rd of june", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
147
+
148
+ Tickle.parse('the twenty third of June', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
149
+ #=> {:next=>2020-06-23 00:00:00 -0400, :expression=>"the twenty third of june", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
150
+
151
+ Tickle.parse('the thirty first of July', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
152
+ #=> {:next=>2020-07-31 00:00:00 -0400, :expression=>"the thirty first of july", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
153
+
154
+ Tickle.parse('the twenty first', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
155
+ #=> {:next=>2020-04-21 00:00:00 -0400, :expression=>"the twenty first", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
156
+
157
+ Tickle.parse('the twenty first of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
158
+ #=> {:next=>2020-04-21 00:00:00 -0400, :expression=>"the twenty first of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
159
+
160
+ COMPLEX
161
+ Tickle.parse('starting today and ending one week from now')
162
+ #=> {:next=>2010-05-10 22:30:00 -0400, :expression=>"day", :starting=>2010-05-09 22:30:00 -0400, :until=>2010-05-16 20:57:35 -0400}
163
+
164
+ Tickle.parse('starting tomorrow and ending one week from now')
165
+ #=> {:next=>2010-05-10 12:00:00 -0400, :expression=>"day", :starting=>2010-05-10 12:00:00 -0400, :until=>2010-05-16 20:57:35 -0400}
166
+
167
+ Tickle.parse('starting Monday repeat every month')
168
+ #=> {:next=>2010-05-10 12:00:00 -0400, :expression=>"month", :starting=>2010-05-10 12:00:00 -0400, :until=>nil}
169
+
170
+ Tickle.parse('starting May 13th repeat every week')
171
+ #=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"week", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
172
+
173
+ Tickle.parse('starting May 13th repeat every other day')
174
+ #=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
175
+
176
+ Tickle.parse('every other day starts May 13th')
177
+ #=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
178
+
179
+ Tickle.parse('every other day starts May 13')
180
+ #=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
181
+
182
+ Tickle.parse('every other day starting May 13th')
183
+ #=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
184
+
185
+ Tickle.parse('every other day starting May 13')
186
+ #=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
187
+
188
+ Tickle.parse('every week starts this wednesday')
189
+ #=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>nil}
190
+
191
+ Tickle.parse('every week starting this wednesday')
192
+ #=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>nil}
193
+
194
+ Tickle.parse('every other day starting May 1st 2021')
195
+ #=> {:next=>2021-05-01 12:00:00 -0400, :expression=>"other day", :starting=>2021-05-01 12:00:00 -0400, :until=>nil}
196
+
197
+ Tickle.parse('every other day starting May 1 2021')
198
+ #=> {:next=>2021-05-01 12:00:00 -0400, :expression=>"other day", :starting=>2021-05-01 12:00:00 -0400, :until=>nil}
199
+
200
+ Tickle.parse('every other week starting this Sunday')
201
+ #=> {:next=>2010-05-16 12:00:00 -0400, :expression=>"other week", :starting=>2010-05-16 12:00:00 -0400, :until=>nil}
202
+
203
+ Tickle.parse('every week starting this wednesday until May 13th')
204
+ #=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>2010-05-13 12:00:00 -0400}
205
+
206
+ Tickle.parse('every week starting this wednesday ends May 13th')
207
+ #=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>2010-05-13 12:00:00 -0400}
208
+
209
+ Tickle.parse('every week starting this wednesday ending May 13th')
210
+ #=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>2010-05-13 12:00:00 -0400}
211
+
212
+
213
+ OPTIONS HASH
214
+ Tickle.parse('May 1st 2020', {:next_only=>true})
215
+ #=> 2020-05-01 00:00:00 -0400
216
+
217
+ Tickle.parse('3 days', {:start=>2010-05-09 20:57:36 -0400})
218
+ #=> {:next=>2010-05-12 20:57:36 -0400, :expression=>"3 days", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
219
+
220
+ Tickle.parse('3 weeks', {:start=>2010-05-09 20:57:36 -0400})
221
+ #=> {:next=>2010-05-30 20:57:36 -0400, :expression=>"3 weeks", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
222
+
223
+ Tickle.parse('3 months', {:start=>2010-05-09 20:57:36 -0400})
224
+ #=> {:next=>2010-08-09 20:57:36 -0400, :expression=>"3 months", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
225
+
226
+ Tickle.parse('3 years', {:start=>2010-05-09 20:57:36 -0400})
227
+ #=> {:next=>2013-05-09 20:57:36 -0400, :expression=>"3 years", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
228
+
229
+ Tickle.parse('3 days', {:start=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400})
230
+ #=> {:next=>2010-05-12 20:57:36 -0400, :expression=>"3 days", :starting=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400}
231
+
232
+ Tickle.parse('3 weeks', {:start=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400})
233
+ #=> {:next=>2010-05-30 20:57:36 -0400, :expression=>"3 weeks", :starting=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400}
234
+
235
+ Tickle.parse('3 months', {:until=>2010-10-09 00:00:00 -0400})
236
+ #=> {:next=>2010-08-09 20:57:36 -0400, :expression=>"3 months", :starting=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400}
237
+
238
+ US HOLIDAYS
239
+
240
+ Tickle.parse('New Years Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
241
+ #=> {:next=>2021-01-01 12:00:00 -0500, :expression=>"january 1, 2021", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
242
+
243
+ Tickle.parse('Inauguration', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
244
+ #=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"january 20", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
245
+
246
+ Tickle.parse('Martin Luther King Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
247
+ #=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"third monday in january", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
248
+
249
+ Tickle.parse('MLK', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
250
+ #=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"third monday in january", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
251
+
252
+ Tickle.parse('Presidents Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
253
+ #=> {:next=>2020-02-17 12:00:00 -0500, :expression=>"third monday in february", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
254
+
255
+ Tickle.parse('Memorial Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
256
+ #=> {:next=>2020-05-25 12:00:00 -0400, :expression=>"4th monday of may", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
257
+
258
+ Tickle.parse('Independence Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
259
+ #=> {:next=>2020-07-04 12:00:00 -0400, :expression=>"july 4, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
260
+
261
+ Tickle.parse('Labor Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
262
+ #=> {:next=>2020-09-07 12:00:00 -0400, :expression=>"first monday in september", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
263
+
264
+ Tickle.parse('Columbus Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
265
+ #=> {:next=>2020-10-12 12:00:00 -0400, :expression=>"second monday in october", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
266
+
267
+ Tickle.parse('Veterans Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
268
+ #=> {:next=>2020-11-11 12:00:00 -0500, :expression=>"november 11, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
269
+
270
+ Tickle.parse('Christmas', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
271
+ #=> {:next=>2020-12-25 12:00:00 -0500, :expression=>"december 25, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
272
+
273
+ Tickle.parse('Super Bowl Sunday', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
274
+ #=> {:next=>2020-02-02 12:00:00 -0500, :expression=>"first sunday in february", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
275
+
276
+ Tickle.parse('Groundhog Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
277
+ #=> {:next=>2020-02-02 12:00:00 -0500, :expression=>"february 2, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
278
+
279
+ Tickle.parse('Valentines Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
280
+ #=> {:next=>2020-02-14 12:00:00 -0500, :expression=>"february 14, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
281
+
282
+ Tickle.parse('Saint Patricks day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
283
+ #=> {:next=>2020-03-17 12:00:00 -0400, :expression=>"march 17, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
284
+
285
+ Tickle.parse('April Fools Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
286
+ #=> {:next=>2020-04-01 12:00:00 -0400, :expression=>"april 1, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
287
+
288
+ Tickle.parse('Earth Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
289
+ #=> {:next=>2020-04-22 12:00:00 -0400, :expression=>"april 22, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
290
+
291
+ Tickle.parse('Arbor Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
292
+ #=> {:next=>2020-04-24 12:00:00 -0400, :expression=>"fourth friday in april", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
293
+
294
+ Tickle.parse('Cinco De Mayo', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
295
+ #=> {:next=>2020-05-05 12:00:00 -0400, :expression=>"may 5, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
296
+
297
+ Tickle.parse('Mothers Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
298
+ #=> {:next=>2020-05-10 12:00:00 -0400, :expression=>"second sunday in may", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
299
+
300
+ Tickle.parse('Flag Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
301
+ #=> {:next=>2020-06-14 12:00:00 -0400, :expression=>"june 14, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
302
+
303
+ Tickle.parse('Fathers Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
304
+ #=> {:next=>2020-06-21 12:00:00 -0400, :expression=>"third sunday in june", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
305
+
306
+ Tickle.parse('Halloween', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
307
+ #=> {:next=>2020-10-31 12:00:00 -0400, :expression=>"october 31, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
308
+
309
+ Tickle.parse('Christmas Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
310
+ #=> {:next=>2020-12-25 12:00:00 -0500, :expression=>"december 25, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
311
+
312
+ Tickle.parse('Christmas Eve', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
313
+ #=> {:next=>2020-12-24 12:00:00 -0500, :expression=>"december 24, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
314
+
315
+ Tickle.parse('Kwanzaa', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
316
+ #=> {:next=>2021-01-01 12:00:00 -0500, :expression=>"january 1, 2021", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
15
317
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.6
1
+ 0.1.7
data/git-flow-version CHANGED
@@ -1 +1 @@
1
- GITFLOW_VERSION=0.1.6
1
+ GITFLOW_VERSION=0.1.7
@@ -43,6 +43,8 @@ module Tickle #:nodoc:
43
43
  @next = @start.bump(:week, token_of_type(:number).interval) if token_types.same?([:number, :week])
44
44
  @next = @start.bump(:month, token_of_type(:number).interval) if token_types.same?([:number, :month])
45
45
  @next = @start.bump(:year, token_of_type(:number).interval) if token_types.same?([:number, :year])
46
+ @next = chronic_parse_with_start("#{token_of_type(:month_name).word} #{token_of_type(:number).start}") if token_types.same?([:number, :month_name])
47
+ @next = chronic_parse_with_start("#{token_of_type(:specific_year).word}-#{token_of_type(:month_name).start}-#{token_of_type(:number).start}") if token_types.same?([:number, :month_name, :specific_year])
46
48
  end
47
49
 
48
50
  def guess_ordinal
data/lib/tickle/tickle.rb CHANGED
@@ -52,7 +52,7 @@ module Tickle #:nodoc:
52
52
 
53
53
  # check to see if this event starts some other time and reset now
54
54
  event = scan_expression(text, options)
55
-
55
+
56
56
  Tickle.dwrite("start: #{@start}, until: #{@until}, now: #{options[:now].to_date}")
57
57
 
58
58
  # => ** this is mostly for testing. Bump by 1 day if today (or in the past for testing)
@@ -173,6 +173,7 @@ module Tickle #:nodoc:
173
173
  text.gsub!(/on the(\s)?/, '')
174
174
  text.gsub!(/([^\w\d\s])+/, '')
175
175
  text.downcase.strip
176
+ text = normalize_us_holidays(text)
176
177
  end
177
178
 
178
179
  # Split the text on spaces and convert each word into
@@ -197,21 +198,40 @@ module Tickle #:nodoc:
197
198
  normalized_text = Numerizer.numerize(normalized_text)
198
199
  normalized_text.gsub!(/['"\.]/, '')
199
200
  normalized_text.gsub!(/([\/\-\,\@])/) { ' ' + $1 + ' ' }
200
- # normalized_text.gsub!(/\btoday\b/, 'this day')
201
- # normalized_text.gsub!(/\btomm?orr?ow\b/, 'next day')
202
- # normalized_text.gsub!(/\byesterday\b/, 'last day')
203
- # normalized_text.gsub!(/\bnoon\b/, '12:00')
204
- # normalized_text.gsub!(/\bmidnight\b/, '24:00')
205
- # normalized_text.gsub!(/\bbefore now\b/, 'past')
206
- # normalized_text.gsub!(/\bnow\b/, 'this second')
207
- # normalized_text.gsub!(/\b(ago|before)\b/, 'past')
208
- # normalized_text.gsub!(/\bthis past\b/, 'last')
209
- # normalized_text.gsub!(/\bthis last\b/, 'last')
210
- # normalized_text.gsub!(/\b(?:in|during) the (morning)\b/, '\1')
211
- # normalized_text.gsub!(/\b(?:in the|during the|at) (afternoon|evening|night)\b/, '\1')
212
- # normalized_text.gsub!(/\btonight\b/, 'this night')
213
- # normalized_text.gsub!(/(?=\w)([ap]m|oclock)\b/, ' \1')
214
- # normalized_text.gsub!(/\b(hence|after|from)\b/, 'future')
201
+ normalized_text
202
+ end
203
+
204
+ # Converts natural language US Holidays into a date expression to be
205
+ # parsed.
206
+ def normalize_us_holidays(text) #:nodoc:
207
+ normalized_text = text.to_s.downcase
208
+ normalized_text.gsub!(/\bnew\syear'?s?(\s)?(day)?\b/, "january 1, #{next_appropriate_year(1, 1)}")
209
+ normalized_text.gsub!(/\bnew\syear'?s?(\s)?(eve)?\b/, "december 31, #{next_appropriate_year(12, 31)}")
210
+ normalized_text.gsub!(/\bm(artin\s)?l(uther\s)?k(ing)?(\sday)?\b/, 'third monday in january')
211
+ normalized_text.gsub!(/\binauguration(\sday)?\b/, 'january 20')
212
+ normalized_text.gsub!(/\bpresident'?s?(\sday)?\b/, 'third monday in february')
213
+ normalized_text.gsub!(/\bmemorial\sday\b/, '4th monday of may')
214
+ normalized_text.gsub!(/\bindepend(e|a)nce\sday\b/, "july 4, #{next_appropriate_year(7, 4)}")
215
+ normalized_text.gsub!(/\blabor\sday\b/, 'first monday in september')
216
+ normalized_text.gsub!(/\bcolumbus\sday\b/, 'second monday in october')
217
+ normalized_text.gsub!(/\bveterans?\sday\b/, "november 11, #{next_appropriate_year(11, 1)}")
218
+ normalized_text.gsub!(/\bthanksgiving(\sday)?\b/, 'fourth thursday in november')
219
+ normalized_text.gsub!(/\bchristmas\seve\b/, "december 24, #{next_appropriate_year(12, 24)}")
220
+ normalized_text.gsub!(/\bchristmas(\sday)?\b/, "december 25, #{next_appropriate_year(12, 25)}")
221
+ normalized_text.gsub!(/\bsuper\sbowl(\ssunday)?\b/, 'first sunday in february')
222
+ normalized_text.gsub!(/\bgroundhog(\sday)?\b/, "february 2, #{next_appropriate_year(2, 2)}")
223
+ normalized_text.gsub!(/\bvalentine'?s?(\sday)?\b/, "february 14, #{next_appropriate_year(2, 14)}")
224
+ normalized_text.gsub!(/\bs(ain)?t\spatrick'?s?(\sday)?\b/, "march 17, #{next_appropriate_year(3, 17)}")
225
+ normalized_text.gsub!(/\bapril\sfool'?s?(\sday)?\b/, "april 1, #{next_appropriate_year(4, 1)}")
226
+ normalized_text.gsub!(/\bearth\sday\b/, "april 22, #{next_appropriate_year(4, 22)}")
227
+ normalized_text.gsub!(/\barbor\sday\b/, 'fourth friday in april')
228
+ normalized_text.gsub!(/\bcinco\sde\smayo\b/, "may 5, #{next_appropriate_year(5, 5)}")
229
+ normalized_text.gsub!(/\bmother'?s?\sday\b/, 'second sunday in may')
230
+ normalized_text.gsub!(/\bflag\sday\b/, "june 14, #{next_appropriate_year(6, 14)}")
231
+ normalized_text.gsub!(/\bfather'?s?\sday\b/, 'third sunday in june')
232
+ normalized_text.gsub!(/\bhalloween\b/, "october 31, #{next_appropriate_year(10, 31)}")
233
+ normalized_text.gsub!(/\belection\sday\b/, 'second tuesday in november')
234
+ normalized_text.gsub!(/\bkwanzaa\b/, "january 1, #{next_appropriate_year(1, 1)}")
215
235
  normalized_text
216
236
  end
217
237
 
@@ -243,6 +263,11 @@ module Tickle #:nodoc:
243
263
  month = number.to_i < @start.day ? (@start.month == 12 ? 1 : @start.month + 1) : @start.month
244
264
  end
245
265
 
266
+ def next_appropriate_year(month, day)
267
+ year = (Date.new(@start.year.to_i, month.to_i, day.to_i) == @start.to_date) ? @start.year + 1 : @start.year
268
+ return year
269
+ end
270
+
246
271
  # Return the number of days in a specified month.
247
272
  # If no month is specified, current month is used.
248
273
  def days_in_month(month=nil)
data/lib/tickle.rb CHANGED
@@ -18,7 +18,7 @@ require 'tickle/handler'
18
18
  require 'tickle/repeater'
19
19
 
20
20
  module Tickle #:nodoc:
21
- VERSION = "0.1.5"
21
+ VERSION = "0.1.7"
22
22
 
23
23
  def self.debug=(val); @debug = val; end
24
24
 
data/test/test_parsing.rb CHANGED
@@ -92,7 +92,7 @@ class TestParsing < Test::Unit::TestCase
92
92
  assert_tickle_match(@date.bump(:day, 1), @date.bump(:day, 1), @date.bump(:week, 1), 'day','starting tomorrow and ending one week from now') # => demonstrates leaving out the actual time period and implying it as daily.
93
93
 
94
94
  assert_tickle_match(@date.bump(:wday, 'Mon'), @date.bump(:wday, 'Mon'), nil, 'month', 'starting Monday repeat every month')
95
-
95
+
96
96
  year = @date >= Date.new(@date.year, 5, 13) ? @date.bump(:year,1) : @date.year
97
97
  assert_tickle_match(Date.new(year, 05, 13), Date.new(year, 05, 13), nil, 'week', 'starting May 13th repeat every week')
98
98
  assert_tickle_match(Date.new(year, 05, 13), Date.new(year, 05, 13), nil, 'other day', 'starting May 13th repeat every other day')
@@ -111,7 +111,6 @@ class TestParsing < Test::Unit::TestCase
111
111
  assert_tickle_match(@date.bump(:wday, 'Wed'), @date.bump(:wday, 'Wed'), Date.new(year, 05, 13), 'week', 'every week starting this wednesday until May 13th')
112
112
  assert_tickle_match(@date.bump(:wday, 'Wed'), @date.bump(:wday, 'Wed'), Date.new(year, 05, 13), 'week', 'every week starting this wednesday ends May 13th')
113
113
  assert_tickle_match(@date.bump(:wday, 'Wed'), @date.bump(:wday, 'Wed'), Date.new(year, 05, 13), 'week', 'every week starting this wednesday ending May 13th')
114
-
115
114
  end
116
115
 
117
116
  def test_tickle_args
@@ -130,6 +129,40 @@ class TestParsing < Test::Unit::TestCase
130
129
  assert_tickle_match(start_date.bump(:month, 3), @date, start_date.bump(:month, 5), '3 months', 'every 3 months', {:until => end_date})
131
130
  end
132
131
 
132
+ def test_us_holidays
133
+ start = Date.new(2020, 01, 01)
134
+ assert_date_match(Date.new(2021, 1, 1), 'New Years Day', {:start => start, :now => start})
135
+ assert_date_match(Date.new(2020, 1, 20), 'Inauguration', {:start => start, :now => start})
136
+ assert_date_match(Date.new(2020, 1, 20), 'Martin Luther King Day', {:start => start, :now => start})
137
+ assert_date_match(Date.new(2020, 1, 20), 'MLK', {:start => start, :now => start})
138
+ assert_date_match(Date.new(2020, 2, 17), 'Presidents Day', {:start => start, :now => start})
139
+ assert_date_match(Date.new(2020, 5, 25), 'Memorial Day', {:start => start, :now => start})
140
+ assert_date_match(Date.new(2020, 7, 4), 'Independence Day', {:start => start, :now => start})
141
+ assert_date_match(Date.new(2020, 9, 7), 'Labor Day', {:start => start, :now => start})
142
+ assert_date_match(Date.new(2020, 10, 12), 'Columbus Day', {:start => start, :now => start})
143
+ assert_date_match(Date.new(2020, 11, 11), 'Veterans Day', {:start => start, :now => start})
144
+ # assert_date_match(Date.new(2020, 11, 26), 'Thanksgiving', {:start => start, :now => start}) # Chronic returning incorrect date. Routine is correct
145
+ assert_date_match(Date.new(2020, 12, 25), 'Christmas', {:start => start, :now => start})
146
+
147
+ assert_date_match(Date.new(2020, 2, 2), 'Super Bowl Sunday', {:start => start, :now => start})
148
+ assert_date_match(Date.new(2020, 2, 2), 'Groundhog Day', {:start => start, :now => start})
149
+ assert_date_match(Date.new(2020, 2, 14), "Valentine's Day", {:start => start, :now => start})
150
+ assert_date_match(Date.new(2020, 3, 17), "Saint Patrick's day", {:start => start, :now => start})
151
+ assert_date_match(Date.new(2020, 4, 1), "April Fools Day", {:start => start, :now => start})
152
+ assert_date_match(Date.new(2020, 4, 22), "Earth Day", {:start => start, :now => start})
153
+ assert_date_match(Date.new(2020, 4, 24), "Arbor Day", {:start => start, :now => start})
154
+ assert_date_match(Date.new(2020, 5, 5), "Cinco De Mayo", {:start => start, :now => start})
155
+ assert_date_match(Date.new(2020, 5, 10), "Mother's Day", {:start => start, :now => start})
156
+ assert_date_match(Date.new(2020, 6, 14), "Flag Day", {:start => start, :now => start})
157
+ assert_date_match(Date.new(2020, 6, 21), "Fathers Day", {:start => start, :now => start})
158
+ assert_date_match(Date.new(2020, 10, 31), "Halloween", {:start => start, :now => start})
159
+ # assert_date_match(Date.new(2020, 11, 10), "Election Day", {:start => start, :now => start}) # Damn Chronic again. Expression is correct
160
+ assert_date_match(Date.new(2020, 12, 25), 'Christmas Day', {:start => start, :now => start})
161
+ assert_date_match(Date.new(2020, 12, 24), 'Christmas Eve', {:start => start, :now => start})
162
+ assert_date_match(Date.new(2021, 1, 1), 'Kwanzaa', {:start => start, :now => start})
163
+
164
+ end
165
+
133
166
  def test_argument_validation
134
167
  assert_raise(Tickle::InvalidArgumentException) do
135
168
  time = Tickle.parse("may 27", :today => 'something odd')
@@ -179,7 +212,7 @@ class TestParsing < Test::Unit::TestCase
179
212
  actual_until = result[:until].to_date rescue nil
180
213
  expected_until = expected_until.to_date rescue nil
181
214
  actual_expression = result[:expression]
182
-
215
+
183
216
  assert (expected_next.to_date == actual_next.to_date), "\"#{date_expression}\" :next parses to #{actual_next} but should be equal to #{expected_next}"
184
217
  assert (expected_start.to_date == actual_start.to_date), "\"#{date_expression}\" :starting parses to #{actual_start} but should be equal to #{expected_start}"
185
218
  assert (expected_until == actual_until), "\"#{date_expression}\" :until parses to #{actual_until} but should be equal to #{expected_until}"
data/tickle.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tickle}
8
- s.version = "0.1.6"
8
+ s.version = "0.1.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Joshua Lippiner"]
12
- s.date = %q{2010-05-09}
12
+ s.date = %q{2010-05-10}
13
13
  s.description = %q{Tickle is a date/time helper gem to help parse natural language into a recurring pattern. Tickle is designed to be a compliment of Chronic and can interpret things such as "every 2 days, every Sunday, Sundays, Weekly, etc.}
14
14
  s.email = %q{jlippiner@noctivity.com}
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 6
9
- version: 0.1.6
8
+ - 7
9
+ version: 0.1.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - Joshua Lippiner
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-09 00:00:00 -04:00
17
+ date: 2010-05-10 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency