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

时间:2022-01-17 21:33:53

I'm trying to randomize the value for a simple DateTime data field.

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

I wish to get a random date/time between two date/times (e.g. min date/time and max date/time).

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

So lets imagine I'm after a random date/time between

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

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

2000年1月1日上午10:00:00和下午1点1点至下午5点00:00。

Also, this code will be used in a for loop, with 100 items ... meaning all 100 items will have random date/times between the min/max date/time period.

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

Any ideas?

7 个解决方案

#1


30  

You could try using:

您可以尝试使用:

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

This will give you different times down to the minute. If you want 100 (or any thing more than 1) DateTimes then only create the Random object once. The MSDN page on Random explains in detail why creating several Random objects in quick succession is a bad idea.

这将为您提供不同的时间。如果您想要100(或任何超过1)DateTimes,那么只需创建一次Random对象。 Random上的MSDN页面详细解释了为什么快速连续创建几个Random对象是一个坏主意。

Using a different TimeSpan constructor will give you different granularity. From the TimeSpan constructor MSDN:

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

TimeSpan(Int64) Initializes a new TimeSpan to the specified number of ticks.
TimeSpan(Int32, Int32, Int32) Initializes a new TimeSpan to a specified number of hours, minutes, and seconds.
TimeSpan(Int32, Int32, Int32, Int32) Initializes a new TimeSpan to a specified number of days, hours, minutes, and seconds.
TimeSpan(Int32, Int32, Int32, Int32, Int32) Initializes a new TimeSpan to a specified number of days, hours, minutes, seconds, and milliseconds.

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

#2


3  

Here's my algorithm and code:

这是我的算法和代码:

  • find the difference between the two dates
  • 找到两个日期之间的差异

  • for each iteration, create a random number between the two dates
  • 对于每次迭代,在两个日期之间创建一个随机数

  • create a new date between them. Simply add that random number as minutes to the start datetime.  

    在它们之间创建一个新的日期。只需将该随机数作为分钟添加到开始日期时间。

    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


2  

Really quickly:

  1. convert your dates to TotalHours
  2. 将您的日期转换为TotalHours

  3. Subtract one number from the other and use Abs to make positive
  4. 从另一个数字中减去一个数字并使用Abs来表示正数

  5. Create a random number within the range of 1 and the result of 2. above
  6. 创建一个范围为1的随机数和上面的2.的结果

  7. Add the resulting random number of hours back to the earlier of your two dates
  8. 将得到的随机小时数添加回两个日期的较早时间

#4


1  

First, figure out what the precision is that you want on random DateTime (hours,minutes,seconds,ms,etc).

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

Then figure out the difference between the two dates in that unit.

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

Create a random integer between 0 and that difference.

创建0和该差异之间的随机整数。

Add the random integer in units to the original date.

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

Given the use case you stated above, calculate the difference outside in the for loop.

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

Inside the for loop, get the random int and construct the random date.

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

#5


1  

A one-liner based on ChrisF's solution

基于ChrisF解决方案的单线程

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

#6


1  

This is what I'm using:

这就是我正在使用的:

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://*.com/q/1483670/1698987
        TimeSpan timeSpan = max - min;

        // for random long see: http://*.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;
    }
}

I used the approach in the accepted answer but modified it slightly as I had issues with it.

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

#7


0  

Here's a method using a random number of ticks:

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

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

This method is exclusive the last date and inclusive the first. You can easily include the last date by adding one tick to the basic (endDate - startDate).Ticks quantity.

此方法独占最后一个日期,包含第一个日期。您可以通过向基本(endDate - startDate)添加一个刻度来轻松包含最后一个日期.Ticks数量。

#1


30  

You could try using:

您可以尝试使用:

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

This will give you different times down to the minute. If you want 100 (or any thing more than 1) DateTimes then only create the Random object once. The MSDN page on Random explains in detail why creating several Random objects in quick succession is a bad idea.

这将为您提供不同的时间。如果您想要100(或任何超过1)DateTimes,那么只需创建一次Random对象。 Random上的MSDN页面详细解释了为什么快速连续创建几个Random对象是一个坏主意。

Using a different TimeSpan constructor will give you different granularity. From the TimeSpan constructor MSDN:

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

TimeSpan(Int64) Initializes a new TimeSpan to the specified number of ticks.
TimeSpan(Int32, Int32, Int32) Initializes a new TimeSpan to a specified number of hours, minutes, and seconds.
TimeSpan(Int32, Int32, Int32, Int32) Initializes a new TimeSpan to a specified number of days, hours, minutes, and seconds.
TimeSpan(Int32, Int32, Int32, Int32, Int32) Initializes a new TimeSpan to a specified number of days, hours, minutes, seconds, and milliseconds.

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

#2


3  

Here's my algorithm and code:

这是我的算法和代码:

  • find the difference between the two dates
  • 找到两个日期之间的差异

  • for each iteration, create a random number between the two dates
  • 对于每次迭代,在两个日期之间创建一个随机数

  • create a new date between them. Simply add that random number as minutes to the start datetime.  

    在它们之间创建一个新的日期。只需将该随机数作为分钟添加到开始日期时间。

    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


2  

Really quickly:

  1. convert your dates to TotalHours
  2. 将您的日期转换为TotalHours

  3. Subtract one number from the other and use Abs to make positive
  4. 从另一个数字中减去一个数字并使用Abs来表示正数

  5. Create a random number within the range of 1 and the result of 2. above
  6. 创建一个范围为1的随机数和上面的2.的结果

  7. Add the resulting random number of hours back to the earlier of your two dates
  8. 将得到的随机小时数添加回两个日期的较早时间

#4


1  

First, figure out what the precision is that you want on random DateTime (hours,minutes,seconds,ms,etc).

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

Then figure out the difference between the two dates in that unit.

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

Create a random integer between 0 and that difference.

创建0和该差异之间的随机整数。

Add the random integer in units to the original date.

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

Given the use case you stated above, calculate the difference outside in the for loop.

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

Inside the for loop, get the random int and construct the random date.

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

#5


1  

A one-liner based on ChrisF's solution

基于ChrisF解决方案的单线程

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

#6


1  

This is what I'm using:

这就是我正在使用的:

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://*.com/q/1483670/1698987
        TimeSpan timeSpan = max - min;

        // for random long see: http://*.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;
    }
}

I used the approach in the accepted answer but modified it slightly as I had issues with it.

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

#7


0  

Here's a method using a random number of ticks:

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

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

This method is exclusive the last date and inclusive the first. You can easily include the last date by adding one tick to the basic (endDate - startDate).Ticks quantity.

此方法独占最后一个日期,包含第一个日期。您可以通过向基本(endDate - startDate)添加一个刻度来轻松包含最后一个日期.Ticks数量。