我有一个像这样的C#方法:
public static int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, String excludeDates)
{
}
它应该做的是计算startDate和endDate之间的天数,但可选地需要排除周末和其他日期(以逗号分隔的日期字符串传递)。
我完全不知道如何解决这个问题。我的直觉是从startDate循环到endDate并进行一些字符串比较,但从我可以发现的结果来看,C#不允许以这种方式循环日期 - 或者至少它不是一种非常优雅的做事方式。
答案 0 :(得分:10)
哦,很容易遍历日期 - 这根本不是问题:
// I'm assuming you want <= to give an *inclusive* end date...
for (DateTime date = start; date <= end; date = date.AddDays(1))
{
// Do stuff with date
}
您也可以轻松编写IEnumerable<DateTime>
,然后使用foreach
。
我尽量避免在这里做 string 操作 - 从根本上说这些日期不是字符串,所以如果你可以尽可能在问题域中工作,它会使事情变得更容易。
当然可能有更有效的方式而不是循环,但它们更难以正确。如果循环在性能方面没问题,我会坚持下去。
作为我自己的开源项目的快速插件,Noda Time有一组代表日期和时间的更多样式 - 在这种情况下,您使用LocalDate
。这样你就不用担心如果“开始”的时间晚于“结束”的时间等会发生什么。另一方面,Noda Time还没有真正完成......你需要的位数为此已做好准备,应该可以正常工作,但API有可能在将来发生变化。
编辑:如果你做需要经常循环日期,你可能想要这样的扩展方法(把它放在顶级非泛型静态类中):
public static IEnumerable<DateTime> To(this DateTime start, DateTime end)
{
Date endDate = end.Date;
for (DateTime date = start.Date; date <= endDate; date = date.AddDays(1))
{
yield return date;
}
}
然后:
foreach (DateTime date in start.To(end))
{
...
}
答案 1 :(得分:9)
这是一个包含排除日期,周末和循环的示例。我确实将字符串excludeDates更改为List。应该添加一些空检查。
public static int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, List<DateTime> excludeDates)
{
int count = 0;
for (DateTime index = startDate; index < endDate; index = index.AddDays(1))
{
if (excludeWeekends && index.DayOfWeek != DayOfWeek.Sunday && index.DayOfWeek != DayOfWeek.Saturday)
{
bool excluded = false; ;
for (int i = 0; i < excludeDates.Count; i++)
{
if (index.Date.CompareTo(excludeDates[i].Date) == 0)
{
excluded = true;
break;
}
}
if (!excluded)
{
count++;
}
}
}
return count;
}
编辑:我想指出我会认为这是一种快速而肮脏的方法 - 如果你不经常这样做的话。如果你执行这么多,并且startDate和endDate之间的距离相当大,那么按照其他一个答案中的说明进行数学运算会好得多。建议这样做是为了感受迭代日期。
答案 2 :(得分:1)
Subsonic糖库有很多帮助器来处理DateTime操作。
您可以在Subsonic site上找到完整列表,源代码位于github。
答案 3 :(得分:0)
这是我在SQL中使用的不同方法的伪代码:
Find the total number of days between the two dates
减去周末数量
如果开始日期是星期日,请删除一天
如果开始日期是星期六,则删除一天
删除您不想要的任何其他日子(请参阅上面的评论,了解如何在c#中执行此操作)
答案 4 :(得分:0)
这可能会起作用并避免使用O(n)类型的解决方案:
public int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, String excludeDates)
{
//Work out days in range
int days = (int)endDate.Subtract(startDate).TotalDays + 1;
if (excludeWeekends)
{
//Remove most weekends by removing 2 in 7 days (rounded down)
days -= ((int)Math.Floor((decimal)(days / 7)) * 2);
if (startDate.DayOfWeek == DayOfWeek.Sunday) days -= 1;
if (startDate.DayOfWeek == DayOfWeek.Saturday) days -= 2;
}
return days;
}
虽然没有详尽的测试。
要处理排除日期,您可以循环使用它们并排除它们在开始和结束之间的位置(如果合适,则不包括周末)。这应该是一个比开始和结束之间的所有日子更短的循环。
答案 5 :(得分:0)
与LINQ表达式结合,
public int GetNoOfLeaveDays(DateTime fromDate, DateTime toDate, Boolean excludeWeekends, List<DateTime> excludeDates)
{
var count = 0;
for (DateTime index = fromDate; index <= toDate; index = index.AddDays(1))
{
if (!excludeWeekends || index.DayOfWeek == DayOfWeek.Saturday || index.DayOfWeek == DayOfWeek.Sunday) continue;
var excluded = excludeDates.Any(t => index.Date.CompareTo(t.Date) == 0);
if (!excluded) count++;
}
return count;
}
答案 6 :(得分:0)
private int workingdays(int month,int year)
{
int daysInMonth = 0;
int days = DateTime.DaysInMonth(year, month);
for (int i = 1; i <= days; i++)
{
DateTime day = new DateTime(year, month, i);
if (day.DayOfWeek != DayOfWeek.Sunday && day.DayOfWeek != DayOfWeek.Saturday)
{
daysInMonth++;
}
}
return daysInMonth;
}