Search code examples
c#linqc#-4.0linq-to-entities

Get List of 1st and 3rd Saturday of month if 2nd Saturday Appear in first 9 days


I want to get List of all 2nd & 4th Saturdays of an year. But if 2nd Saturday appear in first 9 days of a month then return list of 3rd and 5th Saturday of that month. So far i get list of all 2nd & 4th Saturday of whole year. But I'm not able to get 3rd and 5th Saturday if 2nd Saturday appear in first 9 days of a month.

class Program
{
    static void Main(string[] args)
    {
        List<DateTime> MyCalendar = new List<DateTime>(); //create list
        DateTime currDate = new DateTime(2017, 1, 1); //initial value
        //add days to MyCalendar
        while (currDate <= new DateTime(2017, 12, 31))
        {
            MyCalendar.Add(currDate);
            currDate = currDate.AddDays(1);
        }
        //method to get 2. and 4. saturday in month
        var result = MyCalendar.Where(x => x.DayOfWeek == DayOfWeek.Saturday)
                        .GroupBy(x => x.Month)
                        .SelectMany(grp =>
                            grp.Select((d, counter) => new
                            {
                                Month = grp.Key,
                                PosInMonth = counter + 1,
                                Day = d
                            }))

                        .Where(x => x.PosInMonth == 2 || x.PosInMonth == 4)
                        .ToList();

        foreach (var d in result)
        {
            Console.WriteLine("{0} {1} {2}", d.Month, d.PosInMonth, d.Day);
        }

        Console.Read();

    }

}

Out Put of the Program

Out of Program


Solution

  • Here is a quick and dirty solution; I admit that it could be more optimized.

    Method which will do the lookup:

    private static IEnumerable<DateTime> GetWeekDayOfMonth(DateTime monthToCheck, DayOfWeek weekDayToFind)
    {
        var year = monthToCheck.Year;
        var month = monthToCheck.Month;
        var dayCount = DateTime.DaysInMonth(year, month);
        var daysList = Enumerable.Range(1, dayCount)
                                        .Select(day => new DateTime(year, month, day))
                                        .Where(date => date.DayOfWeek == weekDayToFind)
                                        .ToList<DateTime>();
        // Loop with 2 increment
        int lookupStart = 1;
        int loopCount = 0;
        if (daysList[1].Day <= 9)
        {
            lookupStart = 2;
        }
    
        for (var i = lookupStart; i < daysList.Count(); i = i + 2) 
        {
            if (loopCount < 2)
            {
                yield return daysList[i];
                loopCount++;
            }
        }
    }
    

    Here is the code to call it:

    private static void FindWeekDays()
    {
        DateTime dateToCheck = new DateTime(2017, 1, 1);
        List<DateTime> dayList = new List<DateTime>();
        while (dateToCheck.Year <= 2017)
        {
            dayList.AddRange(GetWeekDayOfMonth(dateToCheck, DayOfWeek.Saturday));
            dateToCheck = dateToCheck.AddMonths(1);
        }
    
        dayList.ForEach(date => Console.WriteLine(date.ToString()));
    }
    

    And the Main:

    static void Main(string[] args)
    {
        FindWeekDays();
    }