每個月的第幾個星期幾轉DateTime
遊戲可能在每個月的第一、二、三或最後一個週末有分別的活動,
外國的節日也常常是以每個月的第幾個星期幾表示,譬如
母親節(Mother's Day),五月的第二個週日
感恩節(Thanksgiving Day),十一月的最後一個星期四
這裡紀錄如何將指定年月的第幾個星期幾,轉換成一般DateTime表示
/// <summary>
/// 取活動日
/// </summary>
/// <param name="obj">指定年月</param>
/// <param name="dowCount">星期幾計數,大於0正著數,小於0反著數</param>
/// <param name="dow">星期幾</param>
/// <returns></returns>
public static DateTime GetActivityDate(this DateTime obj, in int dowCount, in DayOfWeek dow)
{
if (dowCount > 0)
{
DateTime date = new DateTime(obj.Year, obj.Month, 1).AddDays(-1);
int targetWK = dowCount;
int cnt = 0;
for (int i = 0; i < 31; ++i)
{
date = date.AddDays(1);
if (date.DayOfWeek == dow)
{
++cnt;
if (cnt == targetWK)
{
return date;
}
}
}
}
else if (dowCount < 0)
{
DateTime date = new DateTime(obj.Year, obj.Month, 1).AddMonths(1);
int targetWK = dowCount * -1;
int cnt = 0;
for (int i = 0; i < 31; ++i)
{
date = date.AddDays(-1);
if (date.DayOfWeek == dow)
{
++cnt;
if (cnt == targetWK)
{
return date;
}
}
}
}
return DateTime.MaxValue;
}
單元測試:
//母親節(Mother's Day),五月的第二個週日
new DateTime(DateTime.Today.Year, 5, 1).GetActivityDate(2, DayOfWeek.Sunday).ToString("yyyy/MM/dd")
"2022/05/08"
//陣亡將士紀念日(Memorial Day),五月的最後一個星期一
new DateTime(DateTime.Today.Year, 5, 1).GetActivityDate(-1, DayOfWeek.Monday).ToString("yyyy/MM/dd")
"2022/05/30"
//勞動節(Labor Day),九月的第一個星期一
new DateTime(DateTime.Today.Year, 9, 1).GetActivityDate(1, DayOfWeek.Monday).ToString("yyyy/MM/dd")
"2022/09/05"
//感恩節(Thanksgiving Day),十一月的最後一個星期四
new DateTime(DateTime.Today.Year, 11, 1).GetActivityDate(-1, DayOfWeek.Thursday).ToString("yyyy/MM/dd")
"2022/11/24"
測試正常
另外台指期的結算日常見第三個星期三(月商品結算),第三個星期五(季商品結算),也能用GetActivityDate取DateTime
實務上假日和活動日常常要再輸出到檔案,再經過人為修飾,再讓程式讀取檔案
有些節日很難程式化計算,譬如農民曆,
或西方的復活節(Pascha),每年春分月圓之後第一個星期日