2011-09-13 6 views
2

私はthis questionを見ました。特定の月のN番目の曜日を探しますが、その月のN番目の[平日のリスト]を検索するものが必要です。月に毎日繰り返すことなく簡単に入手できますか?月にn番目のリスト<WeekDay>があるかどうかを確認する方法はありますか?

たとえば、月に3rd [Mon, Wed, Fri]とし、水曜日に月が始まるとすると、第1月曜日(1 =水曜日、2 =金曜日、3月=月)が返されます。私が2nd last [Mon, Tue, Wed, Thurs]が欲しいと言ったら、その月の最後の日は日曜日です、それは前の水曜日を返すべきです。

+0

興味深い質問です。 –

答えて

3

私は、数式ベースでループを避けることのできない醜い理解できないことを思いつくことができるかもしれないが、バグが発生しやすくメンテナンスの災難ではありません。思いついてみてください。

代わりに、単にLINQを使用して非表示ループループを使用して書きやすいです何を思い付くし、その後

static class DateTimeExtensions { 
    private static IEnumerable<DateTime> DaysOfMonth(int year, int month) { 
     return Enumerable.Range(1, DateTime.DaysInMonth(year, month)) 
         .Select(day => new DateTime(year, month, day)); 
    } 

    public static DateTime NthDayOfMonthFrom(
     this HashSet<DayOfWeek> daysOfWeek, 
     int year, 
     int month, 
     int nth 
    ) { 
     return 
      DateTimeExtensions.DaysOfMonth(year, month) 
           .Where(
            date => daysOfWeek.Contains(date.DayOfWeek) 
          ) 
           .Skip(nth - 1) 
           .First(); 
    } 
} 

使用方法:同様

var daysOfWeek = new HashSet<DayOfWeek> { 
    DayOfWeek.Monday, DayOfWeek.Wednesday, DayOfWeek.Friday 
}; 
DateTime date = daysOfWeek.NthDayOfMonthFrom(2011, 6, 3)); 
Assert.Equal(date, new DateTime(2011, 6, 6)); 

Reverseを使用して、あなたは簡単にNthLastDayOfWeekFromと書くことができます。私はあなたに良い名前を思いつくためにそれを残すでしょう。

+0

すてきで簡単な解決法をお寄せいただきありがとうございます。私の状況でうまく動作するので、あなたの答えを受け入れるだけでなく、ループを使用しないので、私がまとめたコードを投稿します。まだ磨かれている必要があります – Rachel

0

私は彼の解決策が好きなので私はジェイソンの答えを受け入れていると思うが、私は彼のポストを見る前に思いついたことだ。私はすべての日付を徹底的にループしないという考えが好きで、特にNが高い価値があり、今月の外に日付を取得したいと思っているので、私は投稿したいと思った。

すべての日をループするのではなく、最も近い週に早送り(または逆戻りする場合は巻き戻し)し、平日のN番目のインスタンスを見つけるために次の数日間繰り返します。

public static DateTime? GetNthWeekDayInMonth(DateTime month, int nth, List<DayOfWeek> weekdays) 
{ 
    var multiplier = (nth < 0 ? -1 : 1); 
    var day = new DateTime(month.Year, month.Month, 1); 

    // If we're looking backwards, start at end of month 
    if (multiplier == -1) day = day.AddMonths(1).AddDays(-1); 

    var dayCount = weekdays.Count; 

    if (dayCount == 0) 
     return null; 

    // Fast forward (or rewind) a few days to appropriate week 
    var weeks = ((nth - (1 * multiplier))/dayCount); 
    day = day.AddDays(weeks * 7); 

    // Current Nth value 
    var currentNth = (1 * multiplier) + (weeks * dayCount); 

    // Loop through next week looking for Nth value 
    for (var x = 0; x <= 7; x++) 
    { 
     if (weekdays.Contains(day.DayOfWeek)) 
     { 
      if (currentNth == nth) 
      { 
       // Verify the nth instance is still in the current month 
       if (day.Month == month.Month) 
        return day; 
       else 
        return null; 
      } 

      currentNth += multiplier; 
     } 

     day = day.AddDays(multiplier); 
    } 

    return null; 

} 
関連する問題