http://github.com/noctivityinc/tickle by Joshua Lippiner, Noctivity
– DESCRIPTION
Tickle is a natural language parser for recurring events.
Tickle is designed to be a compliment of Chronic and can interpret things such as “every 2 days, every Sunday, Sundays, Weekly, etc.”
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.
– INSTALLATION
Tickle can be installed via RubyGems:
$ gem install tickle
– TINKERING
Everything’s at Github - github.com/noctivityinc/tickle
– DEPENDENCIES
chronic gem (gem install chronic)
thoughtbot’s shoulda (gem install shoulda)
You can parse strings containing a natural language interval using the Tickle.parse method.
Tickle.parse returns the next occurrence of the event.
You can either pass a string prefixed with the word “every, each or ‘on the’” or simply the time frame. You can also pass a start date with the word “starting” (e.g. Tickle.parse(‘every 3 days starting next friday’))
Tickle returns nil if it cannot parse the string cannot be parsed.
Tickle HEAVILY uses chronic for parsing both the event and the start date.
– EXAMPLES
require 'rubygems' require 'tickle' Time.now 2010-04-24 12:05:51 -0400 Tickle.parse('each day') #=> 2010-04-24 12:05:51 -0400 Tickle.parse('every day') #=> 2010-04-24 12:05:51 -0400 Tickle.parse('every week') #=> 2010-05-01 12:05:51 -0400 Tickle.parse('every Month') #=> 2010-05-24 12:05:51 -0400 Tickle.parse('every year') #=> 2011-04-24 12:05:51 -0400 Tickle.parse('daily') #=> 2010-04-24 12:05:51 -0400 Tickle.parse('weekly') #=> 2010-05-01 12:05:51 -0400 Tickle.parse('monthly') #=> 2010-05-24 12:05:51 -0400 Tickle.parse('yearly') #=> 2011-04-24 12:05:51 -0400 Tickle.parse('every 3 days') #=> 2010-04-27 12:05:51 -0400 Tickle.parse('every 3 weeks') #=> 2010-05-15 12:05:51 -0400 Tickle.parse('every 3 months') #=> 2010-07-23 12:05:51 -0400 Tickle.parse('every 3 years') #=> 2013-04-23 12:05:51 -0400 Tickle.parse('every other day') #=> 2010-04-26 12:05:51 -0400 Tickle.parse('every other week') #=> 2010-05-08 12:05:51 -0400 Tickle.parse('every other month') #=> 2010-06-24 12:05:51 -0400 Tickle.parse('every other year') #=> 2012-04-24 12:05:51 -0400 Tickle.parse('every other day starting May 1st') #=> 2010-05-01 12:00:00 -0400 Tickle.parse('every other week starting this Sunday') #=> 2010-04-25 12:00:00 -0400 Tickle.parse('every Monday') #=> 2010-04-26 12:00:00 -0400 Tickle.parse('every Wednesday') #=> 2010-04-28 12:00:00 -0400 Tickle.parse('every Friday') #=> 2010-04-30 12:00:00 -0400 Tickle.parse('every May') #=> 2010-05-01 12:00:00 -0400 Tickle.parse('every june') #=> 2010-06-01 12:00:00 -0400 Tickle.parse('beginning of the week') #=> 2010-04-25 12:00:00 -0400 Tickle.parse('middle of the week') #=> 2010-04-28 12:00:00 -0400 Tickle.parse('end of the week') #=> 2010-05-01 12:00:00 -0400 Tickle.parse('beginning of the month') #=> 2010-05-01 12:00:00 -0400 Tickle.parse('middle of the month') #=> 2010-05-15 12:00:00 -0400 Tickle.parse('end of the month') #=> 2010-04-30 00:00:00 -0400 Tickle.parse('beginning of the year') #=> 2011-01-01 12:00:00 -0500 Tickle.parse('middle of the year') #=> 2010-06-15 00:00:00 -0400 Tickle.parse('end of the year') #=> 2010-12-31 00:00:00 -0500 Tickle.parse('the 3rd of May') #=> 2010-05-03 12:00:00 -0400 Tickle.parse('the 3rd of February') #=> 2011-02-03 12:00:00 -0500 Tickle.parse('the 10th of the month') #=> 2010-05-10 12:00:00 -0400 Tickle.parse('the tenth of the month') #=> 2010-05-10 12:00:00 -0400 Tickle.parse('the first of the month') #=> 2010-05-01 12:00:00 -0400 Tickle.parse('the thirtieth') #=> 2010-04-30 12:00:00 -0400 Tickle.parse('the fifth') #=> 2010-05-05 12:00:00 -0400 Tickle.parse('the 3rd Sunday of May') #=> 2010-05-16 12:00:00 -0400 Tickle.parse('the 3rd Sunday of the month') #=> 2010-05-16 12:00:00 -0400 Tickle.parse('the 23rd of June') #=> 2010-06-23 12:00:00 -0400 Tickle.parse('the twenty third of June') #=> 2010-06-23 12:00:00 -0400 Tickle.parse('the thirty first of August') #=> 2010-08-31 12:00:00 -0400 Tickle.parse('the twenty first') #=> 2010-05-21 12:00:00 -0400 Tickle.parse('the twenty first of the month') #=> 2010-05-21 12:00:00 -0400
– USING IN APP
To use in your app, we recommend adding two attributes to your database model:
-
next_occurrence
-
tickle_query
Then call Tickle.parse(query) when you need to and save the results accordingly. In your code, each day, simply check to see if today is >= next_occurrence and, if so, run your block.
After it completes, call Tickle.parse(tickle_query) again to update the next occurrence of the event.
– LIMITATIONS
Currently, Tickle only works for day intervals but feel free to fork and add time-based interval support or send me a note if you really want me to add it.
HUGE shout-out to both the creator of Chronic, Tom Preston-Werner (chronic.rubyforge.org/) as well as Brian Brownling who maintains a github version at github.com/mojombo/chronic.
Without their work and code structure I’d be lost.
-
Fork the project.
-
Make your feature addition or bug fix.
-
Add tests for it. This is important so I don’t break it in a future version unintentionally.
-
Commit, do not mess with rakefile, version, or history. (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)
-
Send me a pull request. Bonus points for topic branches.
Copyright © 2010 Joshua Lippiner. See LICENSE for details.