Reputation: 9895
How do I utilize the ice_cube gem for items (events) that have both a start and end time (Ex: Mon, Wed, Fri @ 10pm-11:30pm EST)?
I currently store all times in the database in UTC. So for the example above, the item looks like this:
#<Item recurring: {:validations=>{:day=>[1, 3, 5]}, :rule_type=>"IceCube::WeeklyRule", :interval=>1, :week_start=>0}, start_time: "2017-11-21 03:00:00", end_time: "2017-12-24 04:30:00"">
If I want to see if that item occurs on a date between two times, I''m attempting this:
item.schedule(item.start_time).occurs_between?(some_start_time, some_end_time)
This unfortunately returns false
if I pass in some_start_time
of Tue, 28 Nov 2017 03:00:00 UTC +00:00
(Mon @ 10pm EST) and some_end_time
of Tue, 28 Nov 2017 04:30:00 UTC +00:00
(Mon @ 11:30 EST). I believe that's because the ice_cube
gem will only show conflicts for Mon, Wed, Fri with the rules I've setup?
I feel like I'm missing something fundamental about the gem. How do I account for time zones properly? I think the ultimate goal would be, if I let the user select Mon, Wed, Fri from 10pm to 11:30pm, I need it to store the recurrence as Tue, Thu, Sat from 3am to 4:30am.
Here's how I'm implementing my Item
class in Rails.
class Item
serialize :recurring, Hash
def recurring=(value)
RecurringSelect.is_valid_rule?(value) ? super(RecurringSelect.dirty_hash_to_rule(value).to_hash) : super(nil)
end
def rule
IceCube::Rule.from_hash(recurring)
end
def schedule(start)
schedule = IceCube::Schedule.new(start)
schedule.add_recurrence_rule(rule)
schedule
end
end
Update
I am also using the recurrence_select gem. This is what let's the user easily choose "Weekly on Monday, Wednesday, and Friday". I separately let the user select the start_time
and end_time
for the item. I'm correctly converting the times to UTC from their time zone when I save to the database. I somehow need to know if the days roll over as well and modify them before it saves.
Upvotes: 1
Views: 728
Reputation: 369
TL/DR; Yes, since your rule says M, W, F you will get false when you pass in Tuesday.
More info:
From the documentation, "A schedule's occurrences will be returned in the same class and time zone as the schedule's start_time." If you pass UTC, it will return in UTC (or whatever timezone you choose).
Timezones are a pain, but there are several Rails helpers to get you on the right track (http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html). Your instinct to save everything to the db in UTC is a good one. The trick then is keeping track of the days. Essentially you need to have a way to have a display for the user that makes sense in their timezone, then translate it the db in UTC, and pass it to your rule appropriately.
Take a look at this helper, which allows you to convert between timezones, and even pass in a date argument to refine which date you want the actual time attached to: https://github.com/LaunchPadLab/rails_util/blob/master/lib/rails_util/timezone_helper.rb
Not trying to promote, you don't have to use that library, but it might be worth taking a look at the logic we came up with, and see if you can apply that thinking to your app.
Upvotes: 1