2013 年 6 月 1 日更新
この特定の問題を解決する拡張メソッドを開発し、そのコードを以下に掲載しました。それが誰かを助けることを願っています。
バックグラウンド
私は、定期的な会議を設定できるようにする機能をアプリに追加する任務を負っています (Outlook とまったく同じ方法で)。
たとえば、ユーザーは、毎月第 1 金曜日、毎月最終月曜日、または毎月第 2 平日などに会議を設定することができます。
このための標準アルゴリズムは存在しますか? 私は多くの部分的な答えを見つけましたが、たとえば、次のようなクリーンな拡張メソッドを可能にするものは何もありません:
/// <summary>
/// Accepts a date object and finds the next date given an ordinality and type.
/// </summary>
/// <param name="ordinality">The ordinality (e.g. "first", "second", "last", etc.)</param>
/// <param name="dayType">The day type (e.g. "weekday", "Monday", "day", etc)</param>
/// <returns>A new date object</returns>
public static DateTime GetNextDateOfType(this DateTime date, string ordinality, string dayType)
{
//do stuff
return newDate;
}
私はこれに順調に取り組んできましたが、何かがすでにそこにあるに違いないと考え続けています。
私がこれまでに持っているもの:
public static DateTime GetNextDateOfType(this DateTime date, string ordinality, string dayType)
{
var dateTest = new DateTime(date.Year, date.Month, 1);
var dateFound = false;
var ordinal = 1;
var targetOrdinal = ordinality.ToOrdinal();
while (!dateFound)
{
//Test for type:
switch (dayType)
{
case "day":
if (dateTest >= date)
{
if (ordinality == "last" && dateTest == dateTest.GetLastDayOfMonth() || dateTest.Day == targetOrdinal)
{
dateFound = true;
}
}
break;
case "weekday":
if (dateTest >= date && dateTest.IsWeekDay())
{
if (targetOrdinal == ordinal)
{
dateFound = true;
}
ordinal++;
}
break;
case "weekend day":
if (dateTest >= date && !dateTest.IsWeekDay())
{
dateFound = true;
}
break;
default:
if (dateTest >= date && dateTest.DayOfWeek == HelperMethods.GetDayOfWeekFromString(dayType))
{
dateFound = true;
}
break;
}
dateTest = dateTest.AddDays(1);
}
return dateTest;
}
public static DateTime GetLastDayOfMonth(this DateTime date)
{
return new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
}
public static int ToOrdinal(this string ordinal)
{
var result = 0;
switch (ordinal.ToLower())
{
case "first":
result = 1;
break;
case "second":
result = 2;
break;
case "third":
result = 3;
break;
case "fourth":
result = 4;
break;
case "fifth":
result = 5;
break;
default:
result = -1;
break;
}
return result;
}
public static bool IsWeekDay(this DateTime date)
{
var weekdays = new List<DayOfWeek>
{
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday
};
return weekdays.Contains(date.DayOfWeek);
}
public static List<DateTime> GetWeeks(this DateTime month, DayOfWeek startOfWeek)
{
var firstOfMonth = new DateTime(month.Year, month.Month, 1);
var daysToAdd = ((Int32)startOfWeek - (Int32)month.DayOfWeek) % 7;
var firstStartOfWeek = firstOfMonth.AddDays(daysToAdd);
var current = firstStartOfWeek;
var weeks = new List<DateTime>();
while (current.Month == month.Month)
{
weeks.Add(current);
current = current.AddDays(7);
}
return weeks;
}
public static int GetWeekOfMonth(this DateTime date)
{
var beginningOfMonth = new DateTime(date.Year, date.Month, 1);
while (date.Date.AddDays(1).DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
date = date.AddDays(1);
return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + 1;
}