There have been lots and lots of changes and enhancements to Date and Calendar for Drupal 7, so it's high time to outline and explain them. It's been a long road, but there are lots of great improvements and new features in these modules.
We did a lot of thinking about user experience (UX) by asking "What would Google (Calendar) Do?", and trying to push Date and Calendar in that direction.
And everything about the field and Views integration had to be "entified" -- made to work correctly on any kind of entity, not just nodes, to be compatible with the way things work in Drupal 7.
We also tried to address performance and efficiency, and we added lots of tests. There's more to be done, but a lot has been accomplished.
Better User Experience (UX)
The Acquia team jumped into the Date issue queue this year to help improve the Date UX, specifically, the forms used by administrators to create new Date fields, the forms used by end users to add dates, and the complex widget used for entering repeating dates. I'm very happy with the results.
For instance, there is a a redesigned widget for entering repeating dates. Repeating date fields have a 'Repeat' checkbox. If checked, it opens up the repeat options. The actual options that are displayed vary depending on the type of repeat you choose.
I have long wanted to clean that repeat widget up but it was a daunting task to make it simple without losing all the options we have now. Gergely Tamás Kurucz did most of the heavy lifting on that code, and I really like the result.
Show End Date and All Day Checkboxes
Another UX improvement is the addition of checkboxes that let the user decide to hide or show the end date or the time. For instance, checking the 'All Day' checkbox will hide the time and automatically set it to all day. These checkboxes are optional, and the choice to use them is controlled in the field settings.
Date API Administration
There were settings pages for various Date components getting scattered in lot of different places. They are being consolidated into a Date API Administration section to make them easier to find.
Speaking of configuration, anyone who uses Date fields would probably benefit by setting up a few additional date and time formats. The code to create custom, localized, date formats was added to the Drupal 6 version of the Date module by Stella Power, and it got moved to core in Drupal 7. Visit the Date and Time section of the Drupal Configuration page to create additional formats and types. Each new type you create will be available to use as a format for Date fields on the Display Fields tab and in Views.
Not everyone liked the jQuery timepicker used in the D6 version, so we've added support for a new one, the WVega timepicker. To choose that option, go to the Date Popup administration page and you'll see an option to turn off jQuery and use a plain text field or use the current jQuery timepicker. You will also see instructions for how to download and use the WVega timepicker as an alternative.
Date Fields For Any Entity
Once the code was mostly working for date fields on nodes, my focus turned to trying to ensure that date fields would work correctly on any entity. There was still a lot of node-centric code that needed to be updated.
The whole process of adding dates to other entities has taken a big effort and uncovered all kinds of odd issues. For instance, there is no generic API for the form a field will be attached to, and some entities have forms that behave quite differently from node forms. The Entity Translation module creates a form that hides non-translated fields using #access = FALSE, so the date field had to retain its value and work correctly when hidden that way. The Profile 2 module adds date fields onto other forms than its own, like the user registration form, so date fields had to work right there, too.
It has been a huge effort to find and fix all the problems that have been uncovered. There are still some problems with some kinds of dates used on some kinds of entities, but a lot of work has been done to fix the errors and problems that have arisen.
Date Views For Any Entity
We have lots of fieldable entities in Drupal 7, not just nodes, but users, comments, taxonomy terms and potentially other entities added by contributed modules. Most of those entities have date fields of one kind or another -- changed, created, timestamp, etc, on top of any Date fields that might have been added to them. I wanted, and intended, that all of these kinds of fields would be usable in the Date Views handlers and plugins.
First the Views integration code was pulled out into its own module, the Date Views module. Then the Date argument and filter had to be expanded to work with any Views base table, using any of these date fields from any entity.
The next step was to separate the filters into 'simple' and 'complex' filters. The simple filters are the ones that correspond to fields added by the Field module. They extend the basic Views date filters, and add a number of additional options, like a choice of widget to use in exposed filters, and options about the granularity and formatting of the filter.
The complex filters extend the simple ones but add in a method to select any field or property that implements the Date hooks so they can be used in the Date filters. These hooks are implemented by the Date Views module on behalf of many of the core date properties, like the node created date and user, comment, and file timestamps. Other modules can do the same if they choose.
Then, prodded by Kris Vanderwater (EclipseGC), I added in a new Date Pager plugin that lets you page back and forth by date and got rid of the old Date Browser (which was born from an early attempt to get date paging working in older versions of Views). Doing this as a pager plugin makes much more sense.
Again, there probably is still more work to do, but a lot of this is working as intended.
The new Multiday option for calendars was actually added as an option in the D6 version of Calendar. In D7 that has become the default. This code was contributed by Andrew Hall (developer-x). It adds an option to display a multiday event as a band across all the days when it occurs.
This option also adds options to do things like display the values on the day view as overlapping items.
Calendars For Any Entity
Once date fields for any entity were supported in Views, we needed to support them in Calendar. Initially, the Calendar module had a row plugin that only worked for nodes, but it now has a new 'Calendar Entities' row plugin that can be used for any date field on any kind of entity.
Creating calendars has always been an ordeal. I added a Date Tools module with a Date Wizard some time back. The wizard makes it really easy to create a new Date content type, field, and related calendar all in one fell swoop, but there was no easy way to create a calendar for existing date fields if you decided later that you wanted one. And if you created a calendar by cloning the default calendar view, the only other way to do it, you had to do a lot of clicking and checking to be sure you found and replaced all the default date fields with the date field you actually wanted in the calendar. Those days are over!!
Views has an option to 'Add view from template' that is hardly used by any module so far. I decided that Calendar might be the perfect place to take advantage of it. If you click on that 'Add from template' link in the latest code you will see that you have a list of calendar templates available, one for each date field that the Date API can use in a calendar. As noted above, that now means not just node dates or date fields, but also things like the 'last access' field on a user.
To create a new calendar, just select 'add' next to the template that uses the base table and field you want for your calendar. You will be taken to a form where you can input a name and description for your view, and then to the edit page for the view, where you will see that all the calendar displays have been constructed to use the date field you chose. The only thing you need to do is to save it. Of course, you can make changes and additions if you want, but it should be a perfectly functioning calendar for the selected date field.
New Date API and Modules
Lots of new hooks have been added recently to the Date API to make it easier for other modules to interact with date fields and to streamline the core code. The core Date API code has been ballooning as it tried to accommodate all the various features and situations that some people needed. It was time to put Date on a diet and move that code into optional sub modules. This makes the code cleaner and easier to maintain, and avoids parsing code that may not even be used.
A new file, api.date.php, has a list of some of the new hooks. The new hooks include things like hook_date_select_process_alter() and hook_date_field_formatter_settings_form_alter().
And there are two new modules that serve as an illustration of how other modules can use these hooks. The Date All Day module handles the 'All Day' label and the 'All Day' checkbox option. Anyone who doesn't want or need that functionality can leave that module disabled. Existing sites will see that it is enabled in an update hook to be sure we don't break current sites, but you can disable it if you don't want it.
Similarly, there is a new module called Date Repeat Field. Most of the functionality that creates and manages repeating date fields has been moved into that module. Again, it is enabled in an update hook for existing sites that have Date Repeat enabled, but it can be disabled if you don't use repeating date fields.
There have always been a lot of questions about how to create iCal feeds for calendars or other views. That has been managed by the Calendar iCal module in the past (a module that ships with the Calendar module). In D7 this functionality was completely rewritten to make it into a custom row plugin. It adds a new view mode, the 'ical' view mode, to the Display Fields page so you can configure exactly what you want to have in the iCal DESCRIPTION field. In its current state, it actually doesn't have any dependency on the Calendar module, and people were asking about separating it out so it could be used on non-Calendar views. I also wanted to abstract it out so it could work on any entity type, not just nodes.
So a new Date iCal module has been created. It should allow you to create an iCal feed for any type of entity and add it to any view. In the future it could also become a home for code to make it easier to import an iCal feed using the Feeds module, and have some pre-configured Features that illustrate how to import and export iCal feeds.
Code Cleanup and Tests
A lot of time has gone into trying to make the code cleaner and more efficient. The size of the tarball for the Calendar module has dropped from about 500 KB for the Drupal 6 version to 70 KB for the Drupal 7 version. The change in Date module is less dramatic because while a lot of things were removed, a lot of new features were added, but it still dropped from about 250 KB to 200 KB.
The reduction in code for Calendar was accomplished by trying to take much better advantage of Views. A lot of the old calendar code was working around limitations in older versions of Views. The new code is a total, ground-up, rewrite to use all the things that Views can do today.
In keeping with the core emphasis on testing, lots of additional tests have been added to the Date module. I'd still like to see more, but there are probably two or three times as many tests in the D7 version as there were in D6.
What's next? We need lots and lots and lots of documentation. Many things are only documented in the code and need to be pulled out into the Date and Calendar Handbook. I'm hoping people will jump in and start doing that. There are just not enough hours in the day for me to get all this done.
And we need to continue to make performance improvements. And add more tests. And find more ways to optimize the code.
We need to add better Token support for dates, but we're blocked for now by discussions going on in the Token module about how to handle field tokens.
We need to add real support for 'All Day' dates. Currently it is pseudo support -- we set them to midnight. That will require a change in the database architecture to add a column to store that value, so that change can't happen until we're ready to create a new branch.
And repeating dates need to be reworked and re-thought. I have a lot of ideas for better ways to do that, but all of them are major structural changes that also need to wait for a new branch.
I want to give a huge shout out to Arlin Sandbulte and Tim Plunkett for jumping into the Date and Calendar issue queues and cleaning them up, getting code cleaned up and better documented, and making and committing a number of patches. We have hundreds of issues on those queues, and new ones get added about as fast as old ones get cleaned up, so it's a constant battle to stay ahead of it. Having help with the issue queue has freed me up to get a lot of other improvements made, plus they have started (and finished) some things I couldn't get to. For instance, Arlin has been a champion of getting All Day functionality working better, and Tim came up with a patch to improve performance when loading a lot of nodes on the same page (which happens in calendars).
The improvements made to Calendar by Andrew Hall (developer-x) are tremendous, and his work is much appreciated.
And of course I want to give a huge shout out to Lullabot for providing flexibility in my schedule and wiggle room room in their expectations about my client load so I had time to work on Date and Calendar. And I want to thank the whole Lullabot team for their support and encouragement when I was feeling discouraged about the whole process.
And there have been many many other people that have supplied and tested patches, debugged problems, and waited patiently until I could get to their issue. Thanks to all of you!