Giter Site home page Giter Site logo

recurrencecalculator's Introduction

Recurrence Calculator

Library written for .NET that perform Outlook style recurrence calculations. The key to usage is the IRecurrence interface that allows you to specify the recurrence pattern.

I have used for the most part the interface that Outlook supports. You can find the details on MSDN site: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.recurrencepattern(v=office.15).aspx I made one change - I changed the DayOfWeekMask from flags based enumeration to just 7 flags - one for each day of the week. This will allow you to easily expose the same class at the user interface to allow the user to set flags for the days of the week. In order to support things like day, week day and weekend, you just set appropriate days flags. For example, set all the flags for the "day", Sunday and Saturday for the "weekend". I also decided not to support "no end date", so date is required or number of occurrences.

It is very easy to use. Implement IRecurrence in any of your class, create an instance of the calculator, and call Calculate method. An exception will be thrown if your pattern is invalid. You can also call Validate manually. If you get an empty string, you are valid. Otherwise you will get the message telling you what is wrong with your pattern.

The project includes tests that will tell you how to use the calculator. There is now support for default recurrence class and recurrence fluent API builder

private Calculator calendarUtility;
private readonly DateTime startDate = new DateTime(2014, 1, 31, 16, 0, 0);

[TestInitialize]
public void Setup()
{
    calendarUtility = new Calculator();
}

private AppointmentRecurrence CreateWeeklyRecurrence()
{
    return new AppointmentRecurrence
    {
        RecurrenceType = RecurrenceType.Weekly,
        Interval = 2,
        Sunday = false,
        Monday = false,
        Tuesday = true,
        Wednesday = false,
        Thursday = true,
        Friday = false,
        Saturday = false,
        StartDate = startDate,
        Occurrences = 5
    };
}

[TestMethod]
public void Should_Generate_Weekly_Recurrences_Without_End_Date()
{
    var recurrence = CreateWeeklyRecurrence();
    var occurrences = calendarUtility.CalculateOccurrences(recurrence).ToList();
    Assert.AreEqual(5, occurrences.Count, "Should create 5 occurrences");
    Assert.AreEqual(new DateTime(2014, 2, 11).Add(startDate.TimeOfDay), occurrences[0], "Date 1 should be correct");
    Assert.AreEqual(new DateTime(2014, 2, 13).Add(startDate.TimeOfDay), occurrences[1], "Date 2 should be correct");
    Assert.AreEqual(new DateTime(2014, 2, 25).Add(startDate.TimeOfDay), occurrences[2], "Date 3 should be correct");
    Assert.AreEqual(new DateTime(2014, 2, 27).Add(startDate.TimeOfDay), occurrences[3], "Date 4 should be correct");
    Assert.AreEqual(new DateTime(2014, 3, 11).Add(startDate.TimeOfDay), occurrences[4], "Date 5 should be correct");
}

You can also use NuGet to install the package: https://www.nuget.org/packages/RecurrenceCalculator/ Just type Install-Package RecurrenceCalculator in package manager console window.

recurrencecalculator's People

Contributors

sergeybarskiy avatar neremin avatar badsyntax avatar

Stargazers

Hervé  avatar Nertil Poci avatar Michael Tanczos avatar Mark Robinson avatar  avatar fikrihakim avatar mahmoudreza naseri avatar Konrad Bartecki avatar Bipin Paul avatar Lukas Läderach avatar  avatar Abdul Mueed Chaudhry avatar Felipe Crochik avatar John Vinis avatar Ganeshan Venkataraman avatar Roger Saladrigas avatar David Terracino avatar Timothy Lee Russell avatar  avatar

Watchers

 avatar  avatar BRTom avatar Dave Brooks avatar

recurrencecalculator's Issues

Should_Generate_Daily_Weekday_Recurrences_With_End_Date incorrect dates

Change the test to have a start date of 2/24/16 and an end date of 3/26/2016, put a break point on
var occurrences = _calendarUtility.CalculateOccurrences(recurrence).ToList();

See that the list of occurrences are not correct.

The interval does not appear to work at all.
You can see the same outcome in this other test as well:
Should_Generate_Daily_Weekday_Recurrences_Without_End_Date()

You could also just change the test to use the year 2016 while leaving the month and day dates alone, you will see there is still a problem with the interval not working.

Have appointment till end of time and to certain date?

Curious If you want it to go to an end date do you just simply remove occurrences below
Some calendar systems allow you do to till forever until the appointment is removed how does this happen.

 private AppointmentRecurrence CreateWeeklyRecurrence()
{
    return new AppointmentRecurrence
   {
    RecurrenceType = RecurrenceType.Weekly,
    Interval = 2,
    Sunday = false,
    Monday = false,
    Tuesday = true,
    Wednesday = false,
    Thursday = true,
    Friday = false,
    Saturday = false,
    StartDate = startDate,
    Occurrences = 5
};

}

And instead do do this

 private AppointmentRecurrence CreateWeeklyRecurrence(DateTime starDate, int interval, RecurrenceType  )
    {
        return new AppointmentRecurrence
        {
            RecurrenceType = RecurrenceType.Monthly,
            Interval = 1,
            Sunday = false,
            Monday = false,
            Tuesday = true,
            Wednesday = false,
            Thursday = true,
            Friday = false,
            Saturday = false,
            StartDate = starDate,
            EndDate = startDate.AddYears(1)
            
        };
    }

How would i also read back the appointments to place into a calendar have you some examples of that

Configurable start of the week

Hi,

I live in the UK and have been using this library to calculate events.

