What's the best practice for getting a random

2020-05-25 08:04发布

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

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.

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.

Any ideas?

7条回答
成全新的幸福
2楼-- · 2020-05-25 08:04

Really quickly:

  1. convert your dates to TotalHours
  2. Subtract one number from the other and use Abs to make positive
  3. Create a random number within the range of 1 and the result of 2. above
  4. Add the resulting random number of hours back to the earlier of your two dates
查看更多
聊天终结者
3楼-- · 2020-05-25 08:05

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));
    }
    
查看更多
你好瞎i
4楼-- · 2020-05-25 08:05

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.

查看更多
趁早两清
5楼-- · 2020-05-25 08:13

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

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

查看更多
干净又极端
6楼-- · 2020-05-25 08:23

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

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

Create a random integer between 0 and that difference.

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.

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

查看更多
爷的心禁止访问
7楼-- · 2020-05-25 08:23

A one-liner based on ChrisF's solution

var newDate = startDate.AddHours(new Random(Convert.ToInt32(DateTime.Now.Ticks / int.MaxValue)).Next(0, (int)(endDate - startDate).TotalHours));
查看更多
登录 后发表回答