In some projects it's imperative to enable users to set their own rules for repeated events. Sometimes the event rules can be pretty complex, for instance "each second to last day of month" or "the second Friday of each month until a certain date". In order to handle such tasks easily and efficiently, you can use ice_cube gem.

Gem ice_cube allows to specify multiple rules and dates for repeated events using its API similar to iCalendar, and serialize/deserialize schedules to/from YAML and Ruby Hash formats. The power of ice_cube lies in the ability to store only the schedule itself, as opposed to generating the repeated events in advance all at once. We chose ice_cube namely for its easy and flexible API, constant updates and troubleshooting, popularity among other developers.

Gem installation:

gem install ice_cube

In order to create a schedule you should use class IceCube::Schedule:

require 'rubygems'
require 'ice_cube'

include IceCube

# Parameters:
# - date/time of schedule beginning
# - {
#  :duration => 3600  - duration in seconds
#  :end_time => + 3600 - end time
# }
schedule =  

# Add recurrence
# Add exception
schedule.add_exception_time( + 1)

In order to add recurrence rules to a schedule you should use class IceCube::Rule. Ice_сube allows to create rules for daily, weekly, monthly, yearly, hourly, minutely and secondly recurrences. Several use cases are presented below (a more comprehensive list of examples can be found on the GitHub page of this project):

# Every fourth day
schedule.add_recurrence_rule Rule.daily(4)

# Every other week, on Mondays and Fridays
schedule.add_recurrence_rule Rule.weekly(2).day(:monday, :friday)

# Every month on the 10th, 20th and last day of the month
schedule.add_recurrence_rule Rule.monthly.day_of_month(10, 20, -1)

# Every month on the first Monday and last Tuesday
schedule.add_recurrence_rule Rule.monthly.day_of_week(
  :monday => [1],
  :tuesday => [-1]

# Every year on the 50th day and 100th day from the end of the year
schedule.add_recurrence_rule Rule.yearly.day_of_year(50, -100)  

It is possible to combine several rules in a schedule, including exception rules:

# Every fourth day except Mondays and Fridays
schedule.add_recurrence_rule Rule.daily(4)
schedule.add_exception_rule, 5)

Recurrence rules may optionally include restrictions by occurrence count or until a certain date:

# Every other day, 10 times
schedule.add_recurrence_rule Rule.daily(2).count(10)

# Every other day until the end of the month
schedule.add_recurrence_rule Rule.daily(2).until( -

And now probably the most interesting part - querying a schedule:

# All occurrences

# All occurrences until a certain time
schedule.occurrences(( + 5).to_time)

# Occurs at a certain time

# Occurs on a certain date

# Occurs during a certain time-frame
schedule.occurs_between?(, ( + 5).to_time)

# First occurrences

# Next occurrence
# Next 3 occurrences
# Remaining occurrences

Data serialization to YAML/HASH/iCal:

yaml = schedule.to_yaml

# Hash
hash = schedule.to_hash

# iCalendar

We use ice_cube gem to implement repeated events calendar in combination with FullCalendar and DelayedJob, a live example can be found on this page.

Some examples incorporated in this article have been taken from official project documentation. If you have any questions or remarks, please address them in the Comments section below. We will do our best to answer them all.


Tags dev, ruby, ice_cube
Published at December 01, 2012 22:00
Updated at December 09, 2012 12:58

comments powered by Disqus