Reputation: 387
I am creating a Library Management System.
I have used the timestamp to calculate the Date Difference and with the help of date difference I am calculating the Fine also.
Now this date difference includes all days in a week. But for a library application fine should be charged only for 6 days(Mon - Sat) in Week.
I am not able to do this.
Can anyone help me out in performing this task?
Thanks in advance!!
Upvotes: 9
Views: 5015
Reputation:
Tested this quickly and seems to work for your purposes:(edit: added some comments for clarity and corrected code error)
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;
}
Upvotes: 1
Reputation: 18135
This will do it:
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;
}
Upvotes: 7
Reputation: 410
Here is my implementation. My goal was O(1) execution time using a similar approach to McWafflestix. I tried to keep it readable, maximizing OO code and minimizing "math magic" as much as possible (not that I have anything against math... or magic for that matter).
The idea is to determine the number of complete 7-day weeks between the due date and returned date, and a "delta" number of days to adjust it by to correct the number. As long as you can guarantee that neither the due date nor the returned date fall on a Sunday (which I presume from your description will not be a problem) this will work as expected.
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;
}
Edit: I had posed a solution earlier and found a bug in it, and as I was working on it I reduced the code down to this.
Upvotes: 0
Reputation: 18923
Based on Jacob Proffitt answer but without the overhead of in-memory List. Since the DaysBetween yields its dates dynamically, the count is calculated as the list is generated:
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;
}
Of course if you didn't want to showoff LINQ you could simplify it and go with one function:
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;
}
IMHO both of these are cleaner and easier to understand, debug, troubleshoot, and modify than the everybody's favorite (raven's answer).
Of course, this is an O(n) solution, meaning the more the days are apart, the longer it takes to calculate. While this may be Ok for most of real world applications, in some cases you may prefer a formula-based approach, something along these lines:
int q = end.Subtract(begin).Days - (end.Subtract(begin).Days / 7);
Upvotes: 2
Reputation: 12768
My Linqy approach (has the virtue of being easier to read but takes a minor performance hit of creating a List of structure types):
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;
}
Upvotes: -2
Reputation: 39480
Essentially, you can calculate the raw number of days; you need to find the number of Sundays to be subtracted from that number. You know that every 7 days is a Sunday, so you can divide your raw number of days by 7, and subtract that number from your raw number of days. Now you need to remove the number of Sundays in the remainder of the week that exists; a mod of the raw number of days will tell you the remainder days. To find out if that span includes a Sunday, you must know the day of the week of the first day; if you define Monday to be 0, Tuesday to be 1, Wednesday to be 3, etc., then if you add the value of the day of the week of the beginning of the span to the mod (7) of the raw number of days, if the number is 6 or greater, you have spanned an additional Sunday, and should remove 1 day from your fine number.
In pseudocode:
int fine;
int numdays = endDay - startDay;
fine = numdays - (numdays / 7);
int dayOfWeek = startDate.DayOfWeek;
if (dayOfWeek + (numdays % 7) > 6)
{
fine = fine - 1;
}
Upvotes: 17