0

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

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;
}

基本上,是 new 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;
}
测试 0:2203229 63086205:-60882976
测试 1:63126483 102969090:-39842607
测试2:102991588 93487982:9503606
测试 3:93510942 69439034:24071908
测试 4:69465137 70660555:-1195418
测试 5:70695702 68224849:2470853
测试 6:68248593 63555492:4693101
测试 7:63578536 65086357:-1507821
测试8:65108190 64035573:1072617
测试 9:64066128 64933449:-867321
总计:-62484058

完毕

结果始终是负面的......方式负面,所以,看起来构造函数和整数测试是更有效的方法。

4

7 回答 7

5

测量它 - 编写一个测试程序,看看哪个需要更少的时间。

于 2009-10-14T15:00:29.233 回答
3

我相信 datetime 操作会返回新的 datetime 结构,因此无论哪种方式,您都将创建新实例。

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

于 2009-10-14T15:00:39.967 回答
3

除非您正在进行一些财务处理,否则我会更担心可读性而不是性能。如果它是一个被证明的瓶颈,那么只有在像这里这样的地方开始担心性能。

于 2009-10-14T15:02:13.200 回答
2

由于他们最终都做同样的事情,所以没有太大区别。

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

于 2009-10-14T15:00:45.677 回答
1

真的很难想象这会产生显着差异的情况,但 Reflector 表明该AddDays技术应该更有效。

比较AddDays(from 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

AddDays只需将指定的天数转换为等效的刻度数(长)并将其添加到现有刻度。

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


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

于 2009-10-14T15:08:28.210 回答
1

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

 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

输出(我添加了逗号):

新日期时间:545,307,375
.AddDays:180,071,512

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

于 2009-10-14T17:15:55.613 回答
0

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

于 2009-10-14T15:06:36.133 回答