我需要创建一个函数来返回给定项目的下一个处理日期。一个项目的数字代表处理它的一个季度内的月份,以及代表处理该月份的那个星期的数字。因此,给定特定项目的创建日期,我需要获得该项目的下一个处理日期,这将是它在一个季度内分配的周和月的第一天。
请注意,无论一周中的哪一天,周数都会从月初开始算起7天。因此,为了进行此计算,第一周的第一天可以在星期二或任何其他日期开始。
例:
假设我有一个完成日期为2010年8月1日的项目。该项的monthWithinQuarter值为2.它的weekWithinMonth值为3.因此对于此项解析为2月的第3周,所以我希望函数返回2/15/2010的日期。
该功能应如下所示:
var nextProcessingDate = GetNextProcessingDate(
itemCompletedDate,
monthWithinQuarter,
weekWithinMonth);
这个计算必须非常快,因为这个计算将会发生很多,既可以在网站上实时显示,也可以在处理项目时以批处理模式显示。
谢谢,
~Justin
答案 0 :(得分:1)
好的,这应该适合你:
static DateTime GetNextProcessingDate(
DateTime itemCompletedDate,
int monthWithinQuarter,
int weekWithinMonth
) {
if (monthWithinQuarter < 1 || monthWithinQuarter > 3) {
throw new ArgumentOutOfRangeException("monthWithinQuarter");
}
if (weekWithinMonth < 1 || weekWithinMonth > 5) {
throw new ArgumentOutOfRangeException("weekWithinMonth");
}
int year = itemCompletedDate.Year;
DateTime[] startOfQuarters = new[] {
new DateTime(year, 1, 1),
new DateTime(year, 4, 1),
new DateTime(year, 7, 1),
new DateTime(year, 10, 1)
};
DateTime startOfQuarter = startOfQuarters.Where(d => d <= itemCompletedDate)
.OrderBy(d => d)
.Last();
int month = startOfQuarter.Month + monthWithinQuarter - 1;
int day = (weekWithinMonth - 1) * 7 + 1;
if (day > DateTime.DaysInMonth(year, month)) {
throw new ArgumentOutOfRangeException("weekWithinMonth");
}
DateTime candidate = new DateTime(year, month, day);
if (candidate < itemCompletedDate) {
month += 3;
if(month > 12) {
year++;
month -= 12;
}
}
return new DateTime(year, month, day);
}
就效率而言,我认为最有改进空间的地方是反复创建阵列
DateTime[] startOfQuarters = new[] {
new DateTime(year, 1, 1),
new DateTime(year, 4, 1),
new DateTime(year, 7, 1),
new DateTime(year, 10, 1)
};
所以让我们把它卸载到一个方法并记住它:
static Dictionary<int, DateTime[]> cache = new Dictionary<int, DateTime[]>();
public static DateTime[] StartOfQuarters(DateTime date) {
int year = date.Year;
DateTime[] startOfQuarters;
if(!cache.TryGetValue(year, out startOfQuarters)) {
startOfQuarters = new[] {
new DateTime(year, 1, 1),
new DateTime(year, 4, 1),
new DateTime(year, 7, 1),
new DateTime(year, 10, 1)
};
cache.Add(year, startOfQuarters);
}
return startOfQuarters;
}
如果您不需要可能在不寻常的日子开始的季度灵活性,您可以替换
DateTime[] startOfQuarters = new[] {
new DateTime(year, 1, 1),
new DateTime(year, 4, 1),
new DateTime(year, 7, 1),
new DateTime(year, 10, 1)
};
DateTime startOfQuarter = startOfQuarters.Where(d => d <= itemCompletedDate).OrderBy(d => d).Last();
int month = startOfQuarter.Month + monthWithinQuarter - 1;
与
int month = 3 * ((itemCompletedDate.Month - 1) / 3) + monthWithinQuarter;
答案 1 :(得分:-1)
根据我的理解,这应该做的工作:
public static DateTime GetNextProcessingDate(DateTime itemCreationDate, int monthWithinQuarter,
int weekWithinMonth)
{
var quarter = (itemCreationDate.Month - 1) / 4; // Assumes quarters are divided by calendar year.
var month = quarter * 4 + monthWithinQuarter; // First quarter of month plus month within quarter
var dayInMonth = (weekWithinMonth - 1) * 7 + 1; // Weeks are counted from first day, regardless of day of week (as you mention).
return new DateTime(itemCreationDate.Year, month, dayInMonth);
}
如果有任何不清楚的地方,请告诉我。
答案 2 :(得分:-2)
你的计算,我想应该减少
DateTime dt;
dt.AddDays(daysToAdd);
dt.AddMonths(monthsToAdd);
dt.AddHours(hoursToAdd);
dt.AddYears(yearsToAdd);