Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
# This service read and write simplified rrule format into ice_cube.
#
# Simplified RRule (order is important)
#
# FREQ: D(daily), W(weekly), M(monthly), Y(yearly)
# COUNT: #x where x is number
# INTERVAL: +x where x is interval
# BY use dot (.)
# BYDAY: .SU, .MO, .TU, .WE, .TH, .FR, .SA, .1FR, .-1FR, .20MO
# BYMONTHDAY: .D1-31 (+/-)
# BYMONTH: .M1-12 (+/-)
# BYYEARDAY: .Y1, Y100, Y200
# BYWEEKNO: .W20 (week number)
# UNTIL: <YYYYMMDD
#
# Week starts at 0 (Sunday), month and year at 1.
#
require 'ice_cube'
module RuleService
class Rule
RULE_REGEX = /([DMWY]+)([+#\d]*)([\.\w-]*)(<\d*|)/
BYDAY_REGEX = /(-?\d*)(SU|MO|TU|WE|TH|FR|SA)/
BYMONTHDAY_REGEX = /(-?D\d+)/
BYMONTH_REGEX = /(-?M\d+)/
BYYEARDAY_REGEX = /(-?Y\d+)/
BYWEEKNO_REGEX = /(-?W\d+)/
RULE_HASH = {'D' => '::DailyRule', 'M' => '::MonthlyRule', 'Y' => '::YearlyRule', 'W' => '::WeeklyRule'}
BYDAY_HASH = {'SU' => 0, 'MO' => 1, 'TU' => 2, 'WE' => 3, 'TH' => 4, 'FR' => 5, 'SA' => 6}
attr_accessor :rule
def initialize(rule=nil)
@rule = rule.strip if rule.nil? == false
end
def read_rule(rule)
@rule = rule
end
# Write back to simplified rule
def to_s
self.rule
end
def to_rrule
self.to_ice_cube_rule.to_ical
end
def to_ice_cube_rule
matches = RULE_REGEX.match(@rule)
rule_hash = {}
if (m = /\+(\d*)/.match(matches[2])) && (interval = m[1].to_i) && (interval > 0)
rule_hash[:interval] = interval
end
if (m = /#(\d*)/.match(matches[2])) && (count = m[1].to_i) && (count > 0)
rule_hash[:count] = count
end
# Primitive method
rule_hash[:rule_type] = RULE_HASH[matches[1]]
# BY
if matches[3].present? && (bys = matches[3].split('.'))
validations = {}
bys.each do |by_op|
next if by_op.size == 0
if (m = BYDAY_REGEX.match(by_op)) && (d = BYDAY_HASH[m[2]])
if (m[1].size > 0)
day_of_week = validations.fetch(:day_of_week, {})
day_of_week[d] = [day_of_week[d], m[1].to_i].flatten.compact
validations[:day_of_week] = day_of_week
else
validations[:day] = [validations[:day], d].flatten.compact
end
end
if BYMONTH_REGEX =~ by_op
value = by_op.delete('M').to_i
validations[:month_of_year] = [validations[:month_of_year], value].flatten.compact
end
if BYMONTHDAY_REGEX =~ by_op
value = by_op.delete('D').to_i
validations[:day_of_month] = [validations[:day_of_month], value].flatten.compact
end
if BYYEARDAY_REGEX =~ by_op
value = by_op.delete('Y').to_i
validations[:day_of_year] = [validations[:day_of_year], value].flatten.compact
end
if BYWEEKNO_REGEX =~ by_op
# Not support by ice_cube
end
end
if validations.keys.count > 0
rule_hash[:validations] = validations
end
end
if (end_date = matches[4][1..-1])
rule_hash[:until] = Time.parse(end_date).to_s
end
IceCube::Rule.from_hash(rule_hash)
end
end
end
# Example from https://tools.ietf.org/html/rfc5545
#
# Daily for 10 occurrences:
# RRULE:FREQ=DAILY;COUNT=10
# D#10
#
# Daily until December 24, 1997:
# RRULE:FREQ=DAILY;UNTIL=19971224T000000Z
# D<19971224
#
# Every other day - forever:
# RRULE:FREQ=DAILY;INTERVAL=2
# D+2
#
# Every 10 days, 5 occurrences:
# RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
# D+10#5
#
# Every day in January, for 3 years:
# RRULE:FREQ=YEARLY;UNTIL=20000131T140000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA
# Y.M1.SU.MO.TU.WE.TH.FR.SA<20000131
# or
# RRULE:FREQ=DAILY;UNTIL=20000131T140000Z;BYMONTH=1
# D.M1<20000131
#
# Weekly for 10 occurrences:
# RRULE:FREQ=WEEKLY;COUNT=10
# W#10
#
# Weekly until December 24, 1997:
# RRULE:FREQ=WEEKLY;UNTIL=19971224T000000Z
# W<19971224
#
# Every other week - forever:
# RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU
# W+2
#
# Weekly on Tuesday and Thursday for five weeks:
# RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH
# W.TU.TH<19971007
# or
# RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH
# W#10.TU.TH
#
# Every other week on Monday, Wednesday, and Friday until December
# 24, 1997, starting on Monday, September 1, 1997:
# RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR
# W+2.MO.WE.FR<19971224
#
# Every other week on Tuesday and Thursday, for 8 occurrences:
# RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH
# W+2#8.TU.TH
#
# Monthly on the first Friday for 10 occurrences:
# RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR
# M#10.1FR
#
# Monthly on the first Friday until December 24, 1997:
# RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR
# M.1FR<19971224
#
# Every other month on the first and last Sunday of the month for 10 occurrences:
# RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU
# M+2#10.1SU.-1SU
#
# Monthly on the second-to-last Monday of the month for 6 months:
# RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO
# M#6.-2MO
#
# Monthly on the third-to-the-last day of the month, forever:
# RRULE:FREQ=MONTHLY;BYMONTHDAY=-3
# M.-D3
#
# Monthly on the 2nd and 15th of the month for 10 occurrences:
# RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15
# M#10.D2.D15
#
# Monthly on the first and last day of the month for 10 occurrences:
# RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1
# M#10.D1.-D1
#
# Every 18 months on the 10th thru 15th of the month for 10 occurrences:
# RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15
# M+18#10.D10.D11.D12.D13.D14.D15
#
# Every Tuesday, every other month:
# RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU
# M+2.TU
#
# Yearly in June and July for 10 occurrences:
# RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7
# Y#10.M6.M7
#
# Every other year on January, February, and March for 10 occurrences:
# RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3
# Y+2#10.M1.M2.M3
#
# Every third year on the 1st, 100th, and 200th day for 10 occurrences:
# RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200
# Y+3#10.Y1.Y100.Y200
#
# Every 20th Monday of the year, forever:
# RRULE:FREQ=YEARLY;BYDAY=20MO
# Y.20MO
#
# Monday of week number 20 (where the default start of the week is Monday), forever:
# RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO
# Y.W20.MO
#
# Every Thursday in March, forever:
# RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH
# Y.M3.TH
#
# Every Thursday, but only during June, July, and August, forever:
# RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8
# Y.TH.M6.M7.M8
#
# Every Friday the 13th, forever:
# RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
# M.FR.D13
#
# The first Saturday that follows the first Sunday of the month, forever:
# RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13
# M.SA.D7.D8.D9.D10.D11.D12.D13
#
# Every 4 years, the first Tuesday after a Monday in November,
# forever (U.S. Presidential Election day):
# RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8
# Y+4.M11.TU.D2.D3.D4.D5.D6.D7.D8
@yjchen
Owner
yjchen commented Mar 17, 2015
require 'test_helper'

class SimpleRuleTest < ActiveSupport::TestCase
  setup do
  end

  test 'Read rule' do 
    r = RuleService::Rule.new
    assert_not_nil r
  end

  test 'Every Friday the 13th, forever' do
    rule = 'M.FR.D13'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.first(5)
    assert_equal occurrences[0], Time.zone.parse('19980213')
    assert_equal occurrences[1], Time.zone.parse('19980313')
    assert_equal occurrences[2], Time.zone.parse('19981113')
    assert_equal occurrences[3], Time.zone.parse('19990813')
    assert_equal occurrences[4], Time.zone.parse('20001013')
  end

  test 'Every Thursday, but only during June, July, and August, forever' do
    rule = 'Y.M6.M7.M8.TH'
    start_date = Time.zone.parse('19970605')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.first(20)
    assert_equal occurrences[0], Time.zone.parse('19970605')
    assert_equal occurrences[1], Time.zone.parse('19970612')
    assert_equal occurrences[2], Time.zone.parse('19970619')
    assert_equal occurrences[18], Time.zone.parse('19980709')
    assert_equal occurrences[19], Time.zone.parse('19980716')
  end

  test 'Every Thursday in March' do
    rule = 'Y.M3.TH'
    start_date = Time.zone.parse('19970313')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.first(10)
    assert_equal occurrences[0], Time.zone.parse('19970313')
    assert_equal occurrences[1], Time.zone.parse('19970320')
    assert_equal occurrences[2], Time.zone.parse('19970327')
    assert_equal occurrences[8], Time.zone.parse('19990311')
    assert_equal occurrences[9], Time.zone.parse('19990318')
  end

  test 'Every third year on the 1st, 100th, and 200th day for 10 occurrences' do
    rule = 'Y+3#10.Y1.Y100.Y200'
    start_date = Time.zone.parse('19970101')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.all_occurrences
    assert_equal occurrences[0], Time.zone.parse('19970101')
    assert_equal occurrences[1], Time.zone.parse('19970410')
    assert_equal occurrences[4], Time.zone.parse('20000409')
    assert_equal occurrences[5], Time.zone.parse('20000718')
  end

  test 'Every other year on January, February, and March for 10 occurrences' do
    rule = 'Y+2#10.M1.M2.M3'
    start_date = Time.zone.parse('19970310')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.all_occurrences
    assert_equal occurrences[0], Time.zone.parse('19970310')
    assert_equal occurrences[1], Time.zone.parse('19990110')
    assert_equal occurrences[4], Time.zone.parse('20010110')
    assert_equal occurrences[5], Time.zone.parse('20010210')
  end

  test 'Yearly in June and July for 10 occurrences' do
    rule = 'Y#10.M6.M7'
    start_date = Time.zone.parse('19970610')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.first(6)
    assert_equal occurrences[0], Time.zone.parse('19970610')
    assert_equal occurrences[1], Time.zone.parse('19970710')
    assert_equal occurrences[4], Time.zone.parse('19990610')
    assert_equal occurrences[5], Time.zone.parse('19990710')
  end

  test 'Every Tuesday, every other month' do
    rule = 'M+2.TU'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.first(6)
    assert_equal occurrences[0], Time.zone.parse('19970902')
    assert_equal occurrences[1], Time.zone.parse('19970909')
    assert_equal occurrences[4], Time.zone.parse('19970930')
    assert_equal occurrences[5], Time.zone.parse('19971104')
  end

  test 'Every 18 months on the 10th thru 15th of the month for 10 occurrences' do
    rule = 'M+18#10.D10.D11.D12.D13.D14.D15'
    start_date = Time.zone.parse('19970910')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.all_occurrences
    assert_equal occurrences[0], Time.zone.parse('19970910')
    assert_equal occurrences[1], Time.zone.parse('19970911')
    assert_equal occurrences[4], Time.zone.parse('19970914')
    assert_equal occurrences[5], Time.zone.parse('19970915')
    assert_equal s.last, Time.zone.parse('19990313')
  end

  test 'Monthly on the first and last day of the month for 10 occurrences' do
    rule = 'M#10.D1.-D1'
    start_date = Time.zone.parse('19970930')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.all_occurrences
    assert_equal occurrences[0], Time.zone.parse('19970930')
    assert_equal occurrences[1], Time.zone.parse('19971001')
    assert_equal occurrences[4], Time.zone.parse('19971130')
    assert_equal occurrences[5], Time.zone.parse('19971201')
  end

  test 'Monthly on the 2nd and 15th of the month for 10 occurrences' do
    rule = 'M#10.D2.D15'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.all_occurrences
    assert_equal occurrences[0], Time.zone.parse('19970902')
    assert_equal occurrences[1], Time.zone.parse('19970915')
    assert_equal occurrences[4], Time.zone.parse('19971102')
    assert_equal occurrences[5], Time.zone.parse('19971115')
  end

  test 'Monthly on the third-to-the-last day of the month, forever' do
    rule = 'M.-D3'
    start_date = Time.zone.parse('19970928')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.first(6)
    assert_equal occurrences[0], Time.zone.parse('19970928')
    assert_equal occurrences[1], Time.zone.parse('19971029')
    assert_equal occurrences[4], Time.zone.parse('19980129')
    assert_equal occurrences[5], Time.zone.parse('19980226')
  end

  test 'Monthly on the second-to-last Monday of the month for 6 months' do
    rule = 'M#6.-2MO'
    start_date = Time.zone.parse('19970922')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.all_occurrences
    assert_equal occurrences[0], Time.zone.parse('19970922')
    assert_equal occurrences[1], Time.zone.parse('19971020')
    assert_equal occurrences[4], Time.zone.parse('19980119')
    assert_equal occurrences[5], Time.zone.parse('19980216')
  end

  test 'Every other month on the first and last Sunday of the month for 10 occurrences' do
    rule = 'M+2#10.1SU.-1SU'
    start_date = Time.zone.parse('19970907')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.all_occurrences
    assert_equal occurrences[0], Time.zone.parse('19970907')
    assert_equal occurrences[1], Time.zone.parse('19970928')
    assert_equal occurrences[8], Time.zone.parse('19980503')
    assert_equal occurrences[9], Time.zone.parse('19980531')
  end

  test 'Monthly on the first Friday until December 24, 1997' do
    rule = 'M.1FR<19971224'
    start_date = Time.zone.parse('19970905')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970905')
    assert_equal s.first(2)[1], Time.zone.parse('19971003')
    assert_equal s.last, Time.zone.parse('19971205')
    assert_equal 4, s.all_occurrences.count
  end

  test 'Monthly on the first Friday for 10 occurrences' do
    rule = 'M#10.1FR'
    start_date = Time.zone.parse('19970905')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970905')
    assert_equal s.first(2)[1], Time.zone.parse('19971003')
    assert_equal s.last, Time.zone.parse('19980605')
    assert_equal 10, s.all_occurrences.count
  end

  test 'Every other week on Tuesday and Thursday, for 8 occurrences' do
    rule = 'W+2#8.TU.TH'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    assert_equal s.last, Time.zone.parse('19971016')
    assert_equal 8, s.all_occurrences.count
  end

  test 'Every other week on Monday, Wednesday, and Friday until December 24, 1997, starting on Monday, September 1, 1997' do
    rule = 'W+2.MO.WE.FR<19971224'
    start_date = Time.zone.parse('19970901')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970901')
    # Note this differs from RFC5545 because UNTIL does not define time.
    assert_equal s.last, Time.zone.parse('19971224')
    assert_equal 26, s.all_occurrences.count
  end

  test 'Weekly on Tuesday and Thursday for five weeks, another version' do
    rule = 'W#10.TU.TH'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    assert_equal s.last, Time.zone.parse('19971002')
    assert_equal 10, s.all_occurrences.count
  end

  test 'Weekly on Tuesday and Thursday for five weeks' do
    rule = 'W.TU.TH<19971007'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    # Note this differs from RFC5545 because UNTIL does not define time.
    assert_equal s.last, Time.zone.parse('19971007')
    assert_equal 11, s.all_occurrences.count
  end

  test 'Every other week - forever' do
    rule = 'W+2'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    occurrences = s.first(5)
    assert_equal occurrences[0], Time.zone.parse('19970902')
    assert_equal occurrences[4], Time.zone.parse('19971028')
  end

  test 'Weekly until December 24, 1997' do
    rule = 'W<19971224'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    assert_equal s.last, Time.zone.parse('19971223')
    assert_equal 17, s.all_occurrences.count
  end

  test 'Weekly for 10 occurrences' do
    rule = 'W#10'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    assert_equal s.last, Time.zone.parse('19971104')
    assert_equal 10, s.all_occurrences.count
  end

  test 'Every day in January, for 3 years, another version' do
    rule = 'Y.M1.SU.MO.TU.WE.TH.FR.SA<20000131'
    start_date = Time.zone.parse('19980101')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19980101')
    assert_equal s.last, Time.zone.parse('20000131')
    assert_equal 31*3, s.all_occurrences.count
  end

  test 'Every day in January, for 3 years' do
    rule = 'D.M1<20000131'
    start_date = Time.zone.parse('19980101')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19980101')
    assert_equal s.last, Time.zone.parse('20000131')
    assert_equal 31*3, s.all_occurrences.count
  end

  test 'Every 10 days, 5 occurrences' do
    rule = 'D+10#5'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    assert_equal s.last, Time.zone.parse('19971012')
    assert_equal 5, s.all_occurrences.count
  end

  test 'Every other day - forever' do
    rule = 'D+2'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    assert_not s.occurs_on?(Time.zone.parse('19970903'))
    assert s.occurs_on?(Time.zone.parse('19970904'))
  end

  test 'Daily until December 24, 1997' do
    rule = 'D#10'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    assert_equal s.last, Time.zone.parse('19970911')
  end

  test 'Daily for 10 occurrences' do
    rule = 'D<19971224'
    start_date = Time.zone.parse('19970902')
    s = IceCube::Schedule.new(start_date)
    s.add_recurrence_rule(RuleService::Rule.new(rule).to_ice_cube_rule)
    assert_equal s.first, Time.zone.parse('19970902')
    # Note this differs from RFC5545 because UNTIL does not define time.
    assert_equal s.last, Time.zone.parse('19971224')
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment