2008-11-10 36 views
19

Dada una fecha, ¿cómo puedo agregarle varios días, pero excluyo los fines de semana? Por ejemplo, dado 11/12/2008 (miércoles) y agregando cinco resultará en 11/19/2008 (miércoles) en lugar de 17/11/2008 (lunes).Agregar días a una fecha pero sin incluir fines de semana

Puedo pensar en una solución simple como recorrer cada día para agregar y verificar si es un fin de semana, pero me gustaría ver si hay algo más elegante. También me interesaría cualquier solución de F #.

+0

¿Vas a ser la adición de una pequeña cantidad de días o millones de días? – LeppyR64

+7

Solo les digo que, tan pronto como les diga que excluir los fines de semana no es un problema, también querrán vacaciones. Piensa en eso antes de implementar algo. – dnord

Respuesta

-2

Dado el número del día original en el año D y el día original en la semana W y el número de días de trabajo para añadir N, el siguiente número de días de la semana es

W + N % 5. 

Al día siguiente, en el año (sin verificación envolvente) es

D + ((N/5) * 7) + N % 5). 

Esto supone que tiene una división entera.

+0

¿Por qué votar abajo? ¿Esto arroja un resultado incorrecto? – DOK

+0

No veo ningún defecto obvio con mi respuesta. Dejar un comentario que diga lo que está mal sería útil. – gnud

+0

No he votado negativamente, pero varias personas han sugerido este algoritmo y me parece incorrecto. ¿Qué sucede cuando agrega 1 día hábil a un viernes? 'n/5 * 7' es cero y' n% 5' es uno, por lo que puede agregar uno y obtener un sábado, pero la respuesta correcta es el lunes. –

6
public DateTime AddBusinessDays(DateTime dt, int nDays) 
{ 
    int weeks = nDays/5; 
    nDays %= 5; 
    while(dt.DayOfWeek == DayOfWeek.Saturday || dt.DayOfWeek == DayOfWeek.Sunday) 
     dt = dt.AddDays(1); 

    while (nDays-- > 0) 
    { 
     dt = dt.AddDays(1); 
     if (dt.DayOfWeek == DayOfWeek.Saturday) 
      dt = dt.AddDays(2); 
    } 
    return dt.AddDays(weeks*7); 
} 
+0

Puede ser intencional para su escenario, pero para cualquier fecha ingresada en un viernes, sábado o domingo no se calculan correctamente. Marco M. El comentario funcionará para esto. – Frazer

3
int daysToAdd = weekDaysToAdd + ((weekDaysToAdd/5) * 2) + (((origDate.DOW + (weekDaysToAdd % 5)) >= 5) ? 2 : 0); 

A saber; el número de días "reales" para agregar es el número de días de la semana que está especificando, más el número de semanas completas que están en ese total (de ahí el weekDaysToAdd/5) multiplicado por dos (dos días en el fin de semana); más una compensación potencial de dos días si el día original de la semana más el número de días laborables para agregar "dentro" de la semana (de ahí el mod 5 de weekDaysToAdd) es mayor o igual a 5 (es decir, es un día de fin de semana).

Nota: esto funciona suponiendo que 0 = lunes, 2 = martes, ... 6 = domingo. También; esto no funciona en intervalos de días de semana negativos.

-1

Fórmula habrá: Día de trabajo (fecha, No. de días, (día de la semana (1)))

probar esto. Esto ayudará.

0

Creé una extensión que le permite agregar o quitar días hábiles. Use un número negativo de días de negocios para restar. Parece que funciona en todos los casos.

namespace Extensions.DateTime 
{ 
    public static class BusinessDays 
    { 
     public static System.DateTime AddBusinessDays(this System.DateTime source, int businessDays) 
     { 
      var dayOfWeek = businessDays < 0 
           ? ((int)source.DayOfWeek - 12) % 7 
           : ((int)source.DayOfWeek + 6) % 7; 

      switch (dayOfWeek) 
      { 
       case 6: 
        businessDays--; 
        break; 
       case -6: 
        businessDays++; 
        break; 
      } 

      return source.AddDays(businessDays + ((businessDays + dayOfWeek)/5) * 2); 
     } 
    } 
} 

Ejemplo:

using System; 
using System.Windows.Forms; 
using Extensions.DateTime; 

namespace AddBusinessDaysTest 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
      label1.Text = DateTime.Now.AddBusinessDays(5).ToString(); 
      label2.Text = DateTime.Now.AddBusinessDays(-36).ToString(); 
     } 
    } 
} 
+0

Esta solución presupone con precisión que si la fecha de origen es un fin de semana, Agregar o Restar 1 permitirá que pase un día de la semana, dando como resultado el martes o el jueves, respectivamente. Más cero regresará el lunes. Muy eficiente, sin iteraciones/bucle requerido. ¡Gracias! – Heliac

0

Esto es mejor si alguien está buscando una solución TSQL. Una línea de código y funciona con negativos.

CREATE FUNCTION[dbo].[AddBusinessDays](@Date date,@n INT)RETURNS DATE AS BEGIN 
DECLARE @d INT;SET @d=4-SIGN(@n)*(4-DATEPART(DW,@Date)); 
RETURN DATEADD(D,@n+((ABS(@n)[email protected])/5)*2*SIGN(@n)[email protected]/7,@Date)END 
3

Sin complicar el algoritmo, sólo podría crear un método de extensión de esta manera:

public static DateTime AddWorkingDays(this DateTime date, int daysToAdd) 
{ 
    while (daysToAdd > 0) 
    { 
     date = date.AddDays(1); 

     if (date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday) 
     { 
      daysToAdd -= 1; 
     } 
    } 

    return date; 
} 
+0

Causa un ciclo infinito si agrega un número negativo de días. – Jules

+0

Es cierto. Consulte la respuesta de Ogglas para obtener una mejor versión de este – tocqueville

2

me gustaría utilizar esta extensión, recuerde, ya que es un método de extensión para ponerlo en una estática clase.

Uso:

var dateTime = DateTime.Now.AddBusinessDays(5); 

Código:

namespace ExtensionMethods 
{ 
    public static class MyExtensionMethods 
    { 
     public static DateTime AddBusinessDays(this DateTime current, int days) 
     { 
      var sign = Math.Sign(days); 
      var unsignedDays = Math.Abs(days); 
      for (var i = 0; i < unsignedDays; i++) 
      { 
       do 
       { 
        current = current.AddDays(sign); 
       } while (current.DayOfWeek == DayOfWeek.Saturday || 
         current.DayOfWeek == DayOfWeek.Sunday); 
      } 
      return current; 
     } 
    } 
} 
+0

Una pena que no establezca un enlace a la biblioteca FluentDateTime en lugar de copiar y pegar el código (https://github.com/FluentDateTime/FluentDateTime/blob/master/FluentDateTime/DateTime/ DateTimeExtensions.cs). ¡Dale crédito al desarrollador original! – Jules

+0

@Jules ¡Gracias, olvidó agregar el enlace! – Ogglas

Cuestiones relacionadas