Click here to Skip to main content
Click here to Skip to main content

MS Outlook-style Date Recurrence Patterns

, 22 Apr 2002
Rate this:
Please Sign up or sign in to vote.
Date recurrence patterns engine with a UI similar to MS Outlook
<!-- Download Links -->

Screen Shots

Sample Image

Sample Image

<!-- Add the rest of your HTML here -->

Acknowledgements

Thanks to Keith Rule for his MemDC class. Thanks to all the CPians who offered feedback and code for the DateEdit and MiniCalendar projects I posted earlier.

About date recurrence patterns

Many applications require the ability to schedule appointments, workshops or applications, etc. The ability to schedule these items in a recurrence pattern is a must when there is more than a few dates involved.

I have looked for source code to do this but I was not pleased with what I found. There are numerous solutions available (search Google), but the ones I looked at were either not worth the money asked, not written well, did not work correctly or were too limited.

The biggest technical issue with date recurrence patterns is that there is any number of possible patterns which each need to be programmed separately. Most recurrence pattern code (including my own) chooses a set of the most commonly used patterns and provides support for these. Also, they rarely provide support for combining various patterns into one (ie. Occurs on first, third and last Friday of each month). My implementation is based on MS Outlook and includes support for the 7 patterns in MS Outlook. Also, my implementation does not include support for combining patterns.

Technical problems aside, events rarely occur exactly along a specific defined pattern. There are often situations where an event is schedule for Friday, but is reschedule for Thursday. Also, holidays, vacation and other events interfere with and modify the timing of these events. The users I have worked with avoid using the MS Outlook recurrence patterns for precisely this reason. Instead, they schedule individual appointments for the various dates involved. This is often a tedious process and in some cases highly error prone.

About this implementation

As mentioned above I based my implementation on MS Outlook. The way I approached this project was to provide the same level of support as MS Outlook as a basis for getting started. I then reviewed the various enhancements that would benefit the users.

I researched the ability to combine date patterns and the problem with this is not a technical one, but rather a question of user interface and usability. How would the UI need to look and work? Would the average user be able to understand it? Would I need to provide a secondary UI for advanced mode? If someone sets up a combined pattern would others be able to understand it? I decided not to implement combing support because I was unable to adequately answer these questions. The engine which I developed should be able to easily accommodate combining, though assuming I (or anyone else) can satisfactorily answer these questions.

The next enhancement I reviewed was implementing support for skip patterns within the main recurrence pattern. Skip patterns would allow for special dates (ie. Holidays, vacations, etc.) to be automatically removed from the resulting pattern and an appropriate date automatically added into the pattern. An example of this would be "Skip Christmas and reschedule for the following Monday". I have implemented support in the core engine for this feature. However, I have not developed the UI to go with this as it was a low priority (per my users.) I plan to add this in a later release.

I also reviewed giving the user finite control over the dates included in the pattern. This would allow the user to remove a specific date from the pattern and add specific dates back into the pattern. After working with my users I felt that this was the most important ability to provide. My implementation includes support for this and the UI provides a simple means for the user to control the pattern.

Implementation overview

The CFPSRecurringDates class provides the core date pattern generator support. This is a utility class with no direct UI. Methods are provided for accessing the details of the pattern and modifying it. This class exposes a Serialize function so that it can be easily incorporated into many projects. (You may need to implement support for persisting the configuration data to a database, though.)

The CPrShtDateRecur, CPrPgDateRecurBasic, and CPrPgDateRecurPreview classes provide a user interface for manipulating the pattern engine. These classes require the IDD_DATE_RECUR_BASIC, IDD_DATE_RECUR_PREVIEW, and IDB_RECUR_IMAGES resource objects.

Also, I use a mini calendar control and date edit/picker control I developed earlier. These projects are available from Code Project at http://www.codeproject.com/miscctrl/MiniCalendar.asp and http://www.codeproject.com/editctrl/dateparser.asp.

Getting started

To include support for recurring dates in your project:

  1. Copy the .cpp and .h files listed below and include them in your project.

    FPSDatePickerCtrl.h
    FPSDatePickerCtrl.cpp
    FPSDateTimeButtonCtrl.h
    FPSDateTimeButtonCtrl.cpp
    FPSDateTimeCtrl.h
    FPSDateTimeCtrl.cpp
    FPSDateTimePopupCtrl.h
    FPSDateTimePopupCtrl.cpp
    FPSMiniCalendarCtrl.h
    FPSMiniCalendarCtrl.cpp
    FPSMiniCalendarListCtrl.h
    FPSMiniCalendarListCtrl.cpp
    FPSRecurringDates.h
    FPSRecurringDates.cpp
    MemDC.h
    OleDateTimeEx.h
    OleDateTimeEx.cpp
    PrPgDateRecurPreview.h
    PrPgDateRecurPreview.cpp
    PrShtDateRecur.h
    PrShtDateRecur.cpp
    PrShtDateRecurBasic.h
    PrShtDateRecurBasic.cpp
  2. Copy the IDD_DATE_RECUR_BASIC, IDD_DATE_RECUR_PREVIEW, IDB_RECUR_IMAGE and IDB_DATEPICKER_BUTTON resources from the DateRecur.rc file (in the demo project) into your project.

Implementation Details

CFPSRecurringDates

Core date recurrence engine.

IMPORTANT METHODS:

