Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / MFC

MS Outlook-style Date Recurrence Patterns

Rate me:
Please Sign up or sign in to vote.
4.93/5 (20 votes)
22 Apr 2002CPOL8 min read 325.7K   4.8K   113   66
Date recurrence patterns engine with a UI similar to MS Outlook

Sample Image

Sample Image

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 are 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 are 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 (i.e., 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 (i.e., 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 here and here.

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 (i.e., 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)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionDate Recurence pattern code in .Net Pin
kavitharani18-Jul-11 1:49
kavitharani18-Jul-11 1:49 
GeneralC# Version Pin
hmelende6-Jul-10 11:37
hmelende6-Jul-10 11:37 
QuestionHow to get occurrence count when end type is end by date? Pin
manish.patel27-Dec-08 3:35
manish.patel27-Dec-08 3:35 
QuestionASP.net version? Pin
mbruyns19-Sep-07 23:55
mbruyns19-Sep-07 23:55 
GeneralCompile errors with the demo Pin
chicken_feet13-Dec-06 11:48
chicken_feet13-Dec-06 11:48 
GeneralRe: Compile errors with the demo Pin
chicken_feet18-Dec-06 7:17
chicken_feet18-Dec-06 7:17 
GeneralRecurrence .NET - A .NET 2.0 Recurrence Control with GUI Pin
McByte8-Nov-05 6:27
McByte8-Nov-05 6:27 
NewsSource code released Pin
McByte7-Feb-06 4:25
McByte7-Feb-06 4:25 
News.Net Version Pin
TBunce28-Oct-05 18:23
TBunce28-Oct-05 18:23 
QuestionRe: .Net Version Pin
sdekel1-Nov-05 16:04
sdekel1-Nov-05 16:04 
AnswerRe: .Net Version Pin
TBunce2-Nov-05 10:04
TBunce2-Nov-05 10:04 
GeneralRe: .Net Version Pin
sdekel2-Nov-05 12:12
sdekel2-Nov-05 12:12 
GeneralRe: .Net Version Pin
gkurtz15-Dec-05 9:55
gkurtz15-Dec-05 9:55 
GeneralRe: .Net Version Pin
TBunce15-Dec-05 10:03
TBunce15-Dec-05 10:03 
QuestionRe: .Net Version Pin
COA_THE_BESTE24-Jan-06 22:46
COA_THE_BESTE24-Jan-06 22:46 
QuestionWork with Visual Basic 6.0 Pin
sdekel11-Oct-05 5:45
sdekel11-Oct-05 5:45 
GeneralConversion to .NET Pin
mparter30-Mar-05 1:30
mparter30-Mar-05 1:30 
QuestioniCalendar output? Pin
terriblecow27-Jan-05 13:48
terriblecow27-Jan-05 13:48 
GeneralUsage in VB.NET Pin
Desneux M10-May-04 4:06
Desneux M10-May-04 4:06 
QuestionDatabase structure example ? Pin
steve bp31-Mar-04 15:19
steve bp31-Mar-04 15:19 
AnswerRe: Database structure example ? Pin
chicken_feet18-Dec-06 7:20
chicken_feet18-Dec-06 7:20 
AnswerRe: Database structure example ? Pin
sambs6526-Sep-07 3:24
sambs6526-Sep-07 3:24 
QuestionAre you still persuing com object version? Pin
BarrySumpter12-Sep-03 17:38
BarrySumpter12-Sep-03 17:38 
AnswerRe: Are you still persuing com object version? Pin
Matt Gullett26-Sep-03 15:06
Matt Gullett26-Sep-03 15:06 
GeneralWow! Pin
Matt Schultz2-Sep-03 17:16
Matt Schultz2-Sep-03 17:16 
Matt,

I found your project through a Google search as I was looking for ways to implement a recurrence pattern for a web-based calendar system I'm building in ColdFusion for my church (both internally and on the public web site). I must say, I am very impressed! Cool | :cool:

I would be interested in the COM object you mentioned you're developing, since (I think) that would allow ColdFusion to easily access the algorithm for generating the recurrence dates. I'd be willing to test it, as well, if that would help. Web app development is my strong suit (I never was that great with C and C++), but I'd certainly be willing to be a test bed.

Anyway, keep up the good work!

Thanks,
Matt

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

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