请帮助优化此循环

时间:2010-12-06 19:29:20

标签: c# .net

我需要计算两个日期之间的工作日数。工作日是周一至周五的任何一天,节假日除外。下面的代码执行此操作,但它使用循环。有没有人看到摆脱循环或至少优化它的方法?

感谢 康斯坦丁


using System;
using System.Linq;

namespace consapp
{
    static class Program
    {
        static void Main(string[] args)
        {
            var holidays = new DateTime[] { new DateTime(2010, 11, 23), new DateTime(2010, 11, 30) };

            var date_start = new DateTime(2010, 12, 3);
            var date_end = date_start.AddDays(-9.9);
            var duration = (date_end - date_start).Duration();

            for (var d = date_end; d < date_start; d = d.Date.AddDays(1))
            {
                if (holidays.Contains(d.Date) || d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday)
                {
                    duration -= TimeSpan.FromDays(1) - d.TimeOfDay;
                }
            }
            Console.WriteLine(duration);
        }
    }
}

5 个答案:

答案 0 :(得分:0)

这里的表现真的有问题吗?除非分析表明否则我猜这段代码并没有真正减慢你的应用程序。除非你计算每秒数千个长间隔的工作日,否则它的性能应该没问题。

如果您的假期列表比两个日期大得多,则将其转换为HashSet<T>,其中包含O(1)查找时间。

当然,你可以扭转代码。因此,您不要在间隔期间循环,而是在假日期间。然后你只计算一个区间的工作日数(应该是简单的数学运算)并减去一周工作日的假日数。

如果确实有必要,您可以预先计算自某个固定日期以来的工作日,然后从该期间结束时的查找结果中减去该期间开头的查找结果。

答案 1 :(得分:0)

我会研究如下算法。 (对不起,没有提供代码。)

  1. 计算开始日期和结束日期之间的完整7天周数。您应该可以使用.NET DateTime和TimeSpan对象执行此操作。
  2. 对于每个完整的7天工作周,请在结果中添加5天。
  3. 计算出部分周数,包括您的开始日期和结束日期。
  4. 在您的假期中循环,并在开始和结束日期之间的每个假期将结果减少1。循环在这里更好,因为在开始日期和结束日期之间,可能会有更少的假期循环。
  5. 玩得开心!

    编辑:有关源代码,请查看以下答案:Calculate the number of business days between two dates?

答案 2 :(得分:0)

如果您想要更快的代码,请不要在范围内的每一天循环:

从假日列表中删除星期日或星期六的所有假期,然后使用时间跨度方法为您提供两个日期之间的天数。通过一点点数学(考虑整数除以7),您可以得到该范围内的星期四天数,减去周末不会从该数字开始的假期数量,并且您已完成。

答案 3 :(得分:0)

按原样滚动。这不会浪费太多时间,因为边界很小。当你有一些工作代码时,继续前进。无需无理无故地优化代码。

答案 4 :(得分:0)

因为我把它作为一个有趣的谜题开始,这里是代码:

    [Test]
    public void TestDateTime() {
        var start = DateTime.Now.Date;
        var end = DateTime.Now.Date.AddDays(35);
        var workdays = (end - start).Days - ((end - start).Days/7)*2 
            - (((end - start).Days%7==0)?0:(((int)start.DayOfWeek==0)?1:Math.Max(Math.Min((int)start.DayOfWeek + (end - start).Days%7 - 6, 2), 0)));
        new []{DateTime.Now.AddDays(19), DateTime.Now.AddDays(20)}.ToList().ForEach(
            x => { if (x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday) workdays--; });
        Console.Out.WriteLine("workdays = {0}", workdays);
    }

圣诞节和节礼日作为假期包括在内。