Случайная дата в C # - PullRequest
128 голосов
/ 12 октября 2008

Я ищу краткий современный код C # для генерации случайной даты между 1 января 1995 года и текущей датой.

Я думаю, что какое-то решение, которое использует Enumerable.Range, может сделать это более кратким.

Ответы [ 6 ]

214 голосов
/ 12 октября 2008
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));
}

Для повышения производительности, если он будет вызываться повторно, создайте переменные start и gen (и, возможно, даже range) вне функции.

21 голосов
/ 12 октября 2008

Это небольшой ответ на комментарий Джоэла о создании более оптимизированной версии. Вместо того, чтобы возвращать случайную дату напрямую, почему бы не вернуть функцию генератора, которая может вызываться повторно для создания случайной даты.

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));
}
6 голосов
/ 08 октября 2014

Я взял ответ @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());
}
5 голосов
/ 12 октября 2008

Что ж, если вы собираетесь представить альтернативную оптимизацию, мы также можем использовать итератор:

 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;
}
3 голосов
/ 12 октября 2008

Начните с объекта с фиксированной датой (1 января 1995 г.) и добавьте случайное количество дней с AddDays (очевидно, обратите внимание, не превышая текущую дату).

0 голосов
/ 14 ноября 2018

Я немного опоздал с игрой, но вот одно решение, которое работает отлично:

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