Ice cube

Ruby Date Recurrence Library

View the Project on GitHub seejohnrun/ice_cube

Get ice_cube

# install
$ gem install 
# get the code
$ gem clone git://github.com/seejohnrun/ice_cube

Complex Rules, Simple.

# The fridays in October that are on the 13th of the month
Rule.weekly.day(:friday).day_of_month(13).month_of_year(:october)

Persistence

ice_cube offers a hash-backed to_yaml implementation, making it super easy (and safe) to serialize schedule objects to your data store:

# YAML
yaml = schedule.to_yaml
schedule = Schedule.from_yaml(yaml)

# Hash
hash = schedule.to_hash
schedule = Schedule.from_hash(hash)

Using your words

# A complex rule
rule = Rule.daily.day_of_week(:monday => [1, -1]).month_of_year(:april)

rule.to_s # Daily in April on the last and 1st Mondays
rule.to_ical # FREQ=DAILY;BYMONTH=4;BYDAY=-1MO,1MO
rule.to_yaml # :rrules: \n- :until: \n :count: ...

Combining Rules

Multiple validations on the same rule, result in an AND (&&) relationship

# On Wednesdays THAT ARE ALSO in April
schedule.add_recurrence_rule Rule.weekly.day(:wednesday).month_of_year(:april)

Multiple rules in the same schedule, result in an OR (||) relationship

# On Thursdays and the 100th day of the year
schedule.add_recurrence_rule Rule.weekly.day(:thursday)
schedule.add_recurrence_rule Rule.day_of_year(100)

The full workflow, what's in a Schedule?

# Create a schedule for every day in May
schedule = Schedule.new(Time.now)
schedule.add_recurrence_rule Rule.daily.month_of_year(:may)

# Does it occur at a certain time?
schedule.occurs_at?(Time.local(2010, 11, 1)) # false

# Does it occur on a certain date?
schedule.occurs_on?(Date.today)

# All of the occurrences between two Times
schedule.occurrences_between(Time.local(2010, 1, 1), Time.local(2010, 12, 1))

# When are the first 10 occurrences
schedule.first(10) # [Thu May 13 18:01:46 -0400 2010, Fri May 13 ...]

# All of the occurrences between now and another Time
schedule.occurrences(Time.local(2010, 12, 1)) # [Thu May 13 18:01:46 -0400 2010]

# If your schedule has a duration, occurring_at? is important
ten = Time.new(2010, 5, 6, 10, 0, 0)
schedule = Schedule.new(ten, :duration => 3600)
schedule.add_recurrence_rule Rule.daily
schedule.occurring_at?(Time.local(2010, 5, 6, 10, 30, 0)) # true

# If your schedule needs a hard-set end time, that's easy too
schedule = Schedule.new(Time.now, :end_time => Time.now + 3600)
schedule.occurs_at?(Time.now + 3601) # false

Reference