Как найти 5-ю или конечную дату определенного дня в месяце на основе даты того же месяца

Я пытался найти дату 5-й недели дня в месяце, например дату понедельника 5-й недели, дату вторника 5-й недели, среду... и т. д., основываясь на дате того же месяца. Эта дата может относиться к любой неделе того же месяца. я пытался как

DateTime MonthEventDate=05/01/2016; //Date format in dd/MM/yyyy format

DayOfWeek EventDay="Sunday"; //For Example i want to find 5th Sunday in January Month, but days too will change everytime based on user selection

string SelectedWeek="5"; //Here i'm getting the week in which i need to find the given date i.e, 5th Monday or Tuesday & so on  
if (SelectedWeek == "5")
{
    //Here i tried to add number of days to my initial day to find 5th day date, but every time its returning next month value 
    MonthEventDate = MonthEventDate.AddDays((EventDay < MonthEventDate.DayOfWeek ? 31 : 28) + EventDay - MonthEventDate.DayOfWeek);
}

Я знаю, что логика неверна, но я хочу получить дату 5-го дня недели, и если этот день отсутствует, вернуть 0. Ищу какое-то руководство. Примечание. Здесь месяц будет меняться в зависимости от ввода пользователя, поэтому как вернуть дату пятого числа, если он существует в данном месяце


person Amar    schedule 23.12.2015    source источник
comment
Вы сейчас ищете пятую неделю или пятый день недели? Я понятия не имею, что вы пытаетесь сделать. Можете ли вы привести несколько примеров? Если вы ищете пятую неделю, что, если в течение месяца пятой недели не будет?   -  person poke    schedule 23.12.2015
comment
Я... Если 5-й недели нет, то верните null или верните дату 5-го дня. Пример: в январе 2016 года у нас есть 5 воскресений, поэтому как найти дату 5-го воскресенья на основе ввода, указанного в вопросе.   -  person Amar    schedule 23.12.2015
comment
Я понедельник или любой день, который повторяется 5 раз в месяц   -  person Amar    schedule 23.12.2015


Ответы (4)


Это должно дать вам 5-й день (если он есть)...

 DateTime dayInMonth = DateTime.Now;
 DayOfWeek dayToFind = DayOfWeek.Friday;

 var fifth= Enumerable.Range(1, DateTime.DaysInMonth(dayInMonth.Year, dayInMonth.Month))
            .Select(day => new DateTime(dayInMonth.Year, dayInMonth.Month, day))
            .Where(day => day.DayOfWeek == dayToFind)
            .Skip(4)
            .FirstOrDefault();
person PaulB    schedule 23.12.2015
comment
Это не совсем ясно, но я думаю, что это ответ, которого хочет ОП. - person Soner Gönül; 23.12.2015

Расширение ответа @Soner Gönül. В поле ввода вы вводите требуемый день недели, требуемый месяц и требуемый год. На выходе вы получаете дату того же дня недели в пятой неделе или null

    public DateTime? FifthDay(DayOfWeek dayOfWeek, byte monthNum, int year)
    {
        if (monthNum > 12 || monthNum < 1)
        {
            throw new Exception("Month value should be between 1 and 12");
        }

        var searchDate = new DateTime(year, monthNum, 1);
        var weekDay = searchDate.DayOfWeek;

        if (weekDay == dayOfWeek)
        {
            searchDate = searchDate.AddDays(28);
        }

        for (DateTime d = searchDate; d < d.AddDays(7); d = d.AddDays(1))
        {
            if (d.DayOfWeek == dayOfWeek)
            {
                searchDate = searchDate.AddDays(28);
                break;
            }
        }

        if (searchDate.Month == monthNum)
            return searchDate;

        return null;
    }
person Mikhail Tulubaev    schedule 23.12.2015

Вы можете использовать простую математику, подобную этой (без проверки)

static DateTime? FindDate(int year, int month, DayOfWeek dayOfWeek, int weekOfMonth = 5)
{
    var baseDate = new DateTime(year, month, 1);
    int firstDateOffset = ((int)dayOfWeek - (int)baseDate.DayOfWeek + 7) % 7;
    var date = baseDate.AddDays(firstDateOffset + 7 * (weekOfMonth - 1));
    return date.Month == month ? date : (DateTime?)null; 
}

Я думаю, что код говорит сам за себя. Единственный трюк, который, вероятно, нуждается в объяснении, это строка

    int firstDateOffset = ((int)dayOfWeek - (int)baseDate.DayOfWeek + 7) % 7;

который обрабатывает случай, когда, скажем, месяц начинается в пятницу, а вы запросили понедельник, и является кратким эквивалентом

int firstDateOffset = (int)dayOfWeek - (int)baseDate.DayOfWeek;
if (firstDateOffset < 0) firstDateOffset += 7;

Использование в вашем примере

var monthEventDate = FindDate(2016, 1, DayOfWeek.Sunday, 5);
person Ivan Stoev    schedule 23.12.2015

Вы можете сослаться на этот демонстрационный код

  int requiredDay = 5; //Day number i.e 0-6(Sunday to SaturDay)
  DateTime day = new DateTime(2016, 1, 1); //Month,year,Date
  if (DateTime.DaysInMonth(day.Year, day.Month) > 28)
  {
      //Get the first day name of the month
       int firstMonthDay = (int)day.DayOfWeek;

       int offset=0;

      //Number of days from the first day for the required day
      if (firstMonthDay <= requiredDay)
          offset = requiredDay - firstMonthDay;
     else
        offset = 7 - firstMonthDay + requiredDay;
//
    DateTime firstoccurence = day.AddDays((double)offset);
    DateTime fifthOccurence = firstoccurence.AddDays(28);
    if (fifthOccurence.Month == firstoccurence.Month)
          MessageBox.Show(fifthOccurence.ToString());
    else
         MessageBox.Show("No 5th Occurence for this day");
   }
person Venkatesh    schedule 23.12.2015