00:00:09.320
Alright, so I'm going to be talking about recurring dates today. You can see me, John Crepezzi, run on Twitter if anyone is interested in hearing more about recurring dates.
00:00:15.269
This is my blog, and the slides are posted here tonight. You can also find the slides on the GitHub page for IceCube, which is the gem I'm going to talk about today. Not the rapper— the gem.
00:00:21.210
I know the rapper has gotten a lot of attention lately, but I work at Patch in New York City. Patch is a hyperlocal news startup with a network of around 117 websites covering small towns all across America.
00:00:28.500
The reason this project started is that Patch, as part of its offering, includes an events calendar. Often, the events calendar on Patch needs to include committee meetings and board meetings, which can have irregular schedules. They aren't like every Monday, as a soccer game might be. Instead, board meetings may be scheduled for the second Tuesday of the month or the third Sunday, or perhaps the second to last Monday.
00:00:46.950
These schedules can be quite unusual, and we don't want people to have to revisit the site every three months to ensure the next three months of board meetings are set up in the events calendar. They need a way to establish the schedule once and have it exist without constant updates. Thus, I set out to create a gem that would handle date occurrences.
00:01:12.840
I noticed that dates in general can be a tricky issue when programming. In fact, they are often a sticking point for any language. When a programming language emerges, it typically has a built-in time and date library. However, users often find that it does not meet their needs, is too buggy, or has a confusing interface. Dates can present challenges that complicate programming.
00:01:40.380
Daylight saving time is a common problem, as are time zones and their various UTC/GMT offsets. What people might not realize is that different geographical areas can switch to daylight saving time at different times of the year. Consequently, managing the switches among various time zones can be a significant challenge.
00:02:06.659
Moreover, February comes out of nowhere with its 28 days, adding to the complexity. On top of time-related issues, there's also the problem of occurrences—such as identifying the first and last Monday of every month. This might seem simple when described verbally, but when we try to define it in code, the complications multiply, leading to convoluted solutions.
00:02:27.780
One way to circumvent this is by using the date library and incrementing time second by second, allowing the library to handle these peculiar quirks. However, this approach is inefficient because you will need to iterate through every second between now and the next occurrence. This results in code that is not only hard to implement but often slow and clumsy.
00:02:52.019
More importantly, this is not the way code should be written. There should be a library that simplifies this process, and that's what IceCube is designed to be. Here’s the GitHub page: github.com/cjohnrun/icecube. On that page, you will also find a link to the introductory page, which is a well-presented version of the README.
00:03:13.949
A good starting point for IceCube is actually the iCalendar RFC; it makes sense to utilize the groundwork already laid down by someone else. The concept of recurring dates has already been explored thoroughly, so we shouldn't discard the work that’s been done. iCalendar provides a way to describe recurring dates more effectively than cron does.
00:03:50.430
iCalendar may also be referred to as VEvent, vCal, or ical, all of which adhere to the same standard. IceCube, in its specifications, implements every example from the iCalendar RFC to ensure comprehensive coverage. This required a lot of reading, but we emerged with a clean Ruby syntax for the entire thing, and I think it's quite an awesome name—though some may disagree.
00:04:02.219
By the end of this talk, I hope you'll come to appreciate IceCube as much as I do. To give you an idea of its potential, let’s look at a brief example of using IceCube. You create a schedule and set a start time; for instance, the first of January 2010, and you can then attach rules to your schedule.
00:04:23.340
One specific rule I might define is for occurrences that happen monthly, specifically on the 13th when it falls on a Friday. This represents a rule describing every Friday the 13th. IceCube offers methods such as `schedule.first(10)`, where the `first` method retrieves occurrences according to our defined rules.
00:05:07.620
In our context, `our rule` refers to recurrence rules, which we will explore further in due time. For those who prefer a more verbose syntax, there’s also `schedule.ed_recurrence_rule`, an abbreviation for our rule. The slider demonstrates that IceCube negotiates offsets efficiently as it navigates through time.
00:05:50.669
Next, let’s discuss rules in an IceCube context. Rules are foundational to IceCube, and there are many types: yearly, monthly, weekly, daily, hourly, minutely, and secondly. A simple example, such as a recurring monthly event, can be written as a new monthly rule. For instance, an 'every-other-month' rule might be defined as a monthly interval set to every two months.
00:06:35.640
However, it's essential to note that while you can define events based on weekly, daily, or annual criteria, those events typically must start on a pre-defined date. This introduces complexities around validation. For example, defining a rule for every day might seem simple but adding a stipulation like 'on Fridays' complicates things.
00:07:13.110
You can actually chain multiple validations together within the same rule, like I demonstrated earlier, where an event takes place every day that is Friday and occurs on the 13th of the month. This flexibility allows for intricate rule definitions.
00:07:50.090
Each of the rules I mentioned can be organized into schedules. You can create a new schedule that activates now, recurring daily by using `schedule.recurrence_rule` set to daily. However, if you want to exclude Saturdays from this schedule, you would need to add exclusion rules.
00:08:01.380
This demonstrates the flexibility of IceCube. When asking if a rule occurs on a particular day, it will evaluate based on the rules defined. For instance, if you check today, a Saturday, you will find that it was scheduled for yesterday.
00:08:35.790
Conversely, if you check tomorrow, it will confirm that it does, as tomorrow is not a Saturday. There’s also the ability to have blackout days on your schedules. You can include ‘hour dates’ and ‘ex dates’, where an hour date symbolizes a singular occurrence that must happen, while an x date represents a singular occurrence that cannot.
00:09:02.200
The order of precedence for these rules follows certain logic, as outlined in the iCalendar specification. If a rule prohibits a certain date, it takes priority over a rule that suggests a date should occur, and vice-versa.
00:09:50.990
For how we can start utilizing IceCube, we can query if there’s an occurrence on a specific date. By asking whether the schedule includes a date in its duration, it will return true if that date falls within the timeframe of the scheduled event.
00:10:09.970
You can also request the first ten occurrences or all occurrences up to a specified time or between two datetime instances. If there are any questions regarding this, I’m happy to explain further.
00:10:32.000
In addition, rules can include ‘until dates’ and ‘counts’. This means a rule can stop being effective after a certain date or a specific number of occurrences have been reached. It’s important to note that all rules must have either an until option or a count to facilitate utilization of all occurrences.
00:10:44.590
We don’t have a default setting for rules, and trying to call all occurrences will throw an ArgumentError, ensuring proper handling.
00:11:08.790
IceCube can also convert a rule into other formats. For instance, let's say you want to declare a monthly rule specifically set for the last Friday of the month. You would use a hash representation of this rule, allowing easy manipulation without tying it to specific objects.
00:11:43.960
IceCube provides a hash-based representation of its internal structure, as it marshals objects into this simpler format. Moreover, there's an IceCube port called IceCube for PHP, which allows interoperability between the two languages.
00:12:22.350
This enables smooth data interchange without having to abandon the native bar format. In terms of localization, though IceCube isn’t currently compliant with I18n standards, you can still utilize constructs like the second-to-last Friday of the month or add any multiple rules freely.
00:13:02.560
As for integration, if your application uses Active Support, IceCube will leverage its methods for additional capabilities. If those methods aren't available, IceCube will revert to its internal calls without issues.
00:14:04.930
After discussing this with some developers, there's potential for IceCube to enhance the Tickler project, thus introducing more versatile recurrence capabilities. Internally, IceCube implements time representation over date time as it's generally faster and more efficient.
00:14:43.570
However, when integrating with Rails and storing time in the database, it’s crucial to maintain that time zone information. Consequently, we ensure that, before being stored in the database, any date time instances within IceCube retain their time zone for effective retrieval.
00:15:25.540
If you have any queries about these concepts, I’m more than happy to answer them. Additionally, through internal representation of schedules, you can create clever rules and constraints for querying occurrences.
00:15:58.290
If you want to explore this system, you'll find that schedules can house various, linked occurrences, increasing flexibility. People have begun utilizing IceCube for a myriad of applications, such as event calendars, schedule conflict resolution, and task scheduling.
00:16:45.800
For instance, if you're trying to schedule meetings among several team members with various availabilities, IceCube allows you to ascertain easily when those individuals can meet, even if that requires defining complicated rules.
00:17:28.620
Additionally, remember that when you ask for the next occurrence, calling `.first` without arguments will yield a single element, but if you include an argument, it returns an array.
00:18:10.080
There's a growing interest in establishing IceCube as a foundational dependency for task scheduling, showcasing its potential to navigate more complex patterns of occurrences.
00:18:43.020
I encourage you all to explore contributions to this project. There’s a powerful opportunity to expand its capabilities, and I am genuinely excited to see what innovations might develop using IceCube.
00:19:20.350
This time is designated for questions or a demo if anyone is interested. I’m here to address any queries you might have about the concepts we discussed today.
00:19:59.800
For example, let's address a question about whether users primarily expand IceCube schedules or if they query them directly—both methods are valid, but they come with different performance implications.
00:20:22.569
If people wish to query recurring events directly, they should be mindful of the underlying rules and how they intersect, keeping in mind that querying can yield better performance if managed properly.
00:20:56.190
Regarding the intersection or union of rules, it's crucial to understand how IceCube handles multiple rules. If you add intersecting rules to the same schedule, it'll evaluate dates that satisfy at least one of them.
00:21:36.190
However, to get all occurrences that meet every condition defined across several rules, you'd need to accumulate all attributes within a single rule.
00:22:04.590
Connections between schedules can also be made where multiple schedules interact, meaning users can apply AND and OR logic when managing various schedules.
00:22:23.510
When it comes to handling time zones, the built-in Ruby time library only supports local and UTC. However, Active Support has robust time zone support, allowing you to use any timezone, effectively negotiating across various time zones.
00:23:02.389
You can also explore the idea of integrating IceCube with alternative libraries for even better performance, leveraging the strengths of those implementations.
00:23:36.000
This might include linking IceCube with home-grown time libraries to enhance usability while maintaining the existing capabilities.
00:24:07.420
For those with niche use cases, IceCube might not immediately accommodate complex calendrical phenomena like Easter, but we could always employ additional logic to enable this.
00:25:00.890
For instance, you can define considerable conditions within IceCube to navigate special cases like determining the first Sunday after the first full moon. With some creative problem-solving, those possibilities might be achieved.
00:25:56.480
Project contribution seems to be a fruitful direction, given that some users have discussed the potential of integrating election days or particular holiday patterns as well.
00:27:17.890
With more anticipated contributions, the framework can evolve to support features like handling custom time zones or intricate rules.
00:27:48.210
Overall, I'm excited to witness how the community engages with IceCube and look forward to any innovative projects that emerge. Thank you for joining me today—it’s been a wonderful experience discussing these ideas.
00:29:01.200
Remember to check out the slides available on my GitHub page. If anyone has anything more to discuss or suggestions about this topic, don’t hesitate to reach out.
00:29:15.100
Thanks again for your time, and I hope you enjoy using IceCube as much as I do!