2009-07-07 38 views
9

Sto creando un sistema di gestione della libreria.Come si calcola il numero di giorni, meno domeniche, tra due date in C#?

Ho usato il timestamp per calcolare la differenza di data e con l'aiuto della differenza di data sto calcolando anche la Fine.

Ora questa differenza di data include tutti i giorni in una settimana. Ma per una domanda di biblioteca, l'importo dovrebbe essere addebitato solo per 6 giorni (lunedì - sabato) nella settimana.

Non riesco a farlo.

Qualcuno può darmi una mano nello svolgere questa attività?

Grazie in anticipo !!

risposta

17

In sostanza, è possibile calcolare il numero di giorni non elaborati; devi trovare il numero di domeniche da sottrarre da quel numero. Sapete che ogni 7 giorni è una domenica, quindi è possibile dividere il numero di giorni non elaborati per 7 e sottrarre quel numero dal numero di giorni non elaborati. Ora è necessario rimuovere il numero di domeniche nel resto della settimana esistente; a mod del numero grezzo di giorni ti dirà il resto giorni. Per sapere se quella durata include una domenica, devi conoscere il giorno della settimana del primo giorno; se si definisce lunedì come 0, martedì per essere 1, mercoledì per essere 3, ecc., quindi se si aggiunge il valore del giorno della settimana dell'inizio dello span al mod (7) del numero grezzo di giorni, se il numero è 6 o superiore, hai spanning un'altra domenica, e dovresti rimuovere 1 giorno dal tuo numero fine.

In pseudocodice:

int fine; 
int numdays = endDay - startDay; 

fine = numdays - (numdays/7); 

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

Grazie per la risposta. Spiegazione eccellente Potete rappresentare la spiegazione in modo programmatico tramite la codifica? – sheetal

+0

Aggiunto pseudocodice. –

8

Questo lo farà:

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

Sfruttare le classi TimeSpan/Date è sicuramente il modo per passare all'IMO. –

+2

La migliore risposta finora. Ma: in generale, è un "odore" usare "DateTime.Now". Ad esempio, come si esegue il test dell'unità? Potrebbe essere che il risultato del test unitario sia diverso di lunedì da martedì. Meglio, quindi, aggiungere un parametro, ad es. "DateTime returnedDate" e sottrarre dateDate da questo. In secondo luogo, fai molta attenzione a DateTime.Now. Calcola la data e l'ora correnti, tenendo conto dei fusi orari. Strane cose potrebbero accadere due volte all'anno nel periodo in cui l'ora legale cambia. –

+0

@Jeremy: buoni punti. Ho modificato la funzione secondo il tuo suggerimento. – raven

1

testato questo velocemente e sembra funzionare per i vostri scopi: (edit: aggiunto alcuni commenti per chiarezza e corretto codice di errore)

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

Se la mia risposta sarà rifiutata, qualcuno può almeno dare una motivazione? Vorrei sapere perché questo non funzionerà. – Chuck

-2

Il mio approccio Linqy (ha il pregio di essere più facile da leggere ma richiede un minor perfezionamento ormance colpo di creare una lista di tipi di struttura):

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

Questo è l'esempio meno performante di tutte le risposte. È O (N2) dove sarebbe sufficiente una semplice operazione matematica. –

+0

Sì, mi piace la risposta di zvolkov meglio. Non sono molto impressionato dal down-voting, però. Bambini punk –

2

Sulla base di Jacob Proffitt risposta, ma senza il sovraccarico di elenco in memoria. Dal momento che il DaysBetween cede le sue date in modo dinamico, il conteggio viene calcolata come l'elenco viene generato:

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

Naturalmente se non voleva showoff LINQ si potrebbe semplificare e andare con una funzione:

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 entrambi questi sono più chiari e facili da capire, eseguire il debug, risolvere i problemi e modificare rispetto al preferito di tutti (risposta del corvo).

Ovviamente, questa è una soluzione O (n), il che significa che più i giorni sono separati, più tempo è necessario per calcolare. Anche se questo potrebbe essere ok per la maggior parte delle applicazioni del mondo reale, in alcuni casi si può preferire un approccio formula a base, qualcosa in questo senso:

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

Qui è la mia realizzazione. Il mio obiettivo era O (1) tempo di esecuzione usando un approccio simile a McWafflestix.Ho cercato di tenerlo leggibile, massimizzando il codice OO e riducendo al minimo la "magia della matematica" il più possibile (non che io abbia qualcosa contro la matematica ... o la magia per quella materia).

L'idea è di determinare il numero di settimane di 7 giorni complete tra la data di scadenza e la data di ritorno e un numero di giorni "delta" da regolare per correggere il numero. Finché è possibile garantire che né la data di scadenza né la data di reso cadano di domenica (che presumo dalla descrizione non costituirà un problema), funzionerà come previsto.

 
     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: mi aveva posto una soluzione in precedenza e ha trovato un bug in esso, e mentre stavo lavorando su di esso ho ridotto il codice riduce a questo.

Problemi correlati