C#中的随机日期


Answers:


240
private Random gen = new Random();
DateTime RandomDay()
{
    DateTime start = new DateTime(1995, 1, 1);
    int range = (DateTime.Today - start).Days;           
    return start.AddDays(gen.Next(range));
}

为了获得更好的性能,如果将其重复调用,请在函数外部创建startgen(甚至是range)变量。


1
随机只是伪随机。如果需要真正的随机性,请尝试使用System.Security.Cryptography命名空间中的RNGCryptoServiceProvider。
tvanfosson

感谢tvanfosson。伪随机足以解决此问题。
Judah Gabriel Himango

5
实际上,除非您将实例保留一段时间并不断从中获取值,否则Random甚至都不是伪随机的。
大卫·米切尔

2
这就是为什么这只是示例而不是生产代码的原因。
Joel Coehoorn

1
是的,对我有用。我的真实世界代码将在方法本身之外具有Random实例。
Judah Gabriel Himango,2009年

25

这是对Joel关于制作更好的优化版本的评论的轻微回应。与其直接返回一个随机日期,不如返回一个生成器函数,可以重复调用该函数以创建一个随机日期。

Func<DateTime> RandomDayFunc()
{
    DateTime start = new DateTime(1995, 1, 1); 
    Random gen = new Random(); 
    int range = ((TimeSpan)(DateTime.Today - start)).Days; 
    return () => start.AddDays(gen.Next(range));
}

您能解释一下这有什么好处吗?无法开始,生成和生成班级成员吗?
Mark A. Nicolosi's

他们可以,在这种情况下,他们可以。在引擎盖下,这将生成一个词法闭包,这是一个包含成员start,gen和range的词汇。这只是更简洁。
JaredPar

好的功能,我只是希望没有人将其用作:for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
Aidiakapi 2014年

2
此功能如何使用,有人可以解释一下吗?我的意思是怎么称呼它?
BurakKarakuş16年

2
@BurakKarakuş:首先得到一个工厂:var getRandomDate = RandomDayFunc();然后调用它来获取随机日期:var randomDate = getRandomDate();记住,您需要重用getRandomDate,以使其比Joel的答案更有用。
Şafak古尔

8

我接受了@Joel Coehoorn的回答,并做了他建议的更改-将变量从方法中排除,并将其全部放在类中。再加上现在时间也是随机的。这是结果。

class RandomDateTime
{
    DateTime start;
    Random gen;
    int range;

    public RandomDateTime()
    {
        start = new DateTime(1995, 1, 1);
        gen = new Random();
        range = (DateTime.Today - start).Days;
    }

    public DateTime Next()
    {
        return start.AddDays(gen.Next(range)).AddHours(gen.Next(0,24)).AddMinutes(gen.Next(0,60)).AddSeconds(gen.Next(0,60));
    }
}

以及示例如何使用100个随机的DateTimes编写控制台:

RandomDateTime date = new RandomDateTime();
for (int i = 0; i < 100; i++)
{
    Console.WriteLine(date.Next());
}

为什么要创建两次Random()?一次在类中生成gen声明,而其他时间在c-tor中?
像素像素

是的,一次就足够了。我修好了它。
9:30

1
仅生成一个随机秒数并将其添加到您的开始日期大约要快四倍:range = (int)(DateTime.Today - start).TotalSeconds;return start.AddSeconds(gen.Next(range));
Jurgy

5

好吧,如果您要提出替代性优化,我们也可以选择迭代器:

 static IEnumerable<DateTime> RandomDay()
 {
    DateTime start = new DateTime(1995, 1, 1);
    Random gen = new Random();
    int range = ((TimeSpan)(DateTime.Today - start)).Days;
    while (true)
        yield return  start.AddDays(gen.Next(range));        
}

您可以这样使用它:

int i=0;
foreach(DateTime dt in RandomDay())
{
    Console.WriteLine(dt);
    if (++i == 10)
        break;
}

1
在迭代器与生成器函数之间要考虑的一件事是,迭代器解决方案将产生IDisposable值。这迫使调用者处置或支付在GC中启用终结器的代价。发电机无需处置
JaredPar

2
@JaredPar,那不是很正确。仅仅因为一个类型实现IDisposable并不意味着它是可终结的。
德鲁·诺阿克斯

3

从固定日期对象开始(1995年1月1日),然后使用AddDays添加随机天数(显然,请注意不要超过当前日期)。


感谢Friol。我要问如何限制随机数。Joel发布了一个带有代码示例的示例,因此我将其回答标记为答案。
Judah Gabriel Himango

0

我玩游戏有点迟了,但是这里有一个很好的解决方案:

    void Main()
    {
        var dateResult = GetRandomDates(new DateTime(1995, 1, 1), DateTime.UtcNow, 100);
        foreach (var r in dateResult)
            Console.WriteLine(r);
    }

    public static IList<DateTime> GetRandomDates(DateTime startDate, DateTime maxDate, int range)
    {
        var randomResult = GetRandomNumbers(range).ToArray();

        var calculationValue = maxDate.Subtract(startDate).TotalMinutes / int.MaxValue;
        var dateResults = randomResult.Select(s => startDate.AddMinutes(s * calculationValue)).ToList();
        return dateResults;
    }

    public static IEnumerable<int> GetRandomNumbers(int size)
    {
        var data = new byte[4];
        using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider(data))
        {
            for (int i = 0; i < size; i++)
            {
                rng.GetBytes(data);

                var value = BitConverter.ToInt32(data, 0);
                yield return value < 0 ? value * -1 : value;
            }
        }
    }

0

一种小型方法,它基于一些简单的输入参数以字符串形式返回随机日期。基于以上答案的变体构建:

public string RandomDate(int startYear = 1960, string outputDateFormat = "yyyy-MM-dd")
{
   DateTime start = new DateTime(startYear, 1, 1);
   Random gen = new Random(Guid.NewGuid().GetHashCode());
   int range = (DateTime.Today - start).Days;
   return start.AddDays(gen.Next(range)).ToString(outputDateFormat);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.