GeneratePattern(CPtrList& List) Call this function to execute the recurrence pattern and retrieve the result set.
If the date pattern is configured for NO end, this function will only generate the first 31 occurrences within the pattern. You will need to use one of the other GeneratePattern functions if this is not adequate.
GeneratePattern(CPtrList& List, COleDateTime& dtEndBy) Call this function to execute the recurrence pattern and retrieve the result set up-to a cut off date specified by the dtEndBy parameter.
GeneratePattern(CPtrList& List, int iMaxOccurences) Call this function to execute the recurrence pattern and retrieve the result set up-to a cut off # of occurrences.
CleanupDateList(CPtrList &List) The GeneratePattern function takes a CPtrList& parameter which it populates with pointers to COleDateTime objects. It is necessary to cleanup this list before the list is deconstructed.
IsDateInPattern(COleDateTime& dtCheck) Call this function to determine if the specified date exists in the pattern.
This version of the function is provided for low-volume checks (ie. once or twice) but should not be used within a loop as it can be quite slow since it must regenerate the pattern on each call.
IsDateInPattern(CPtrList& List, COleDateTime &dtCheck) Call this function to determine if the specified date exists in the pattern previously generated and stored in List.
This version of the function is preferred for performance over the previous version.

Ongoing development

This project is still under development, however the code posted here has been tested and functions correctly to the best of my knowledge.

I am currently working on implementing support for skip patterns into the UI. Also, I have wrapped the core engine into a COM component and added support for database persistence. This work is being done to implement an ASP (and hopefully an ASP.NET) version of the UI. When I have completed the ASP (ASP.NET?) version of the project I will post it to Code Project.

I am also working with the users of this component to determine what other features/enhancements need to be made. I do not know what this will reveal, but if there are significant changes I will post them to Code Project.

Notes

You are free to use this code in your own projects both personal and professional. It can be used in freeware, shareware or commercial software without a license fee, etc. This code is provided AS-IS and may cause the universe to implode so use with care. I assume no liability for the results of this implosion. All I ask is that you include my name in the credits for your app and that you leave the header comments intact within the source code.

Change history

April 20, 2002 Thanks to Neville Franks for identifying an issue with how numeric values were being entered.
Also, thanks to Martin Bohring for pointing out some localization issues.

  • Modified basic config dialog to filter input for numeric fields. This prevented a message box from being displayed due to DDX_ functions mapping to an integer.
  • Modified CFPSDateTimeCtrl to automatically set date format based on regional settings in Control Panel.
  • Added functions to COleDateTimeEx function to retrieve the date/time formats set in regional settings in Control Panel and convert values to C style ones.
  • Modified method used to populate start/end time combo boxes to use the appropriate time format as set in Control Panel.
April 22, 2002 Thanks to Michael A. Barnhart for suggesting a new monthly-type pattern.

  • Added a new month pattern option. This option allows for [First|Second|Third|Fourth|Last] [Day|Weekday|Weekend day|Sunday|etc] of Every X months [plus|minus] X days
April 23, 2002 Thanks to Michael A. Barnhart for identifying a bug involving duplicate entries in 2 combo boxes.
Thanks to Kwakkie for identifying a problem in the yearly pattern due to a localization issue (my laziness). Also, time combo boxes not populated correctly (again localization issue) and unable to use numeric keypad for numeric  fields.
  • Corrected problem w/duplicate entries in 2 combo boxes
  • Corrected problem w/yearly pattern caused by using ParseDateTime instead of SetDate.
  • Corrected problem w/time combo boxes caused by incorrect functionality in the ConvertVBFormatToCFormat function.
  • Corrected problem w/numeric fields not allowing numeric keypad entry.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Matt Gullett
Web Developer
United States United States
No Biography provided

Comments and Discussions

 
QuestionDate Recurence pattern code in .Net Pinmemberkavitharani18-Jul-11 1:49 
GeneralC# Version Pinmemberhmelende6-Jul-10 11:37 
QuestionHow to get occurrence count when end type is end by date? Pinmembermanish.patel27-Dec-08 3:35 
QuestionASP.net version? Pinmembermbruyns19-Sep-07 23:55 
GeneralCompile errors with the demo Pinmemberchicken_feet13-Dec-06 11:48 
GeneralRe: Compile errors with the demo Pinmemberchicken_feet18-Dec-06 7:17 
GeneralRecurrence .NET - A .NET 2.0 Recurrence Control with GUI PinmemberMcByte8-Nov-05 6:27 
NewsSource code released PinmemberMcByte7-Feb-06 4:25 
News.Net Version PinmemberTBunce28-Oct-05 18:23 
QuestionRe: .Net Version Pinmembersdekel1-Nov-05 16:04 
AnswerRe: .Net Version PinmemberTBunce2-Nov-05 10:04 
GeneralRe: .Net Version Pinmembersdekel2-Nov-05 12:12 
GeneralRe: .Net Version Pinmembergkurtz15-Dec-05 9:55 
GeneralRe: .Net Version PinmemberTBunce15-Dec-05 10:03 
QuestionRe: .Net Version PinmemberCOA_THE_BESTE24-Jan-06 22:46 
QuestionWork with Visual Basic 6.0 Pinmembersdekel11-Oct-05 5:45 
GeneralConversion to .NET Pinmembermparter30-Mar-05 1:30 
QuestioniCalendar output? Pinmemberterriblecow27-Jan-05 13:48 
GeneralUsage in VB.NET PinmemberDesneux M10-May-04 4:06 
QuestionDatabase structure example ? Pinmembersteve bp31-Mar-04 15:19 
AnswerRe: Database structure example ? Pinmemberchicken_feet18-Dec-06 7:20 
AnswerRe: Database structure example ? Pinmembersambs6526-Sep-07 3:24 
QuestionAre you still persuing com object version? PinmemberBarrySumpter12-Sep-03 17:38 
AnswerRe: Are you still persuing com object version? PinmemberMatt Gullett26-Sep-03 15:06 
GeneralWow! PinsussMatt Schultz2-Sep-03 17:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140821.2 | Last Updated 23 Apr 2002
Article Copyright 2002 by Matt Gullett
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid