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));
}
Для повышения производительности, если это будет вызываться многократно, создайте переменные startand gen(и, возможно, даже range) вне функции.
Случайное - только псевдослучайное. Если вам нужен действительно случайный, попробуйте использовать RNGCryptoServiceProvider из пространства имен System.Security.Cryptography.
tvanfosson
Спасибо tvanfosson. Для этой задачи достаточно псевдослучайной последовательности.
Иуда Габриэль Химанго
5
Фактически, Random даже не является особенно псевдослучайным, если вы не держите экземпляр какое-то время и продолжаете получать из него значения.
Дэвид Митчелл,
2
Вот почему это всего лишь образец, а не производственный код.
Джоэл Кохорн,
1
Да, это работает для меня; мой реальный код будет иметь экземпляр Random вне самого метода.
Иуда Габриэль Химанго 01
26
Это небольшой ответ на комментарий Джоэла о том, чтобы сделать немного более оптимизированную версию. Вместо того, чтобы напрямую возвращать случайную дату, почему бы не вернуть функцию генератора, которую можно вызывать повторно для создания случайной даты.
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));
}
Вы можете объяснить, чем это выгодно? Не могли бы вместо этого быть членами класса start, gen и range?
Марк А. Николози,
Могли, и в данном случае они есть. Под капотом это сгенерирует лексическое замыкание, которое является классом, содержащим start, gen и range в качестве членов. Это просто более кратко.
JaredPar
Хорошая функция, я просто надеюсь, что никто не будет использовать ее как:for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
Aidiakapi
2
Как эта функция используется, кто-нибудь может объяснить? Я имею в виду, как я могу это назвать?
Бурак Каракуш
2
@ BurakKarakuş: Сначала вы получаете фабрику: var getRandomDate = RandomDayFunc();затем вы вызываете ее, чтобы получить случайные даты: var randomDate = getRandomDate();Помните, что вам нужно повторно использовать getRandomDate, чтобы это было более полезным, чем ответ Джоэла.
Шафак Гюр
9
Я взял ответ @Joel Coehoorn и внес изменения, которые он посоветовал - убрать переменную из метода и поместить все в класс. Плюс теперь время тоже случайное. Вот результат.
classRandomDateTime
{
DateTime start;
Random gen;
int range;
publicRandomDateTime()
{
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?
пиксель
Да, одного раза достаточно. Я починил это.
prespic
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)
yieldreturn start.AddDays(gen.Next(range));
}
вы можете использовать это так:
int i=0;
foreach(DateTime dt inRandomDay())
{
Console.WriteLine(dt);
if (++i == 10)
break;
}
При выборе между итератором и функцией генератора следует учитывать, что решение итератора будет выдавать значение IDisposable. Это вынуждает вызывающий объект избавиться от него или заплатить цену за наличие финализатора в GC. Генератор не требует утилизации
JaredPar
2
@JaredPar, это не совсем так. Тот факт, что тип реализует IDisposable, не означает, что его можно завершить.
Дрю Ноукс,
3
Начните с объекта с фиксированной датой (1 января 1995 г.) и добавьте случайное количество дней с помощью AddDays (очевидно, обратите внимание, не превышайте текущую дату).
Спасибо, Фриоль. Я собирался спросить, как ограничить число, переданное в случайное. Джоэл опубликовал пример с образцом кода, поэтому я отмечу его ответ как ответ.
Иуда Габриэль Химанго
0
Я немного опоздал в игру, но вот одно решение, которое отлично работает:
voidMain()
{
var dateResult = GetRandomDates(new DateTime(1995, 1, 1), DateTime.UtcNow, 100);
foreach (var r in dateResult)
Console.WriteLine(r);
}
publicstatic 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;
}
publicstatic IEnumerable<int> GetRandomNumbers(int size)
{
var data = newbyte[4];
using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider(data))
{
for (int i = 0; i < size; i++)
{
rng.GetBytes(data);
varvalue = BitConverter.ToInt32(data, 0);
yieldreturnvalue < 0 ? value * -1 : value;
}
}
}
Небольшой метод, который возвращает случайную дату в виде строки на основе некоторых простых входных параметров. Построен на основе вариантов из приведенных выше ответов:
publicstringRandomDate(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);
}
Ответы:
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
andgen
(и, возможно, дажеrange
) вне функции.источник
Это небольшой ответ на комментарий Джоэла о том, чтобы сделать немного более оптимизированную версию. Вместо того, чтобы напрямую возвращать случайную дату, почему бы не вернуть функцию генератора, которую можно вызывать повторно для создания случайной даты.
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)); }
источник
for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
var getRandomDate = RandomDayFunc();
затем вы вызываете ее, чтобы получить случайные даты:var randomDate = getRandomDate();
Помните, что вам нужно повторно использовать getRandomDate, чтобы это было более полезным, чем ответ Джоэла.Я взял ответ @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()); }
источник
range = (int)(DateTime.Today - start).TotalSeconds;
иreturn start.AddSeconds(gen.Next(range));
.Что ж, если вы собираетесь представить альтернативную оптимизацию, мы также можем использовать итератор:
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 января 1995 г.) и добавьте случайное количество дней с помощью AddDays (очевидно, обратите внимание, не превышайте текущую дату).
источник
Я немного опоздал в игру, но вот одно решение, которое отлично работает:
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; } } }
источник
Небольшой метод, который возвращает случайную дату в виде строки на основе некоторых простых входных параметров. Построен на основе вариантов из приведенных выше ответов:
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); }
источник