2009-07-07 10 views
9

Ich erstelle ein Bibliotheksverwaltungssystem.Wie berechne ich die Anzahl der Tage, minus Sonntage, zwischen zwei Daten in C#?

Ich habe den Zeitstempel verwendet, um die Datumsdifferenz zu berechnen, und mit Hilfe der Datumsdifferenz berechne ich auch die Fine.

Jetzt umfasst dieser Datumsunterschied alle Tage in einer Woche. Aber für eine Bibliothek Anwendung sollte nur für 6 Tage (Mo - Sa) in Woche in Rechnung gestellt werden.

Ich bin nicht in der Lage, dies zu tun.

Kann mir jemand bei der Ausführung dieser Aufgabe helfen?

Vielen Dank im Voraus!

Antwort

17

Im Wesentlichen können Sie die rohe Anzahl von Tagen berechnen; Sie müssen die Anzahl der Sonntage finden, die von dieser Zahl abgezogen werden sollen. Du weißt, dass alle 7 Tage ein Sonntag ist, also kannst du deine rohe Anzahl von Tagen durch 7 teilen und diese Zahl von deiner rohen Anzahl von Tagen subtrahieren. Jetzt müssen Sie die Anzahl der Sonntage im Rest der Woche entfernen. Ein Mod der rohen Anzahl von Tagen wird Ihnen die restlichen Tage erzählen. Um herauszufinden, ob diese Zeitspanne einen Sonntag beinhaltet, müssen Sie den Wochentag des ersten Tages kennen; Wenn Sie Montag als 0, Dienstag als 1, Mittwoch als 3 usw. definieren, dann addieren Sie den Wert des Wochentages des Beginns der Spanne zum Mod (7) der Rohzahl von Tage, wenn die Nummer 6 oder größer ist, haben Sie einen zusätzlichen Sonntag überspannt, und sollten 1 Tag von Ihrer feinen Nummer entfernen.

In Pseudo-Code:

int fine; 
int numdays = endDay - startDay; 

fine = numdays - (numdays/7); 

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

Danke für Ihre Antwort. Hervorragende Erklärung Können Sie die Erklärung programmatisch mittels Codierung darstellen? – sheetal

+0

Pseudocode hinzugefügt. –

8

Dies wird es tun:

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

Die TimeSpan/Date-Klassen zu nutzen ist definitiv der Weg, um IMO zu gehen. –

+2

Beste Antwort bis jetzt. Aber: Im Allgemeinen ist es ein "Geruch", "DateTime.Now" zu verwenden. Zum Beispiel, wie testen Sie das Gerät? Es kann sein, dass das Ergebnis des Unit-Tests an einem Montag von einem Dienstag abweicht. Besser, dann, um einen Parameter hinzuzufügen, z.B. "DateTime returnedDate" und subtrahieren Sie dayDate davon. Zweitens, seien Sie sehr vorsichtig von DateTime.Now. Es berechnet das aktuelle Datum und die aktuelle Uhrzeit unter Berücksichtigung der Zeitzonen. Seltsame Dinge könnten zweimal im Jahr passieren, wenn sich die Sommerzeit ändert. –

+0

@ Jeremy: Gute Punkte. Ich habe die Funktion nach deinem Vorschlag geändert. – raven

1

dies schnell getestet und scheint für Ihre Zwecke zu arbeiten: (edit: hinzugefügt einige Kommentare aus Gründen der Klarheit und korrigierte Codefehler)

+1

Wenn meine Antwort abgelehnt wird, kann jemand einen Grund angeben? Möchte wissen, warum das nicht funktioniert. – Chuck

-2

Mein Linqy-Ansatz (hat den Vorteil, dass es leichter zu lesen ist, aber eine kleinere Leistung benötigt ormance Hit eine Liste der Strukturtypen erstellen):

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; 
} 
+2

Dies ist das am wenigsten performante Beispiel für alle Antworten. Es ist O (N2), wo eine einfache mathematische Operation ausreichen würde. –

+0

Ja, ich mag zvolkovs Antwort besser. Ich bin nicht besonders beeindruckt von der Abstimmung. Punkkinder. –

2

Basierend auf Jacob Proffitt Antwort, aber ohne den Overhead von In-Memory-Liste. Da die DaysBetween seine Daten dynamisch ergibt, wird der Zählwert berechnet als die Liste generiert wird:

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; 
} 

Natürlich, wenn Sie nicht LINQ to showoff wollten Sie es vereinfachen könnte und gehen mit einer Funktion:

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 beide sind sauberer und einfacher zu verstehen, zu debuggen, zu beheben und zu ändern als jedermanns Lieblings (Rabens Antwort).

Natürlich ist dies eine O (n) -Lösung, dh je mehr die Tage auseinander liegen, desto länger dauert die Berechnung. Während dies in Ordnung sein für die meisten realen Anwendungen, in einigen Fällen können Sie eine Formel-basierten Ansatz bevorzugen, etwas in dieser Richtung:

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

Hier meine Implementierung ist. Mein Ziel war O (1) Ausführungszeit mit einem ähnlichen Ansatz zu McWafflestix.Ich habe versucht, es lesbar zu halten, den OO-Code zu maximieren und "Mathe-Magie" so weit wie möglich zu minimieren (nicht, dass ich irgendetwas gegen Mathe habe ... oder Magie für die Sache).

Die Idee ist die Anzahl der vollständigen 7-Tage-Wochen zwischen dem Fälligkeitsdatum und zurückgegebenen Datum zu bestimmen, und eine "Delta" Anzahl von Tagen, um es anzupassen, um die Zahl zu korrigieren. Solange Sie garantieren können, dass weder das Fälligkeitsdatum noch das zurückgegebene Datum auf einen Sonntag fallen (was ich aus Ihrer Beschreibung nicht als Problem erachte), wird dies wie erwartet funktionieren.

 
     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: Ich hatte eine Lösung früher gestellt und einen Fehler darin gefunden, und als ich daran arbeite ich den Code unten zu diesem reduziert.

Verwandte Themen