public static DateTime GetAnnDate(DateTime curDate, int freqencyType, int day, int month, int countTimes)
{
int n = 0;
int absTimes = Math.Abs(countTimes);
int sign = countTimes > 0 ? 1 : -1;
//Daily
if (freqencyType == (int)FreqencyType.Daily)
{
return curDate.AddDays(countTimes);
}
//Weekly
else if (freqencyType == (int)FreqencyType.Weekly)
{
DateTime nextdate = curDate;
int dayOfWeek = day % 7;
int curDayofWeek = (int)nextdate.DayOfWeek;
// get first date
int offDays = (dayOfWeek - curDayofWeek) * sign;
if (offDays < 0)
{
offDays = 7 + offDays;
}
nextdate = nextdate.AddDays(Math.Abs(offDays) * sign);
while (n < absTimes - 1)
{
nextdate = nextdate.AddDays(sign * 7);
n++;
}
return nextdate;
}
//Monthly、Quarterly、SemiAnnual、Annual
else if (freqencyType == (int)FreqencyType.Monthly
||
freqencyType == (int)FreqencyType.Quarterly
||
freqencyType == (int)FreqencyType.SemiAnnual
||
freqencyType == (int)FreqencyType.Annual
)
{
int nNumOfMonth = 0;
if (freqencyType == (int)FreqencyType.Monthly)
{
nNumOfMonth = 1;
month = curDate.Month;
}
else if (freqencyType == (int)FreqencyType.Quarterly)
nNumOfMonth = 3;
else if (freqencyType == (int)FreqencyType.SemiAnnual)
nNumOfMonth = 6;
else if (freqencyType == (int)FreqencyType.Annual)
nNumOfMonth = 12;
// make date in the same year
int nDayInMonth = DateTime.DaysInMonth(curDate.Year, month);
nDayInMonth = Math.Min(day, nDayInMonth);
DateTime targetDate = new DateTime(curDate.Year, month, nDayInMonth);
// 後ろ或は前へ目標日付を探すか。 (sign:1 前へ) (sing:-1 後ろへ)
sign = (curDate - targetDate).Days > 0 ? 1 : -1;
DateTime prevDate = targetDate;
// 二つ日付の前後関係が反転するまで、処理を行う
// 下記の処理に 基準日を挟む 前後二つの日付を探し出す。
while ((curDate - targetDate).Days * sign > 0)
{
prevDate = targetDate;
targetDate = targetDate.AddMonths(sign * nNumOfMonth);
// 日数の調整
nDayInMonth = DateTime.DaysInMonth(targetDate.Year, targetDate.Month);
nDayInMonth = Math.Min(day, nDayInMonth);
targetDate = new DateTime(targetDate.Year, targetDate.Month, nDayInMonth);
}
if (targetDate == curDate || prevDate == curDate)
{
//
targetDate = curDate;
}
else
{
// countTimesの符号によって、前後の二つの日付から条件を満たす日付を選択する
targetDate = sign * countTimes > 0 ? targetDate : prevDate;
}
sign = countTimes > 0 ? 1 : -1;
while (n < absTimes - 1)
{
targetDate = targetDate.AddMonths(sign * nNumOfMonth);
// 日数の調整
nDayInMonth = DateTime.DaysInMonth(targetDate.Year, targetDate.Month);
nDayInMonth = Math.Min(day, nDayInMonth);
targetDate = new DateTime(targetDate.Year, targetDate.Month, nDayInMonth);
n++;
}
return targetDate;
}
else
{
throw new Exception("Invalid parameterin in GetAnnDate");
}
}
test data and test result
//weekly
DateTime datetimeWeekly1 = GetAnnDate(DateTime.Now, 4, 3, 0, 2); //2012.8.22
DateTime datetimeWeekly2 = GetAnnDate(DateTime.Now.AddDays(4), 4, 2, 0, 2); //2012.8.28
DateTime datetimeWeekly3 = GetAnnDate(DateTime.Now, 4, 3, 0, -2); //2012.8.1
DateTime datetimeWeekly4 = GetAnnDate(DateTime.Now.AddDays(4), 4, 2, 0, -2);//2012.8.7
//Month
DateTime datetimeMonthly1 = GetAnnDate(DateTime.Now, 3, 22, 9, 2); //2012.9.22
DateTime datetimeMonthly2 = GetAnnDate(DateTime.Now, 3, 8, 5, 2); //2012.10.8
DateTime datetimeMonthly3 = GetAnnDate(DateTime.Now, 3, 22, 9, -2); //2012.6.22
DateTime datetimeMonthly4 = GetAnnDate(DateTime.Now, 3, 8, 5, -2); //2012.7.8
//Quarterly
DateTime datetimeMonthly11 = GetAnnDate(DateTime.Now, 2, 22, 9, 2); //2012.12.22
DateTime datetimeMonthly12 = GetAnnDate(DateTime.Now, 2, 8, 1, 2); //2013.1.8
DateTime datetimeMonthly13 = GetAnnDate(DateTime.Now, 2, 22, 1, -2); //2012.4.22
DateTime datetimeMonthly14 = GetAnnDate(DateTime.Now, 2, 31, 8, -2); //2012.2.29
//SemiAnnual
DateTime datetimeMonthly21 = GetAnnDate(DateTime.Now, 1, 22, 1, 2); //2013.7.22
DateTime datetimeMonthly22 = GetAnnDate(DateTime.Now, 1, 8, 8, 2); //2013.8.8
DateTime datetimeMonthly23 = GetAnnDate(DateTime.Now, 1, 22, 1, -2); //2012.1.22
DateTime datetimeMonthly24 = GetAnnDate(DateTime.Now, 1, 8, 9, -2); //2011.9.8
//Annual
DateTime datetimeMonthly31 = GetAnnDate(DateTime.Now, 0, 22, 8, 2); //2013.8.22
DateTime datetimeMonthly32 = GetAnnDate(DateTime.Now, 0, 8, 8, 2); //2014.8.8
DateTime datetimeMonthly33 = GetAnnDate(DateTime.Now, 0, 22, 9, -2); //2010.9.22
DateTime datetimeMonthly34 = GetAnnDate(DateTime.Now, 0, 31, 10, -2); //2010.10.31
DateTime datetime1 = new DateTime(2012, 1, 31);
DateTime datetimeMonthly41 = GetAnnDate(datetime1, 4, 5, 0, 1); //2012/2/3
DateTime datetime2 = new DateTime(2012, 1, 31);
DateTime datetimeMonthly42 = GetAnnDate(datetime2, 3, 31, 0, 1); //2012/1/31
DateTime datetime3 = new DateTime(2012, 2, 29);
DateTime datetimeMonthly43 = GetAnnDate(datetime3, 3, 31, 0, 1); //2012/2/29
DateTime datetime4 = new DateTime(2012, 2, 29);
DateTime datetimeMonthly44 = GetAnnDate(datetime4, 2, 30, 5, -1); //2012/2/29
DateTime datetime5 = new DateTime(2012, 2, 29);
DateTime datetimeMonthly45 = GetAnnDate(datetime5, 2, 31, 5, 1); //2012/2/29
DateTime datetime6 = new DateTime(2012, 8, 31);
DateTime datetimeMonthly46 = GetAnnDate(datetime6, 1, 31, 8, 2); //2013/2/28