ice_cube
Ruby Date Recurrence Library - Allows easy creation of recurrence rules and fast querying
Ice cube by seejohnrun
Is it possible to make a rule like every 1 month and 10 days? Obviously 40 days isn't correct since months have a variable number of days in them, and it isn't by day of month or a particular day of the week?
Something that would generate:
1/01/2014
2/10/2014
3/20/2014
4/30/2014
6/09/2014
Source: (StackOverflow)
Lets say I want a task to be scheduled every 6 hours on one day a week, every 2 weeks. How would I achieve this? I've used hour_of_day
to add a specific hour to a weekly rule, but I'd like to avoid having to calculate each specific hour based off of the interval and start time, and adding them individually. Is it possible to chain rules? Like an hourly rule on top of a weekly one? When I add them as two separate rules, the hourly one fires independent of the weekly one, i.e. on days that wouldn't satisfy the weekly rule.
Source: (StackOverflow)
I'm using Ice_cube gem to generate events, and looks fine. The model that implements the recurrency is called "Job" , now I have a list of job, using pagination. I need to sort the Jobs in the list using the next events. The problem is that I'm using find method and will paginate to obtain the jobs . So my question is hoy I can sort the jobs , using the next event like parameter ?
Thanks.
Source: (StackOverflow)
I have Event model(title,user,desciption,date_begin,date_end,repeat(daily, weekly, etc.))
class Event < ActiveRecord::Base
belongs_to :user
include IceCube
end
What are the next steps for recurring events and their output? for example repeat = daily
Source: (StackOverflow)
I'm attempting to utilize the [awesome] functionality of ice_cube and recurring_select gems to handle recurring events. I've got a schedule
(text) column in my database and the following in the event model:
def schedule=(new_schedule)
write_attribute(:schedule, RecurringSelect.dirty_hash_to_rule(new_schedule).to_yaml)
end
def converted_schedule
Schedule.from_yaml(self.schedule, :start_date_override => self.start_date)
end
Looking at the schedule column in psql, it appears to be storing the schedule correctly.
Here's my form:
.control-group
= f.label 'Date', :class => 'control-label'
.controls
= f.text_field :start_date, :class => 'datepicker'
.control-group
= f.label 'Recurring?', :class => 'control-label'
.controls
= f.select_recurring :schedule, :allow_blank => true
However, when I attempt to output converted_schedule
, it only shows the start date and won't show any additional dates. I have a few suspicions that I've tinkered with no success... perhaps the YAML isn't being converted correctly for the converted_schedule
method? Perhaps I need an end-date (I don't see where this functionality is available on recurring_select)?
Source: (StackOverflow)
I'm looking into using Ice Cube https://github.com/seejohnrun/ice_cube for recurring events.
My question is, if I then need to get any events that fall within a given time period (say, on a day or within a week), is there any better way than to loop through them all like this:
items = Records.find(:all)
items.each do |item|
schedule = item.schedule
if schedule.occurs_on?(Date.new)
#if today is a recurrence, add to array
end
end
This seems horribly inefficient but I'm not sure how else to go about it.
Source: (StackOverflow)
I'm trying to use a Ruby gem called ice_cube in IRB, but it doesn't work:
[~]$ rvm gemset create ice
'ice' gemset created (/home/joe/.rvm/gems/ruby-1.9.2-p320@ice).
[~]$ rvm gemset use ice
Using ruby-1.9.2-p320 with gemset ice
[~]$ gem install ice_cube
Fetching: ice_cube-0.8.0.gem (100%)
Successfully installed ice_cube-0.8.0
1 gem installed
Installing ri documentation for ice_cube-0.8.0...
Installing RDoc documentation for ice_cube-0.8.0...
[~]$ irb --simple-prompt
>> require 'ice_cube'
=> true
>> schedule = Schedule.new(Time.now)
NameError: uninitialized constant Object::Schedule
from (irb):2
from /home/joe/.rvm/rubies/ruby-1.9.2-p320/bin/irb:16:in `<main>'
What am I doing wrong? (I'm a beginner Ruby programmer.)
Source: (StackOverflow)
I have simple Event model (title, date, user)
And I created Events Calendar by months (gem 'watu_table_builder'). I need the feature to create repeating events. I figured out that I may use gem ice_cube for it. But it is not clear for me.
I added to model:
class Event < ActiveRecord::Base
#require 'ice_cube'
include IceCube
belongs_to :user
validates :title, :presence => true,
:length => { :minimum => 5 }
validates :shedule, :presence => true
def self.events_and_repeats(date)
@events = Event.where(shedule:date.beginning_of_month..date.end_of_month)
# Here I need to figure out what is events repeats at this month (from date param)
# how I may combine it with Events array
@events_repeats = @events # + repeats
return @events_repeats
end
1) How I may combine repeat rules with Events array?
2) As I understand, I may save to db information about repeats in yaml
yaml = schedule.to_yaml
But it is not clear for me how it is good way to create drop-down for repeats (none, each day, each month, each year) and link it with shedule rules. Where and how I should realize it (convert user choise to right shedule)
Source: (StackOverflow)
There must be something simple being overlooked here...
I've been trying various methods for creating a basic IceCube
schedule (https://github.com/seejohnrun/ice_cube). The overall goal is to use IceCube
to allow "price schedules" inside a "room reservation" rails application.
The first scenario would be creating a basic schedule
with a specific start_time
and end_time
- occurring only once. IceCube
can do this, correct?
The schedule would begin on the start_time
and end at the end_time
. I would expect to be able to check if dates or times occurs_on?
this schedule to determine if a room price should be adjusted.
So in console I've tried creating a basic schedule and would expect it to be occurring 5.days
from now since the start_time
is Time.now
and the end_time
is Time.now + 30.days
. But it seems to never return true...
1.8.7 :001 > schedule = IceCube::Schedule.new(Time.now, :end_time => Time.now + 30.days)
=> #<IceCube::Schedule:0xb619d604 @all_recurrence_rules=[], @duration=nil, @end_time=Tue Jan 08 09:13:11 -0600 2013, @all_exception_rules=[], @start_time=Sun Dec 09 09:13:11 -0600 2012>
1.8.7 :002 > schedule.occurs_on? Date.today + 5.days
=> false
1.8.7 :005 > schedule.occurs_at? Time.now + 5.days
=> false
1.8.7 :006 > schedule.occurring_at? Time.now + 5.days
=> false
Adding a recurrence rule
1.8.7 :018 > schedule.rrule IceCube::Rule.monthly
=> [#<IceCube::MonthlyRule:0xb687a88c @validations={:base_day=>[#<IceCube::Validations::ScheduleLock::Validation:0xb6875b0c @type=:day>], :base_hour=>[#<IceCube::Validations::ScheduleLock::Validation:0xb6875abc @type=:hour>], :interval=>[#<IceCube::Validations::MonthlyInterval::Validation:0xb6875d28 @interval=1>], :base_min=>[#<IceCube::Validations::ScheduleLock::Validation:0xb6875a6c @type=:min>], :base_sec=>[#<IceCube::Validations::ScheduleLock::Validation:0xb6875a1c @type=:sec>]}, @interval=1>]
Then checking Date.today
works...
1.8.7 :025 > schedule.occurs_on? Date.today
=> true
But checking occurs_on? for Date.today + 10.days
still returns false... Why?
1.8.7 :026 > schedule.occurs_on? Date.today + 10.days
=> false
So what am I overlooking / doing wrong? Or what is the point of setting an IceCube::Schedule start_time
and end_time
- they seem to have no effect...?
Does IceCube
not work for single occurrence events with a start and end time?
Another example scenario, a room owner wants room prices raised for a holiday season. So the room owner creates a price schedule that starts on Dec 1 2012 and ends Jan 7 2013. (shouldn't have to recur, but could if the owner wanted).
Then when people are searching rooms, the prices would be adjusted if the requested stay occurs_on?
a holiday price schedule
Do I need to store the start_time
and end_time
outside of the schedule and check it manually or something?
Or is there a better suited gem / tool to assist with this kind of schedule management?
Source: (StackOverflow)
i would like to identify the details of an schedule. e.g:
i have the schedule for an event: event.schedule
"Every 3 months on the 10th day of the month"
represented by the hash:
{
:start_date=>2012-02-06 10:37:04 +0100,
:rrules=>[{
:validations=>{
:day_of_month=>[10]},
:rule_type=>"IceCube::MonthlyRule",
:interval=>3
}],
:exrules=>[], :rdates=>[], :exdates=>[]
}
to set the specific form elements (dropdown, checkbox) i need to evaluate the specific rules. e.g. for
event.schedule.interval
i would expect
IceCube::MonthlyRule
i did not found any methods in the source, does somebody did sth. similar ? My approach would be to parse the hash and extract every rule...
Source: (StackOverflow)
I am trying to create recurring events using ice_cube and recurring_select gems.
Here is my _form.html.erb code:
<%= simple_form_for(@event) do |f| %>
<div class="form-inputs">
<%= f.select_recurring :day, [IceCube::Rule.daily] %>
<%= f.input :start_time %>
<%= f.input :end_time %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
In my controller I have (among other things):
def new
@event = Event.new
end
def create
@event = Event.new(event_params)
respond_to do |format|
if @event.save
format.html { redirect_to @event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: @event }
else
format.html { render :new }
format.json { render json: @event.errors, status: :unprocessable_entity }
end
end
end
def event_params
params.require(:event).permit(:day, :start_time, :end_time, :reserved)
end
As you can see I want to create the same event for each day in a week, but actually my :day column remains empty if I submit this form.
Can you give some feedback? I don't know what can be wrong
Source: (StackOverflow)
Given two large arrays of ranges...
A = [0..23, 30..53, 60..83, 90..113]
B = [-Float::INFINITY..13, 25..33, 45..53, 65..73, 85..93]
When I do a logical conjuction...
C = A.mask(B)
Then I expect
describe "Array#mask" do
it{expect(C = A.mask(B)).to eq([0..13, 30..33, 45..53, 65..73, 90..93])}
end
It feels like it should be...
C = A & B
=> []
but that's empty because none of the ranges are identical.
Here's a pictorial example.
.
I've included Infinity in the range because solutions to this problem typically involve converting the Range to an Array or Set.
My current solution
This is my current solution with passing tests for speed and accuracy. I was looking for comments and/or suggested improvements. The second test uses the excellent IceCube gem to generate an array of date ranges. There's an implicit assumption in my mask method that date range occurrences within each schedule do not overlap.
require 'pry'
require 'rspec'
require 'benchmark'
require 'chronic'
require 'ice_cube'
require 'active_support'
require 'active_support/core_ext/numeric'
require 'active_support/core_ext/date/calculations'
A = [0..23, 30..53, 60..83, 90..113]
B = [-Float::INFINITY..13, 25..33, 45..53, 65..73, 85..93]
class Array
def mask(other)
a_down = self.map{|r| [:a, r.max]}
a_up = self.map{|r| [:a, r.min]}
b_down = other.map{|r| [:b, r.max]}
b_up = other.map{|r| [:b, r.min]}
up = a_up + b_up
down = a_down + b_down
a, b, start, result = false, false, nil, []
ticks = (up + down).sort_by{|i| i[1]}
ticks.each do |tick|
tick[0] == :a ? a = !a : b = !b
result << (start..tick[1]) if !start.nil?
start = a & b ? tick[1] : nil
end
return result
end
end
describe "Array#mask" do
context "simple integer array" do
it{expect(C = A.mask(B)).to eq([0..13, 30..33, 45..53, 65..73, 90..93])}
end
context "larger date ranges from IceCube schedule" do
it "should take less than 0.1 seconds" do
year = Time.now..(Time.now + 52.weeks)
non_premium_schedule = IceCube::Schedule.new(Time.at(0)) do |s|
s.duration = 12.hours
s.add_recurrence_rule IceCube::Rule.weekly.day(:monday, :tuesday, :wednesday, :thursday, :friday).hour_of_day(7).minute_of_hour(0)
end
rota_schedule = IceCube::Schedule.new(Time.at(0)) do |s|
s.duration = 7.hours
s.add_recurrence_rule IceCube::Rule.weekly(2).day(:tuesday).hour_of_day(15).minute_of_hour(30)
end
np = non_premium_schedule.occurrences_between(year.min, year.max).map{|d| d..d+non_premium_schedule.duration}
rt = rota_schedule.occurrences_between(year.min, year.max).map{|d| d..d+rota_schedule.duration}
expect(Benchmark.realtime{np.mask(rt)}).to be < 0.1
end
end
end
It feels odd that you can't do this with Ruby's existing core methods? Am I missing something? I find myself calculating range intersections on a fairly regular basis.
It also occurred to me that you could use the same method to find an intersection between two single ranges by passing single item arrays. e.g.
[(54..99)].mask[(65..120)]
I realise I've kind of answered my own question but thought I would leave it here as a reference for others.
Source: (StackOverflow)
How am I able to rule opening hours of a restaurant within single Schedule?
Mon-Fri 8-16 is quite easy:
schedule = Schedule.new(Time.parse(Date.yesterday.to_s + ' 8:00'), :duration => 60*60*8)
(...)
schedule.add_recurrence_rule Rule.daily.day(:wednesday)
schedule.add_recurrence_rule Rule.daily.day(:thursday)
(...)
schedule.occurring_at?(Time.now)
Problem is when trying to rule something like:
Mon 9-17,
Tu 16-01 (the next day after midnight)
etc.
Am I able to do this with that plugin?
Source: (StackOverflow)
I am trying to implement recurring events for event_calendar and it is turing out to be quite challenge. It seem I have to write the recurrence for my events from scratch. I have no problem with that as long as I am not missing a better way of doing it that has already been implemented and that I could potentially even contribute to.
How did or do you recommend implementing recurring events for a calendar such as event_calendar?
If I have to start from scratch what advices could you give?
Would you use Ice_cube? Can you describe your approach? Thank you so much.
Source: (StackOverflow)
Just started playing around with ice_cube I've got a weekly schedule (with a granularity of half an hour) created
schedule = IceCube::Schedule.new(Time.now.change(:min => 30))
with several rules (let's say 20) such as e.g.
IceCube::Rule.weekly.day(:tuesday).hour_of_day(14).minute_of_hour(30)
or
IceCube::Rule.weekly.day(:wednesday).hour_of_day(10).minute_of_hour(0)
Now I'd like to exclude a full day, which would subsequently exclude all occurrences during this full day.
I've tried
schedule.add_exception_date [DATE]
but it seems that my exception has to match the event exactly.
Is there a way to get this done without looping through all rules and creating exception for the exact times for the date specified?
Update:
To make a better example:
Weekly schedule:
* Every monday at 14:40
* Every monday at 15:00
* Every thursday at 16:00
* Every saturday at 10:00
Exception date:
Tuesday, 13th of September 2011
=> For the week from Monday 12th to Sunday 18th I'd like to get only the occurrences on Thursday and Saturday.
One solution could look something like this, but it's a little icky:
schedule = IceCube::Schedule.from_yaml([PERSISTED SCHEDULE])
occurrences = schedule.occurrences_between([START TIME], [END TIME])
exceptions = schedule.exdates.map(&:to_date)
occurrences.reject {|occurrence|
exceptions.include?(occurrence.to_date)
}
—Any better ideas?
Source: (StackOverflow)