如何计算C#中两个日期之间的天数减去星期天?

问题描述:

我正在创建图书馆管理系统。如何计算C#中两个日期之间的天数减去星期天?

我已经使用时间戳来计算日期差异,并借助于日期差异我正在计算罚款也。

现在这个日期差异包括一周中的所有日子。但对于图书馆申请,罚款仅在周内收取6天(周一至周六)。

我无法做到这一点。

任何人都可以帮助我完成这项任务吗?

在此先感谢!

基本上,你可以计算原始天数;你需要找到从这个数字中减去的星期日数。你知道每7天是一个星期天,所以你可以将原始天数除以7,并从原始天数中减去该数字。现在,您需要删除存在的剩余时间星期日的数量;原始天数的mod会告诉您剩余的天数。要了解该跨度是否包含星期日,您必须知道第一天的星期几;如果您将星期一定义为0,星期二为1,星期三为3等,那么如果将跨度开始的星期几的值添加到原始数的mod(7)天,如果这个数字是6或更大,你已经跨过了一个额外的星期天,并且应该从你的罚款数字中删除1天。

伪代码:

int fine; 
int numdays = endDay - startDay; 

fine = numdays - (numdays/7); 

int dayOfWeek = startDate.DayOfWeek; 
if (dayOfWeek + (numdays % 7) > 6) 
{ 
    fine = fine - 1; 
} 
+0

感谢您的回复。 非常好的解释 你能通过编码的方式来编程地表示解释吗? – sheetal 2009-07-07 17:23:45

+0

添加了伪代码。 – 2009-07-07 17:24:48

这将做到这一点:

private int DaysLate(DateTime dueDate, DateTime returnDate) 
{ 
    var ts = returnDate - dueDate; 
    int dayCount = 0; 

    for (int i = 1; i <= ts.Days; i++) 
    { 
     if (dueDate.AddDays(i).DayOfWeek != DayOfWeek.Sunday) 
      dayCount++; 
    } 

    return dayCount; 
} 
+0

充分利用TimeSpan/Date类绝对是走向IMO的方式。 – 2009-07-07 18:16:18

+2

到目前为止最好的答案。但是:一般来说,使用“DateTime.Now”是一种“气味”。 例如,你如何单元测试这个?单元测试的结果可能与星期一的星期一不同。 然后,最好添加一个参数,例如“DateTime returnedDate”并从中减去dueDate。其次,要对DateTime.Now保持警惕。它计算当前日期和时间,考虑时区。奇怪的事情可能会在夏令时发生变化时每年发生两次。 – 2009-07-07 18:29:08

快速测试这一点,似乎满足您的需要:(编辑:增加了清晰一些意见和更正后的代码错误)

private static int CalculateDaysToFine(DateTime dateDue, DateTime dateIn) 
     { 
      TimeSpan ts = dateIn - dateDue; 
      int daysToFine = ts.Days - (ts.Days/7); //subtract full weeks (1 Sunday each) 
      if (((int)dateDue.DayOfWeek + (ts.Days%7)) >6) //check to see if the remaining days contain a Sunday 
       daysToFine--; 
      return daysToFine; 
     } 

我Linqy方法(有由于是更易于阅读,但需要一个小PERF创建一个结构类型列表):

private int DaysLate(DateTime dateDue, DateTime dateReturned) 
{ 
    return getDayList(dateDue, dateReturned).Where(d => d.DayOfWeek != DayOfWeek.Sunday).Count(); 
} 

private List<DateTime> getDayList(DateTime begin, DateTime end) 
{ 
    List<DateTime> dates = new List<DateTime>(); 
    DateTime counter = begin; 
    while (counter <= end) 
    { 
     dates.Add(counter); 
     counter = counter.AddDays(1); 
    } 
    return dates; 
} 

基于Jacob Proffitt的答案,但没有内存列表的开销。由于DaysBetween动态生成它的日期,计数计算生成的列表:

int c = DaysBetween(begin, end).Count(d => d.DayOfWeek != DayOfWeek.Sunday); 

private IEnumerable<DateTime> DaysBetween(DateTime begin, DateTime end) 
{ 
    for(var d = begin; d <= end; d.AddDays(1)) yield return d; 
} 

当然,如果你不想showoff LINQ,你可以把它简化,并用一个函数去:

private int DaysBetween(DateTime begin, DateTime end) 
{ 
    int count = 0; 
    for(var d = begin; d <= end; d.AddDays(1)) 
     if(d.DayOfWeek != DayOfWeek.Sunday) count++ 
    return count; 
} 

恕我直言,这两个都比每个人的最爱(乌鸦的答案)更清洁,更易于理解,调试,排除故障和修改。

当然,这是一个O(n)解决方案,这意味着分离的日子越多,计算所需的时间就越长。虽然这可能是好于大多数的实际应用,在某些情况下,你可能更喜欢基于公式的方法,东西沿着这些线路:

int q = end.Subtract(begin).Days - (end.Subtract(begin).Days/7); 

这里是我的实现。我的目标是使用类似McWafflestix的方法执行O(1)。我试图保持它的可读性,最大化OO代码并尽可能地减少“数学魔法”(并非我对数学或魔术有任何反应)。

这个想法是确定截止日期和返回日期之间的完整7天周的数量,以及通过更正数字来调整它的“增量”天数。只要您可以保证星期日(假定您的描述不会成为问题)的到期日和退回日期都不会发生,就可以按预期工作。

 
     static int CalculateFineDays(DateTime due, DateTime returned) 
     { 
      TimeSpan ts = returned - due; 
      if (ts < TimeSpan.Zero) 
       return 0;
int delta = returned.DayOfWeek - due.DayOfWeek; return delta + ts.Subtract(TimeSpan.FromDays(delta)).Days * 6/7; }

编辑:我曾提出了一个解决方案更早发现了一个bug在里面,和我的工作就可以了我减少了代码到这一点。