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

Recurring Date Generator with Pattern Coding

By , 4 Sep 2007
 
Screenshot - ScreenShot01.png

Introduction

I needed a way to create recurring dates using a given pattern of dates such as every weekday, every Saturday and Monday, etc. I couldn't find any sample code on the web other than what you can purchase, so I made this library.

This library not only creates recurring dates but it also returns a coded value that you can store to at a later date, create the same recurring date pattern and adjust the values as needed. This ability to alter the pattern or add more dates to the end of the returned values is what I consider to be a real world requirement. Creating recurring dates is not the issue when creating a pattern of dates, it's being able to store that pattern's design value so it can be used to alter the dates at a later date.

Using the coded pattern value, or Series Info as I call it in this article, you can edit appointment dates similar to those found in Microsoft Outlook. When editing an event in Outlook, you're asked if this is for the current date or the entire series. If you don't have the series date format pattern it's impossible to load up the date controls in the correct format so they match what you first used when you created the recurring dates. This library gives you the ability to do this using the Series Info returned value.

Background

I needed a way to create recurring dates and be able to edit them or adjust the values at a later date.

Using the code

You can open the source solution for a complete sample application that uses the RecurrenceGenerator assembly.

The RecurrenceGenerator library exposes Daily, Weekly, Monthly, and Yearly RecurrenceSettings classes that inherit from RecurrenceSettings class. All the classes have the same constructors.

The constructors allow for:

  1. Start Date (No ending date)
  2. Start Date, End Date (defined ending date)
  3. Start Date, Number of Occurrences (create only x-number of dates)

The constructors are constructed in such a way that you have to, at a minimum, give a Start Date.

/// <summary>
/// Get dates by Start date only. This is for no ending date values.
/// </summary>
/// <param name="startDate"></param>
public DailyRecurrenceSettings(DateTime startDate) : base(startDate) { }

/// <summary>
/// Get dates by Start and End date boundaries.
/// </summary>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
public DailyRecurrenceSettings(DateTime startDate, DateTime endDate) : 
         base(startDate, endDate) { }

/// <summary>
/// Get dates by Start date and number of occurrences.
/// </summary>
/// <param name="startDate"></param>
/// <param name="numberOfOccurrences"></param>
public DailyRecurrenceSettings(DateTime startDate, int numberOfOccurrences) : 
         base(startDate, numberOfOccurrences) { }

The dates are returned in an object called RecurrenceValues. This object is returned by making a call to GetValues([various params based on type of RecurrenceSettings]).

Once the dates are returned, you can use them to list the values such as those in the sample application.

Screenshot - ScreenShot02.png

This workspace shows the dates that were generated by the previous tabs date pattern. The "Series Info" readonly text box shows you the return value that you would store with each date event in your application. Storing this value allows you to create the next date in the pattern as well as generate all the values and adjust them as needed.

Screenshot - ScreenShot05.png

This tab of the sample application allows you to adjust the original Series Info value and create a new set of values. This is the real world in that you may need to extend the date values you're looking at in your calendar control. You might also need to show the next date for the month that's being viewed in your UI control in Winforms.

This third tab allows you to adjust:

  • Start Date
  • Number of occurrences
  • End Date
  • View the definition of the Series Info value. See screen below for example.
Screenshot - ScreenShot06.png

Clicking the "Def." button will bring up a viewer to explain what each Series Info value means. The definitions are different for each pattern (daily, weekly, monthly, yearly).

Screenshot - ScreenShot04.png

This tab shows you the object that can be returned by passing in the Series Info into the RecurrenceHelper shared function GetFriendlySeriesInfo(string seriesInfo).

The Series Info value is different for each date pattern type such as daily, weekly, etc. Each RecurrenceSettings class has a method to view the breakdown of the coded value. This is reached by a call to the RecurrenceHelper.GetPatternDefinition(string seriesInfo).

Points of Interest

Making the sample application helped in the testing process of the date generation. Making a prototype was a good tool to ensure that the RecurrenceGenerator library created the correct values.

