代码之家  ›  专栏  ›  技术社区  ›  Rob

datetime.adddays或新的datetime

  •  0
  • Rob  · 技术社区  · 15 年前

    我正在创建一个月的日期列表。我想知道什么更有效率

    List<DateTime> GetDates(DateTime StartDay) {
      List<DateTime> dates = new List<DateTime>();
      int TotalDays=StartDay.AddMonths(1).AddDays(-1).Day;
      for (int i=1; i<TotalDays; i++) {
        dates.Add(new DateTime(StartDay.Year, StartDay.Month, i));
      }
      return dates;
    }
    

    List<DateTime> GetDates(DateTime StartDay) {
      List<DateTime> dates = new List<DateTime>();
      DateTime NextMonth = StartDay.AddMonths(1);
      for (DateTime curr=StartDay; !curr.Equals(NextMonth); curr=curr.AddDays(1)) {
        dates.Add(curr);
      }
      return dates;
    }
    

    基本上,新的datetime()或datetime.adddays更有效。

    更新:

    static void Main(string[] args) {
      System.Diagnostics.Stopwatch sw=new System.Diagnostics.Stopwatch();
      long t1, t2, total;
      List<DateTime> l;
      DateTime begin = DateTime.Now;
      total = 0L;
      for (int i=0; i<10; i++) {
        sw.Start();
        l = GetDates(begin);
        sw.Stop();
    
    
        sw.Stop();
        t1 = sw.ElapsedTicks;
        sw.Reset();
        sw.Start();
    
        l = GetDates2(begin);
        sw.Stop();
        t2=sw.ElapsedTicks;
        total +=  t1- t2;
    
        Console.WriteLine("Test {0} : {1} {2} : {3}", i,t1,t2, t1- t2);
      }
      Console.WriteLine("Total: {0}", total);
    
      Console.WriteLine("\n\nDone");
      Console.ReadLine();
    }
    
    static List<DateTime> GetDates(DateTime StartDay) {
      List<DateTime> dates = new List<DateTime>();
      int TotalDays=StartDay.AddMonths(10000).AddDays(-1).Day;
      for (int i=1; i<TotalDays; i++) {
        dates.Add(new DateTime(StartDay.Year, StartDay.Month, i));
      }
      return dates;
    }
    
    
    static List<DateTime> GetDates2(DateTime StartDay) {
      List<DateTime> dates = new List<DateTime>();
      DateTime NextMonth = StartDay.AddMonths(10000);
      for (DateTime curr=StartDay; !curr.Equals(NextMonth); curr=curr.AddDays(1)) {
        dates.Add(curr);
      }
      return dates;
    }
    
    Test 0 : 2203229 63086205 : -60882976
    Test 1 : 63126483 102969090 : -39842607
    Test 2 : 102991588 93487982 : 9503606
    Test 3 : 93510942 69439034 : 24071908
    Test 4 : 69465137 70660555 : -1195418
    Test 5 : 70695702 68224849 : 2470853
    Test 6 : 68248593 63555492 : 4693101
    Test 7 : 63578536 65086357 : -1507821
    Test 8 : 65108190 64035573 : 1072617
    Test 9 : 64066128 64933449 : -867321
    Total: -62484058
    
    Done
    

    结果始终是阴性的…因此,看起来构造函数和整数测试是更有效的方法。

    7 回复  |  直到 12 年前
        1
  •  1
  •   Jeff Sternal    15 年前

    很难想象这种情况会有很大的不同,但Reflector显示 AddDays 技术应该更有效。

    比较的核心逻辑 附加日期 (从 Add(Double, Int32) )

    long num = (long) ((value * scale) + ((value >= 0.0) ? 0.5 : -0.5));
    if ((num <= -315537897600000L) || (num >= 0x11efae44cb400L)) {
        // Throw omitted
    }
    return this.AddTicks(num * 0x2710L);
    

    到的核心逻辑 DateTime(int, int, int) 建造师(来自 DateToTicks ):

    if (((year >= 1) && (year <= 0x270f)) && ((month >= 1) && (month <= 12)))
    {
        int[] numArray = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365;
        if ((day >= 1) && (day <= (numArray[month] - numArray[month - 1])))
        {
            int num = year - 1;
            int num2 = ((((((num * 0x16d) + (num / 4)) - (num / 100)) + (num / 400)) + numArray[month - 1]) + day) - 1;
            return (num2 * 0xc92a69c000L);
        }
    }
    // Throw omitted
    

    附加日期 只需将指定的天数转换为相等的刻度数(长),并将其添加到现有刻度。

    创建新的 DateTime 使用年/月/日构造函数需要更多的计算。该构造函数必须检查指定的年份是否为闰年,在每个月分配一个天数数组,执行一系列额外的操作,最终得到这三个数字所代表的刻度数。


    编辑: DateTime.AddDays(int) 比快 new DateTime(int, int, int) 但是第一个算法比第二个算法快。这可能是因为第二种算法的迭代成本要高得多。正如你在编辑中所观察到的,这很可能是因为 DateTime.Equals 比比较整数贵。

        2
  •  5
  •   mmmmmm    15 年前

    测量它-写一个测试程序,看看哪个花费更少的时间。

        3
  •  3
  •   Gratzy    15 年前

    我相信datetime操作返回新的datetime结构,所以您将以任何方式创建新的实例。

    http://msdn.microsoft.com/en-us/library/system.datetime.aspx

        4
  •  3
  •   dove    15 年前

    除非你在做一些财务处理,否则我更担心的是可读性而不是性能。只有在像这里这样的地方开始担心性能,如果它是一个被证实的瓶颈。

        5
  •  2
  •   Will    15 年前

    因为他们最终都做了相同的事情,所以没有什么区别。

    如果你在寻找效率,只需使用滴答。在完成任何数学运算之前,datetime中的所有(我见过的)调用最终都会转换为tick。

        6
  •  1
  •   Jon Seigel    15 年前

    这是一个有效的测试程序,实现了算法,以便实际比较(尽管它们仍然需要工作):

     class Program
        {
            static void Main(string[] args)
            {
                IList<DateTime> l1, l2;
                DateTime begin = new DateTime(2000, 1, 1);
    
                Stopwatch timer1 = Stopwatch.StartNew();
                for (int i = 0; i < 10000; i++)
                    l1 = GetDates(begin);
                timer1.Stop();
    
                Stopwatch timer2 = Stopwatch.StartNew();
                for (int i = 0; i < 10000; i++)
                    l2 = GetDates2(begin);
                timer2.Stop();
    
                Console.WriteLine("new DateTime: {0}\n.AddDays: {1}",
                    timer1.ElapsedTicks, timer2.ElapsedTicks);
                Console.ReadLine();
            }
    
            static IList<DateTime> GetDates(DateTime StartDay)
            {
                IList<DateTime> dates = new List<DateTime>();
    
                int TotalDays = DateTime.DaysInMonth(StartDay.Year, StartDay.Month);
    
                for (int i = 0; i < TotalDays; i++)
                    dates.Add(new DateTime(StartDay.Year, StartDay.Month, i + 1));
    
                return dates;
            }
    
    
            static IList<DateTime> GetDates2(DateTime StartDay)
            {
                IList<DateTime> dates = new List<DateTime>();
    
                DateTime NextMonth = StartDay.AddMonths(1);
    
                for (DateTime curr = StartDay; !curr.Equals(NextMonth); curr = curr.AddDays(1))
                    dates.Add(curr);
    
                return dates;
            }
        } // class

    输出(我加了逗号):

    new DateTime: 545,307,375
    .AddDays: 180,071,512

    这些结果对我来说似乎很清楚,但老实说,我认为它们会更接近。

        7
  •  0
  •   Kibbee    15 年前

    我同意马克的观点。自己测试两种方法,看看哪种方法更快。使用秒表类可以精确计算每个方法运行所需的时间。我的第一个猜测是,由于两者最终都创造了新的结构,任何速度差都可以忽略不计。另外,由于只生成一个月的日期(最多31天),我认为这两种方法都不会比另一种慢得多。也许是您生成了数千或数百万个日期,这会有所不同,但对于31个日期,这可能是过早的优化。