Here in the UK we use the start of the week as Monday. However, I have noticed in your library that for some event date calculations you are using Sunday. This does not match Outlook (when used in the UK with default configuration) recurrence calculations.

Would it be possible to make the start day of the week configurable?

e.g. this is one example of where the start day of the week needs to be configurable.

while (date.DayOfWeek != DayOfWeek.Sunday)

order of date enumeration

Hello this is only question about order of date enumeration.
when ever I generate the recurrences should I order or is it already sorted ASC?
This is not bug. As far as I know Ienumerable does not guarantee to be ordered when I iterate the datas.
If I am wrong please correct me.
Thx in advance. @SergeyBarskiy

Day property in IRecurrence interface

I see the Day property in IRecurrence interface. But this property seems useless. What exactly is your intention with this property. As far as I guess it indicates the appointment is all day event. Right?
If you really don't use why don't you eliminate it?
It has already unclear property definition.

useless

You stated Day of month. You have already one more DayOfMonth.
Sincerely greetings.

Monthly Recurrence Calculation Issue

Hi Sergey,

We have come across an issue in the monthly recurrence calculation.

private IEnumerable<DateTime> GetMonthlyRecurrenceOccurrences(IRecurrence recurrence)
{
DateTime date = recurrence.StartDate.Date;
if (date.Day > recurrence.DayOfMonth)
{
date = date.AddMonths(recurrence.Interval).AddDays(-1 * (date.Day - 1));
}
int occurenceCounter = 0;
while (!GeneratedEnoughOccurrences(occurenceCounter++, date, recurrence))
{
if (date.Day < recurrence.DayOfMonth)
{
date = date.AddDays(((recurrence.DayOfMonth > DateTime.DaysInMonth(date.Year, date.Month))
? DateTime.DaysInMonth(date.Year, date.Month)
: recurrence.DayOfMonth) - date.Day);
}
yield return date.Add(recurrence.StartDate.TimeOfDay);
date = date.AddMonths(recurrence.Interval);
}
}

Explanation of the Issue

Before I explain what the code is doing, I'll give an example of the problem with some data (there is also an incoming PR with a failing test so you can just run it).

Consider we have set the following values on IRecurrence:

recurrence.StartDate = 31/01/2023
interval = 1
recurrence.DayOfMonth = 18
Occurrences = 1

I would expect the following:

When line 141 has executed, date should be equal to 01/02/2023 and when the method GetMonthlyRecurrenceOccurrences has finished, I would expect that we have one date of 18/02/2023.

The date is returned from the method is 29/01/2023.

Why I think it's returning that value.

AddMonths() will pass the result to AddDays() but the expression inside the AddDays() does NOT see that value, it still has a reference to "date" on line 138. The date declared on line 138 does not get updated until the whole line (141) has finished executing, which is too late for your expression. You need the new date.Day from the result of AddMonths().

Steps:

DateTime date = recurrence.StartDate.Date;
if (date.Day > recurrence.DayOfMonth)
{
date = date.AddMonths(recurrence.Interval).AddDays(-1 * (date.Day - 1));
}

  1. AddMonths() evaluates first and changes the date to 28/02/2023, that is passed through to AddDays()
  2. The expression inside AddDays() is evaluated, date.Day inside that expression has not been updated yet so it's still set to 31 (the original reference on line 138), so we take that day value of 31, minus 1 makes it 30 then multiply by -1 makes it -30.
  3. AddDays() evaluates and subtracts -30 from the date (28/02/2023) making it 29/01/2023 which is incorrect.

There is a fix for this, you can either switch the AddDays and AddMonths around so that AddDays(expression) is evaluated first:

date = date.AddDays(-1 * (date.Day - 1)).AddMonths(recurrence.Interval);

This works because the date.Day reference is ok to use at this point because we haven't tried to modify it yet.

Or you can split them onto multiple lines:

date = date.AddMonths(recurrence.Interval);
date = date.AddDays(-1 * (date.Day - 1));

Either of those will produce the correct result.

I will send a PR for this that has a failing test, just to aid communication of the problem and clarify anything above that was unclear.

If you agree that the issue is valid and like one of the suggested fixes above, I can send a second PR with the fix if that would help.

I haven't checked the whole year but I have a feeling it only occurs in Feb because of it being a short month of 28 days.

Kind Regards,
Mark

Setting Days

private AppointmentRecurrence CreateMonthlyRecurrence()
{
return new AppointmentRecurrence
{
RecurrenceType = RecurrenceType.Monthly,
Interval = 3,
DayOfMonth = 31,
Sunday = false,
Monday = false,
Tuesday = true,
Wednesday = false,
Thursday = false,
Friday = false,
Saturday = false,
StartDate = _startDate,
Occurrences = 3
};
}
the day of the date of "2014,1,31" is Friday.
Why did you set only Tuesday?
It is emergency question.
Please let me know..
According to date the Friday should be set.
But Tuesday is set

I think in monthly cases days has no deal. Right?

Index

Hello Dear Sergey,
Nowadays,I am inspecting your package. If your calculator can cover all of my requirements I will be able to use. I have a question. It is about "broken serial appointments".
Consider that the appointments sould be shown everyday but user deleted wednesday of week for only next week. As you know we should not show this appointment for next week on wednesday. We have to ignore this. It is clear.
So Could you think to add ignorance list -should start from 1 because 0 is undefined in time-? in IRecurrence interface.
If you don't even do this I can cover but this is possible situation for all recurrence calculator app. It might be useful for every programmer who will use your package.
If you did not understand of if you have further question please let me know.
Best regards and wishes

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.