Necesito encontrar 2 implementaciones completas elegantes de
public static DateTime AddBusinessDays(this DateTime date, int days)
{
// code here
}
and
public static int GetBusinessDays(this DateTime start, DateTime end)
{
// code here
}
O (1) preferible (sin bucles).
EDITAR: Por días hábiles me refiero a días hábiles (lunes, martes, miércoles, jueves, viernes). No festivos, solo fines de semana excluidos.
Ya tengo algunas soluciones desagradables que parecen funcionar, pero me pregunto si hay formas elegantes de hacerlo. Gracias
Esto es lo que he escrito hasta ahora. Funciona en todos los casos y también hace negativos. Todavía se necesita una implementación de GetBusinessDays
public static DateTime AddBusinessDays(this DateTime startDate,
int businessDays)
{
int direction = Math.Sign(businessDays);
if(direction == 1)
{
if(startDate.DayOfWeek == DayOfWeek.Saturday)
{
startDate = startDate.AddDays(2);
businessDays = businessDays - 1;
}
else if(startDate.DayOfWeek == DayOfWeek.Sunday)
{
startDate = startDate.AddDays(1);
businessDays = businessDays - 1;
}
}
else
{
if(startDate.DayOfWeek == DayOfWeek.Saturday)
{
startDate = startDate.AddDays(-1);
businessDays = businessDays + 1;
}
else if(startDate.DayOfWeek == DayOfWeek.Sunday)
{
startDate = startDate.AddDays(-2);
businessDays = businessDays + 1;
}
}
int initialDayOfWeek = (int)startDate.DayOfWeek;
int weeksBase = Math.Abs(businessDays / 5);
int addDays = Math.Abs(businessDays % 5);
if((direction == 1 && addDays + initialDayOfWeek > 5) ||
(direction == -1 && addDays >= initialDayOfWeek))
{
addDays += 2;
}
int totalDays = (weeksBase * 7) + addDays;
return startDate.AddDays(totalDays * direction);
}
AddBusinessDays
implementación en la pregunta anterior (que en realidad era una respuesta eliminada que propuse recuperar; un mod copió esa respuesta a la pregunta en su lugar): En mi opinión, esta solución es mejor que todas las respuestas hasta ahora porque es la única uno que trate correctamente con valores negativos, sábado y domingo como fuente y no necesite una biblioteca de terceros. (He creado un pequeño programa para probar las diferentes soluciones aquí). Solo agregaríaif (businessDays == 0) return startDate;
al comienzo del método para obtener el resultado correcto también para este caso de borde.AddBusinessDays
fue la solución más general aquí que funcionó en todos los casos que necesito. Lo he copiado en uno de mis proyectos actuales (después de una ligera modificación y traducción a C ++), gracias por el código :) Me ayudó mucho, ya que es sorprendentemente difícil acertar en todos los casos extremos.Respuestas:
Último intento de su primera función:
La segunda función, GetBusinessDays, se puede implementar de la siguiente manera:
fuente
usando Fluent DateTime :
el código interno es el siguiente
fuente
Creé una extensión que te permite sumar o restar días laborales. Utilice un número negativo de BusinessDays para restar. Creo que es una solución bastante elegante. Parece funcionar en todos los casos.
Ejemplo:
fuente
Para mí, tenía que tener una solución que saltara los fines de semana y diera positivo o negativo. Mi criterio era que si avanzaba y aterrizaba en un fin de semana, tendría que avanzar al lunes. Si regresaba y aterrizaba un fin de semana, tendría que saltar al viernes.
Bueno, ya captas la idea ;)
Terminé escribiendo esta clase de extensión
Utiliza este método que pensé que sería útil para usar en otros lugares ...
Si no quiere molestarse con eso, simplemente puede reemplazarlo
if (MyClass.IsBusinessDay(date))
con ifif ((date.DayOfWeek != DayOfWeek.Saturday) && (date.DayOfWeek != DayOfWeek.Sunday))
Entonces ahora puedes hacer
o
Estos son los resultados de algunas pruebas:
fuente
fuente
Llego tarde a la respuesta, pero hice una pequeña biblioteca con toda la personalización necesaria para realizar operaciones sencillas en días laborables ... Lo dejo aquí: Gestión de Días Laborables
fuente
La única solución real es que esas llamadas accedan a una tabla de base de datos que define el calendario de su empresa. Puede codificarlo para una semana laboral de lunes a viernes sin demasiada dificultad, pero manejar los días festivos sería un desafío.
Editado para agregar una solución parcial no elegante y no probada:
También violé el requisito de no bucles.
fuente
Estoy resucitando esta publicación porque hoy tuve que encontrar una manera de excluir no solo los sábados y domingos, sino también los feriados. Más específicamente, necesitaba manejar varios conjuntos de posibles vacaciones, que incluyen:
Finalmente, obtuve el siguiente conjunto de clases de ayuda / extensiones: aunque no son descaradamente elegantes, ya que hacen un uso masivo de bucles ineficientes, son lo suficientemente decentes como para resolver mis problemas para siempre. Dejo todo el código fuente aquí en esta publicación, esperando que también sea útil para otra persona.
Código fuente
Información de uso
El código es bastante autoexplicativo, sin embargo, aquí hay un par de ejemplos para explicar cómo se puede usar.
Agregue 10 días hábiles (omitiendo solo los sábados y domingos entre semana)
Agregue 10 días hábiles (omitiendo los sábados, domingos y todos los días festivos invariables del país para 2019)
Agregue 10 días hábiles (omitiendo los sábados, domingos y todos los días festivos italianos para 2019)
Agregue 10 días hábiles (omitiendo los sábados, domingos, todos los feriados italianos y los feriados específicos de Roma para 2019)
Las funciones anteriores y los ejemplos de código se explican con más detalle en esta publicación de mi blog.
fuente
fuente
Quería un "AddBusinessDays" que admitiera números negativos de días para agregar, y terminé con esto:
No se requiere bucle, por lo que debería ser razonablemente rápido incluso para adiciones "grandes".
Funciona con días expresados como un número de días calendario desde la época, ya que está expuesto por la nueva clase JDK8 LocalDate y yo estaba trabajando en Java. Sin embargo, debería ser fácil de adaptar a otros entornos.
Las propiedades fundamentales son que
addDays
siempre devuelve un día de la semana, y que para todosd
yn
,daysBetween(d, addDays(d, n)) == n
Tenga en cuenta que, en teoría, sumar 0 días y restar 0 días deberían ser operaciones diferentes (si su fecha es un domingo, la suma de 0 días debería llevarlo al lunes y la resta de 0 días debería llevarlo al viernes). Dado que no existe el 0 negativo (¡fuera del punto flotante!), He optado por interpretar un argumento n = 0 en el sentido de agregar cero días.
fuente
Creo que esta podría ser una forma más sencilla de GetBusinessDays:
fuente
Aquí está mi código con la fecha de salida y la fecha de entrega al cliente.
Codificación feliz.
fuente
fuente
fuente
Espero que esto ayude a alguien.
fuente