代码之家  ›  专栏  ›  技术社区  ›  Pure.Krome

在两个日期时间之间获取随机日期时间的最佳实践是什么?

  •  15
  • Pure.Krome  · 技术社区  · 15 年前

    我正在尝试随机化 DateTime 数据字段。

    我希望获得两个日期/时间之间的随机日期/时间(例如,最小日期/时间和最大日期/时间)。

    所以让我们想象一下,我在一个随机的日期/时间间隔

    1/1/2000 10:00:00am 1/1/2000 5:00:00pm .

    此外,此代码将在for循环中使用,其中包含100个项…这意味着所有100个项目的最小/最大日期/时间段之间都有随机日期/时间。

    有什么想法吗?

    7 回复  |  直到 7 年前
        1
  •  35
  •   ChrisF toni    15 年前

    您可以尝试使用:

    TimeSpan timeSpan = endDate - startDate;
    var randomTest = new Random();
    TimeSpan newSpan = new TimeSpan(0, randomTest.Next(0, (int)timeSpan.TotalMinutes), 0);
    DateTime newDate = startDate + newSpan;
    

    这会给你不同的时间。如果你想要100(或任何超过1的东西) DateTime 然后只创建 Random 对象一次。这个 MSDN page on Random 详细解释为什么要创建多个 随机的 快速连续的对象是个坏主意。

    使用不同的 TimeSpan 构造函数将为您提供不同的粒度。来自 TimeSpan constructor MSDN :

    TimeS盘(国际64) 将新的时间跨度初始化为指定的刻度数。
    时间跨度(Int32、Int32、Int32) 将新的时间跨度初始化为指定的小时、分钟和秒数。
    时间跨度(Int32、Int32、Int32、Int32) 将新的时间跨度初始化为指定的数字 天、小时、分钟和秒。
    时间跨度(Int32、Int32、Int32、Int32、Int32) 将新的时间跨度初始化为指定的天、小时、分钟、秒和毫秒数。

        2
  •  4
  •   p.campbell    15 年前

    这是我的算法和代码:

    • 找出两个日期的区别
    • 对于每个迭代,在两个日期之间创建一个随机数
    • 在两者之间创建新日期。只需将该随机数作为分钟添加到开始日期时间。

      Random randNum = new Random();
      
      DateTime minDt = new DateTime(2000,1,1,10,0,0);
      DateTime maxDt = new DateTime(2000,1,1,17,0,0);
      List<DateTime> myDates = new List<DateTime>();
      //Random.Next in .NET is non-inclusive to the upper bound (@NickLarsen)
      int minutesDiff = Convert.ToInt32(maxDt.Subtract(minDt).TotalMinutes+1);
      
      for (int i = 0; i < 100; i++)
      {
         // some random number that's no larger than minutesDiff, no smaller than 1
         int r=   randNum.Next(1, minutesDiff); 
         myDates.Add(minDt.AddMinutes(r));
      }
      
      foreach (DateTime d in myDates)
      {
        Console.WriteLine(string.Format("{0:dd-MMM-yyyy hh:mm}",d));
      }
      
        3
  •  3
  •   Noctis    10 年前

    这是我正在使用的:

    class RandomDates
    {
        private Random random = new Random();
    
        public DateTime Date(DateTime? start = null, DateTime? end = null)
        {
            if (start.HasValue && end.HasValue && start.Value >= end.Value)
                throw new Exception("start date must be less than end date!");
    
            DateTime min = start ?? DateTime.MinValue;
            DateTime max = end ?? DateTime.MaxValue;
    
            // for timespan approach see: http://stackoverflow.com/q/1483670/1698987
            TimeSpan timeSpan = max - min;
    
            // for random long see: http://stackoverflow.com/a/677384/1698987
            byte[] bytes = new byte[8];
            random.NextBytes(bytes);
    
            long int64 = Math.Abs(BitConverter.ToInt64(bytes, 0)) % timeSpan.Ticks;
    
            TimeSpan newSpan = new TimeSpan(int64);
    
            return min + newSpan;
        }
    }
    

    我在接受的答案中使用了这个方法,但由于我对它有一些问题,所以稍微修改了一下。

        4
  •  2
  •   D'Arcy Rittich    15 年前

    非常快:

    1. 将日期转换为总小时数
    2. 从另一个数字中减去一个数字,用abs表示正数
    3. 在1和2的范围内创建一个随机数。在上面
    4. 将产生的随机小时数加回到两个日期中较早的一个。
        5
  •  1
  •   tschaible    15 年前

    首先,找出随机日期时间(小时、分钟、秒、毫秒等)的精度。

    然后计算出该单元中两个日期之间的差异。

    创建一个介于0和该差之间的随机整数。

    将以单位表示的随机整数添加到原始日期。

    考虑到上面提到的用例,计算for循环中外部的差异。

    在for循环中,获取随机int并构造随机日期。

        6
  •  1
  •   Ryan Penfold    10 年前

    基于Chrisf解决方案的一行程序

    var newDate = startDate.AddHours(new Random(Convert.ToInt32(DateTime.Now.Ticks / int.MaxValue)).Next(0, (int)(endDate - startDate).TotalHours));
    
        7
  •  0
  •   Eamon Nerbonne    15 年前

    下面是一个使用随机刻度数的方法:

    Random r= new Random(); 
        //for better randomness don't recreate a new Random() too frequently.
    long rand62bit = (((long)r.Next())<<31) + r.Next(); 
        // 62bits suffices for random datetimes, 31 does not!
    DateTime newDate = startDate + new TimeSpan(rand62bit % (endDate - startDate).Ticks); 
    

    此方法排斥最后一个日期,并包含第一个日期。您可以通过在“基本”中添加一个勾号来轻松包括最后一个日期。 (endDate - startDate).Ticks 数量。