Creating outlook style occurrences in Xamarin forms application

I have a set of check boxes represents the days of the week I also have a start date and and end date. I no what I want is like how outlook handles the days in its calendar but am a bit at loss how to calculate it. I was going use this library but its not compatible with Xamarin forms. https://github.com/SergeyBarskiy/RecurrenceCalculator. When I say doesn't work its not been updated in quite some time so incompatible with XF.

The days of week list will have the days as comma sept ie Mon,Tue,Wed but may not have Thur , Fri ,Sunday

I need some way to calculate the dates if worst comes to worst I could do it on the api which is server based. But I would rather do it on the users device.

if (picksessionType.SelectedItem.ToString() == Enums.RepeatOccurance.Daily.ToString())
{
   foreach (var item in daysOfWeekList)
   {
     Session session = new Session();
     session.Name = "\r\n" + txtName.Text + "\r\n" + item.ToString() + "\r\n";
     session.StartDate = txtDateStartEntry.SelectedDate; // I obv need to shift this date to each date in days of week list
     session.EndDate = txtDateEndEntry.SelectedDate;
     session.IsActive = true;
     session.IsDeleted = false;
     await api.AddToSession(session);
  }
 await DisplayAlert(Constants.AppName, "Sessions Created For "+daysOfWeekList.ToString(), "OK");
}

At present in the ui I am doing the following

 <Frame x:Name="daySelector" IsVisible="false">
    <StackLayout Orientation="Horizontal">
      <syncfusion:SfCheckBox  x:Name="daySun" Text="Sun" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
      <syncfusion:SfCheckBox x:Name="dayMon" Text="Mon" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
      <syncfusion:SfCheckBox x:Name="dayTue" Text="Tue" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>

     <syncfusion:SfCheckBox x:Name="dayWed" Text="Wed" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
     <syncfusion:SfCheckBox x:Name="dayThur" Text="Thur" StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
     <syncfusion:SfCheckBox x:Name="dayFri" Text="Fri"  StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
      <syncfusion:SfCheckBox x:Name="daySat" Text="Sat"  StateChanged="SfCheckBox_StateChanged" Visual="Material"></syncfusion:SfCheckBox>
 </StackLayout>
</Frame>

This function could also do with some shocking tidying up if someone new a better way of doing it.

private void SfCheckBox_StateChanged(object sender, StateChangedEventArgs e)
{
    var selectedDay = sender as SfCheckBox;
    daysOfWeekList.Add(selectedDay.Text);

    List<string> distinct = daysOfWeekList.Distinct().ToList();
    if (daySun.IsChecked == false)
        distinct.Remove(daySun.Text);
    if (dayMon.IsChecked == false)
        distinct.Remove(dayMon.Text);
    if (dayTue.IsChecked == false)
       distinct.Remove(dayTue.Text);
    if (dayWed.IsChecked == false)
       distinct.Remove(dayWed.Text);
    if (dayThur.IsChecked == false)
       distinct.Remove(dayThur.Text);
    if (dayFri.IsChecked == false)
       distinct.Remove(dayFri.Text);
    if (daySat.IsChecked == false)
       distinct.Remove(daySat.Text);

       daysOfWeekList = distinct;
    }

Ui Example

enter image description here

So in the UI example you will see I have selected the two dates and then I selected Daily with Mon,Tue,Wed,Thur selected until the end date is hit it should create sessions in the above for loop for each of those days checked.

Thanks in advance

Edit 2

I have tried the code above but cause I picked Friday between these condition its saying their should be 9 sessions created but I figure only 8 should be created as 27th is the cut off but the system is still generating a session for 28th.

Here is a .netFiddle of my example

https://dotnetfiddle.net/N6nkgP

Unit Test

DAY of week enum value https://docs.microsoft.com/en-us/dotnet/api/system.dayofweek?view=net-6.0

using System;
using NUnit.Framework;
using System.Collections.Generic;

namespace TestApp {
public class Program
{
    public static void Main() 
    {
        var x = new NUnitLite.AutoRun().Execute(new string[]{"--test:TestApp.CalculateOccuranceTests", "--noc"});
        Console.WriteLine("");
        Console.WriteLine("----------------------------------------------");
        Console.WriteLine(x==0?"All Test Passed... :¬)": string.Format("{0} tests failed... :¬(", x));
        Console.WriteLine("----------------------------------------------");
    }
}

  
    [TestFixture]
    public class CalculateOccuranceTests
    {
        [TestCase(8,"2022-01-10" ,"2022-01-27",2,3,5 )]
        public void OccuranceTest(int expected,DateTime startDate, DateTime endDate, params int[] numbers)
        {
            //Setup
            List<int> daysofWeek = new List<int>();
            foreach (var item in numbers)
            {
                daysofWeek.Add(item);
                Console.WriteLine("Date Selected "  + item.ToString());
            }
            //act
            var act = CalculateDaysToSessions( startDate, endDate, daysofWeek);
            //Assert
            Assert.AreEqual(expected,act.Count);
        }


        public List<DateTime> CalculateDaysToSessions(DateTime startDate, DateTime enddate, List<int> daysOfWeek)
        {
            List<DateTime> dates = new List<DateTime>();
            DateTime date = new DateTime();
            date = startDate;

            while (date <= enddate)
            {

                if (daysOfWeek.Contains((int)date.DayOfWeek))
                {
                    dates.Add(date);
                    Console.WriteLine("Date Session "  + date.ToString("dd/MM/yyyy"));

                }
                date = date.AddDays(1);

            }
            return dates;

        }

   
}

}

The above outputs

Date Selected 2 =Tuesday    
Date Selected 3 =Wednesday
Date Selected 5 =Friday
Date Session 11/01/2022
Date Session 12/01/2022
Date Session 14/01/2022
Date Session 18/01/2022
Date Session 19/01/2022
Date Session 21/01/2022
Date Session 25/01/2022
Date Session 26/01/2022
Date Session 28/01/2022

When it should not be creating the 28th

What I had to do was this just in the while this is now working as expected.

if (date > enddate) date = date.AddDays(-1);

Edit 3 Jason was correct the date.AddDays had to be at the bottom of the loop no need for the if statement


The algorithm to calculate this should be pretty simple. Just loop between the start and end date, and check each iteration to see if it is one of the user's selected days

// this is pseudo-c# and may need to be cleaned up a bit
List<DaysOfWeek> days = // initialize this based on the user selections
List<DateTime> dates = new List<DateTime>();
var date = StartDate;

while (date <= EndDate)
{
  if (days.Includes(date.DayOfWeek))
  {
    dates.Add(date);
  }

  date = date.AddDays(1);
}