AddBusinessDays和GetBusinessDays

Adr*_*scu 85 .net c#

我需要找到2个优雅的完整实现

public static DateTime AddBusinessDays(this DateTime date, int days)
{
 // code here
}

and 

public static int GetBusinessDays(this DateTime start, DateTime end)
{
 // code here
}
Run Code Online (Sandbox Code Playgroud)

O(1)优选(无环).

编辑:工作日我指的是工作日(周一,周二,周三,周四,周五).没有假期,只是周末排除在外.

我已经有一些似乎有效的丑陋解决方案,但我想知道是否有优雅的方法来做到这一点.谢谢


这就是我到目前为止所写的内容.它适用于所有情况,也会产生负面影响.仍然需要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);
}
Run Code Online (Sandbox Code Playgroud)

Pat*_*ald 131

您的第一个功能的最新尝试:

public static DateTime AddBusinessDays(DateTime date, int days)
{
    if (days < 0)
    {
        throw new ArgumentException("days cannot be negative", "days");
    }

    if (days == 0) return date;

    if (date.DayOfWeek == DayOfWeek.Saturday)
    {
        date = date.AddDays(2);
        days -= 1;
    }
    else if (date.DayOfWeek == DayOfWeek.Sunday)
    {
        date = date.AddDays(1);
        days -= 1;
    }

    date = date.AddDays(days / 5 * 7);
    int extraDays = days % 5;

    if ((int)date.DayOfWeek + extraDays > 5)
    {
        extraDays += 2;
    }

    return date.AddDays(extraDays);

}
Run Code Online (Sandbox Code Playgroud)

第二个函数Ge​​tBusinessDays可以实现如下:

public static int GetBusinessDays(DateTime start, DateTime end)
{
    if (start.DayOfWeek == DayOfWeek.Saturday)
    {
        start = start.AddDays(2);
    }
    else if (start.DayOfWeek == DayOfWeek.Sunday)
    {
        start = start.AddDays(1);
    }

    if (end.DayOfWeek == DayOfWeek.Saturday)
    {
        end = end.AddDays(-1);
    }
    else if (end.DayOfWeek == DayOfWeek.Sunday)
    {
        end = end.AddDays(-2);
    }

    int diff = (int)end.Subtract(start).TotalDays;

    int result = diff / 7 * 5 + diff % 7;

    if (end.DayOfWeek < start.DayOfWeek)
    {
        return result - 2;
    }
    else{
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • DateTime.AddDays使用负数.这与使用负数无法正确遵循相同的模式,AddBusinessDays允许选择非工作日. (2认同)

Sim*_*mon 62

使用Fluent DateTime:

var now = DateTime.Now;
var dateTime1 = now.AddBusinessDays(3);
var dateTime2 = now.SubtractBusinessDays(5);
Run Code Online (Sandbox Code Playgroud)

内部代码如下

    /// <summary>
    /// Adds the given number of business days to the <see cref="DateTime"/>.
    /// </summary>
    /// <param name="current">The date to be changed.</param>
    /// <param name="days">Number of business days to be added.</param>
    /// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns>
    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;
    }

    /// <summary>
    /// Subtracts the given number of business days to the <see cref="DateTime"/>.
    /// </summary>
    /// <param name="current">The date to be changed.</param>
    /// <param name="days">Number of business days to be subtracted.</param>
    /// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns>
    public static DateTime SubtractBusinessDays(this DateTime current, int days)
    {
        return AddBusinessDays(current, -days);
    }
Run Code Online (Sandbox Code Playgroud)


Arj*_*jen 13

我创建了一个扩展程序,允许您添加或减去工作日.使用负数的businessDays进行减法.我认为这是一个非常优雅的解决方案.它似乎适用于所有情况.

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

例:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Slauma:这就是加拿大大多数企业的运作方式.+1营业日="下一个工作日",如果星期六是星期二.星期一将是"同一工作日". (3认同)
  • @Slauma程序按预期工作.从逻辑上考虑一下.如果商业相关的事情在星期六开始,并且你必须允许一个工作日让人们在所述工作日的范围内作出反应,那么告诉他们必须在星期一之前完成吗? (3认同)
  • 如果源日期是星期六或星期日,结果是有问题的。例如:星期六 + 1 个工作日的结果是星期二,而我宁愿期待星期一。 (2认同)

Hug*_*tes 8

对我来说,我必须有一个解决方案,可以跳过周末,无论是消极的还是积极的.我的标准是,如果它向前推进并在周末降落,则需要提前到周一.如果它要回去并在周末降落,它将不得不跳到星期五.

例如:

  • 星期三 - 3个工作日=上周五
  • 周三+ 3个工作日=周一
  • 星期五 - 7个工作日=上周三
  • 星期二 - 5个工作日=上周二

反正你懂这个意思 ;)

我最后写了这个扩展类

public static partial class MyExtensions
{
    public static DateTime AddBusinessDays(this DateTime date, int addDays)
    {
        while (addDays != 0)
        {
            date = date.AddDays(Math.Sign(addDays));
            if (MyClass.IsBusinessDay(date))
            {
                addDays = addDays - Math.Sign(addDays);
            }
        }
        return date;
    }
}
Run Code Online (Sandbox Code Playgroud)

它使用我认为在其他地方使用的方法很有用......

public class MyClass
{
    public static bool IsBusinessDay(DateTime date)
    {
        switch (date.DayOfWeek)
        {
            case DayOfWeek.Monday:
            case DayOfWeek.Tuesday:
            case DayOfWeek.Wednesday:
            case DayOfWeek.Thursday:
            case DayOfWeek.Friday:
                return true;
            default:
                return false;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你不想打扰它,你可以if (MyClass.IsBusinessDay(date))用if 替换掉if ((date.DayOfWeek != DayOfWeek.Saturday) && (date.DayOfWeek != DayOfWeek.Sunday))

所以现在你可以做到

var myDate = DateTime.Now.AddBusinessDays(-3);
Run Code Online (Sandbox Code Playgroud)

要么

var myDate = DateTime.Now.AddBusinessDays(5);
Run Code Online (Sandbox Code Playgroud)

以下是一些测试的结果:

Test                         Expected   Result
Wednesday -4 business days   Thursday   Thursday
Wednesday -3 business days   Friday     Friday
Wednesday +3 business days   Monday     Monday
Friday -7 business days      Wednesday  Wednesday
Tuesday -5 business days     Tuesday    Tuesday
Friday +1 business days      Monday     Monday
Saturday +1 business days    Monday     Monday
Sunday -1 business days      Friday     Friday
Monday -1 business days      Friday     Friday
Monday +1 business days      Tuesday    Tuesday
Monday +0 business days      Monday     Monday