2011-06-30 21 views
7

que tiene un método de C# como esto:Número de días en el rango de fechas, excepto fines de semana y otras fechas, en C#

public static int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, String excludeDates) 
{ 
} 

Lo que se supone que debe hacer es calcular el número de días entre la startDate y endDate, pero opcionalmente debe excluir fines de semana y también otras fechas (pasadas como una cadena de fechas separadas por comas).

No tengo ni idea de cómo abordar esto. Mi intuición sería ir de loop de startDate a endDate y hacer algunas comparaciones de cadenas, pero por lo que puedo descubrir, C# no permite pasar las fechas de esa manera, o al menos no es una forma muy elegante de hacer las cosas.

+0

un O mejor (1) solución se puede encontrar aquí: stackoverflow.com/questions/1044688 –

Respuesta

8

Aquí hay un ejemplo que incluye las fechas excluidas, los fines de semana y los bucles. Sin embargo, cambié la cadena excludeDates a una lista. Se debe agregar alguna comprobación nula.

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

EDIT: yo quiero señalar que me parece que es el método rápido y sucio - si usted no tiene que hacer esto a menudo. Si está realizando esto mucho y la distancia entre startDate y endDate es bastante grande, sería mucho mejor hacer los cálculos como se indica en una de las otras respuestas. Esto se sugiere para tener una idea de las fechas de iteración.

+0

En vez de hacer un bucle 'for (int i = 0; i Alex

1

La biblioteca de azúcar Subsónica tiene muchos ayudantes para manejar la manipulación de DateTime.

Puede encontrar una lista completa en Subsonic site y el código fuente está en github.

10

Oh, es muy fácil de recorrer las fechas - que no es un problema en absoluto:

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

Desde aquí se puede escribir un IEnumerable<DateTime> también, y utilizar foreach.

Trataré de evitar hacer cadena operaciones aquí si es posible - fundamentalmente estas fechas no son cadenas, así que si puedes trabajar en el dominio problemático lo más posible, te facilitará las cosas.

Por supuesto que puede haber maneras más eficientes que bucles, pero será más difícil hacerlo bien. Si el ciclo está bien en términos de rendimiento, me apegaré a eso.

Como un complemento rápido para mi propio proyecto de código abierto, Noda Time tiene un conjunto bastante diverso de tipos que representan fechas y horas; en este caso, usaría LocalDate. De esta forma, no tiene que preocuparse por lo que sucede si el tiempo de "inicio" es posterior al tiempo en "fin", etc. Por otro lado, Noda Time aún no está terminado ... los bits que necesita para esto están listos y deberían funcionar bien, pero es posible que la API aún pueda cambiar en el futuro.

EDIT: Si hace necesidad de bucle a través de fechas con frecuencia, es posible que desee algo parecido a este método de extensión (ponerlo en una clase estática de nivel superior no genérico):

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

continuación:

foreach (DateTime date in start.To(end)) 
{ 
    ... 
} 
+0

Para evitar la comparación de cadenas para excluir fechas, toda lo que necesita hacer es encontrar el número de fechas que estés excluyendo (asumiendo que no hay fines de semana), que se puede encontrar con: excludeDates.split ('') de longitud.. Luego reste esto de la cantidad de días. El – macleojw

+0

excluyen las fechas podrían no necesariamente caen dentro de las fechas de inicio y final, sin embargo, por lo que es necesario que haya un cheque aquí - que forma parte de la dificultad y significa que no puedo hacerlo de la manera que usted sugiere. – Dan

0

Aquí es pseudocódigo para un enfoque diferente, que he utilizado en SQL:

Find the total number of days between the two datesnúmero Restar de fines de semana
Retirar un día si la fecha de inicio es un domingo
Retirar un día si la fecha de inicio es un sábado
Retire cualquier otro día que no desee (ver mi comentario anterior para saber cómo hacerlo esto en C#)

0

Esto podría funcionar y evitar un O (n) de tipo solució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; 

} 

Su no exhaustivamente probado sin embargo.

Para hacer frente a las exclusiones fecha que podría navegar por los excluir y donde están entre el inicio y el final (y no un fin de semana en su caso). Este debería ser un ciclo más corto que pasar por todos los días entre el inicio y el final.

0

Combinar con expresiones 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; 
    } 
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; 
} 
Cuestiones relacionadas