History

  • 7 September, 2007: Added the ability to return a modified series of dates using an existing Series Info value and modified Start Date

License

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

About the Author

Victor Boba
Software Developer (Senior) BOCA Software Technologies, Inc.
United States United States
Member
.NET Developer in Garner, North Carolina. Specializing in WinForms development in C#, VB.Net.

CEO/Founder BOCA Software Technologies, Inc.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionDoes this project work with web based applicationsmemberochiha_ita19 Oct '12 - 6:16 
Hello there,
i am currently creating a website, will this code work with web applications?
if not, could anyone help me find one.
 
regards,
Questionrecur weekly not workingmemberShivapragasam17 Jun '12 - 19:58 
Hi Victor,
Your date generation class library works fine. But when i schedule a recur every two week or more is working perfectly when I'm not choosing Saturday. If i choose Saturday it generates for every week. Not for recur week. Please reply for this ASAP.
AnswerRe: recur weekly not workingmemberMember 36963833 Aug '12 - 3:28 
This bug occurs because the method GetNextDay() in the WeeklyRecurrenceSettings class increments the date by the recurring week value (regenEveryXWeeks) number of weeks every time the date gets to a Saturday but ONLY when a Saturday isn't one of your selected recurring days. When you've got a Saturday selected as a recurring day, it merely adds the date to the recurring date collection back in the calling method GetEveryXWeeksValues() and incremements the date to the day after.
 
I've fixed this by updating GetNextDay() to first check if the date being passed in to the method is a Saturday and then straight away incremementing it by the recurring week value if and only if we've already saved at least one Saturday to our collection. This is because in the very first week you look at you don't want to increment the date by X weeks until after you've checked (and selected) your first Saturday. To do this I had to create a class level private int "counter" variable which is incremented everytime a Saturday is saved to the recurring date collection.
 
int selectedSaturdayCount = 0;
 
<pre>  DateTime GetNextDay(DateTime input)
        {
            DateTime? returnDate = null;
 
            // Get the return date by incrementing the date
            // and checking the value against the selected days
            // of the week.
            do
            {
                //BUG FIX: 03/08/2012 : A.Powell : Fix issue around recurring Saturdays
                //If we've just finished a single week (ie. last day was a Saturday) 
                //AND are selecting Saturdays then increment the date by Weekly 
                //Occurrence value number of days so that we're looking in the
                //correct next appropriate week ... but MUST ensure that we only do 
                //this after at least one Saturday has been selected ie. we've
                //finished checking the first week, which may be a Partial week
                if (input.DayOfWeek == DayOfWeek.Saturday && selectedSaturdayCount > 0)
                {
                    input = input.AddDays((regenEveryXWeeks - 1) * 7);
                }
                input = input.AddDays(1);
 
                switch (input.DayOfWeek)
                {
                    case DayOfWeek.Monday:
                        if (selectedDays.Monday)
                            returnDate = input;
                        break;
                    case DayOfWeek.Tuesday:
                        if (selectedDays.Tuesday)
                            returnDate = input;
                        break;
                    case DayOfWeek.Wednesday:
                        if (selectedDays.Wednesday)
                            returnDate = input;
                        break;
                    case DayOfWeek.Thursday:
                        if (selectedDays.Thursday)
                            returnDate = input;
                        break;
                    case DayOfWeek.Friday:
                        if (selectedDays.Friday)
                            returnDate = input;
                        break;
                    case DayOfWeek.Saturday:
                        if (selectedDays.Saturday)
                        {
                            returnDate = input;
                            selectedSaturdayCount += 1;
                        }
                        else
                        {
                            // Increment by weeks if regenXWeeks has a value 
                            // greater than 1 which is default.
                            // But only increment if we've gone over
                            // at least 7 days already.
                            if (regenEveryXWeeks > 1)
                                input = input.AddDays((regenEveryXWeeks - 1) * 7);
                        }
                        break;
                    case DayOfWeek.Sunday:
                        if (selectedDays.Sunday)
                            returnDate = input;
                        break;
                }
            } while (!returnDate.HasValue);
            return returnDate.Value;
        }
 

