在两个日期之间获取随机DateTime的最佳做法是什么?

时间:2009-09-27 14:21:27

标签: c# .net datetime random

我正在尝试为简单的DateTime数据字段随机化值。

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

所以让我们想象一下我之间的随机日期/时间

1/1/2000 10:00:00am1/1/2000 5:00:00pm

此外,此代码将用于for循环,包含100个项目...意味着所有100个项目将在最小/最大日期/时间段之间具有随机日期/时间。

有什么想法吗?

7 个答案:

答案 0 :(得分:36)

您可以尝试使用:

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 s,那么只需创建一次Random对象。 MSDN page on Random详细解释了为什么快速连续创建多个Random对象是一个坏主意。

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

  

TimeSpan(Int64)将新的TimeSpan初始化为指定的刻度数。
   TimeSpan(Int32,Int32,Int32)将新的TimeSpan初始化为指定的小时数,分钟数和秒数。
   TimeSpan(Int32,Int32,Int32,Int32)将新的TimeSpan初始化为指定的数量   天,小时,分钟和秒    TimeSpan(Int32,Int32,Int32,Int32,Int32)将新的TimeSpan初始化为指定的天数,小时数,分钟数,秒数和毫秒数。

答案 1 :(得分:4)

这是我的算法和代码:

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

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

答案 2 :(得分:3)

这就是我正在使用的:

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

我在接受的答案中使用了这种方法,但稍微修改了一下,因为我遇到了问题。

答案 3 :(得分:2)

真的很快:

  1. 将您的日期转换为TotalHours
  2. 从另一个数字中减去一个数字并使用Abs来制作正面
  3. 创建1的范围内的随机数和
  4. 的结果
  5. 将得到的随机小时数添加回两个日期中的较早日期

答案 4 :(得分:1)

首先,找出随机DateTime(小时,分钟,秒,ms等)所需的精度。

然后找出该单位中两个日期之间的差异。

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

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

根据您上面说明的用例,计算for循环外部的差异。

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

答案 5 :(得分:1)

基于ChrisF的解决方案的单行

var newDate = startDate.AddHours(new Random(Convert.ToInt32(DateTime.Now.Ticks / int.MaxValue)).Next(0, (int)(endDate - startDate).TotalHours));

答案 6 :(得分:0)

这是一个使用随机数滴答的方法:

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数量上添加一个勾号来轻松包含最后日期。