In fact, if you look at Microsoft Outlook (which I believe this is mostly replicating), it appears to use Sunday as the day to increment the weekly recurrence, so you could just update GetNextDay() to carry out the relevant checks on the Sunday rather than the Saturday. I've tested this to some degree by running identical tests creating Recurring Appointments in MS Outlook and this Recurrence Tester front-end and it all seems to match exactly.
GeneralIs there a newer Version which works with EndDateType.NoEndDate ?memberBombias15 Apr '11 - 1:48 
This ist exactly what I need, great work!
But unfortunately it doesn't work with "NoEndDate" (I got Exceptions).
 
Is there a newer Version which is supporting "NoEndDate"?
GeneralDate pattern not working correctly for week daysmembermonisshamsi23 Dec '09 - 23:23 
Hi,
 
Its really helpful.....
 
But there is 1 problem occuring.......
 
Like...As for weekly section i am mentioning that a particular person has to come for 2 weeks on these days i.e (Mon,Tue,Wed,Thu,Fri,Sun) for 5 no. of times(take it as any no.)/(Occurences) then the dates are getting generated correctly in the lstdates by pressing generate dates button but if i am also mentioning Sat along with all these days, then its generating a wrong pattern( like if i am also inputting period more than 1).............
 
One more if i just want a recurring of appointments only on sat,then mentioning the no. of occurences(take any no. like 5) and mentioning the no. on textbox1(like 1) the dates are getting generated ,But soon after these dates get generated,what the problem is comming is that when i again change the textbox1 value to 2, 3 or either any no. ,then its not generating the correct result,its just overriding the previous result....and not showing the correct pattern....
 
Kindly check it out..............ASAP......
If u can resolve this problem just mail me update on my ID i.e monisshamsi2000@gmail.com
 
Thx.....
GeneralRe: Date pattern not working correctly for week daysmemberVictor Boba24 Dec '09 - 3:00 
I submitted this as a one-time example and do not have the time to fix anything that's wrong with it. I know that may sound selfish, but you're more than welcome to try and fix it yourself. You have all the code in the example so go for it.
GeneralRe: Date pattern not working correctly for week daysmembermonisshamsi25 Dec '09 - 19:01 
okk......that i wll try to do it......
 
Can u tell me 1 more thing.........
 
I don't want all those dates to be generated when a doctor is on a leave on that dates.....
 
So, how should i do this.........
GeneralIt's very nice.memberiamnon26 May '09 - 6:32 
I am working with CRM project and looking for this solution. Thank you so much. Wink | ;) Thumbs Up | :thumbsup:
GeneralGood codingmemberTomChris24 Oct '08 - 12:11 
Thanks for your effort here and for sharing. I needed exactly this capability and addapted your code to a web control.
I did add two thing that have made this more useful than it is here currently. 1. I added time to the control so I can recur to specific time. I was surprised you did not have that. 2. I added time zones as well.
For the time I added 4 characters at the end of the pattern with a 24 hour clock concept. And then the time zone as a two position addition. I set the time then on the startdate property when I instanciate your code objects. That way all the return values have the time element on them as your code adds whole days and does not change any existing time.
Happy to share if you wish.
 
I would like to have added the ability to get back the date and time in UTC but we have utility code to do this so I make sure if I'm working with a UTC datetime that I put back to the timezone local time before I call your adjustment code and just modify the return set to UTC before storing.
 
Your coding style and methodolgy I found very solid. Well oranized and broken down very nicely.
GeneralRe: Good codingmemberVictor Boba24 Oct '08 - 12:59 
Thanks for the comments. I'm glad you find it useful.
 
Could you paste your improvements to the pattern definition and usage here so everyone gets the benefits of your improvements, or at minimum send them to me at [victor] [dot] [boba] [at] [boca-software] [dot] [com] and I'll update the article with them.
 
Thanks

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 4 Sep 2007
Article Copyright 2007 by Victor Boba
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid