Какая наилучшая практика для получения случайного DateTime между двумя датами?
Я пытаюсь рандомизировать значение для простого поля данных DateTime
.
Я хочу получить случайную дату/время между двумя датами/временем (например, min date/time и max date/time).
Итак, представьте себе, что я после случайной даты/времени между
1/1/2000 10:00:00am
и 1/1/2000 5:00:00pm
.
Кроме того, этот код будет использоваться в цикле for, с 100 элементами... что означает, что все 100 элементов будут иметь случайную дату/время между минимальным/максимальным периодом даты/времени.
Любые идеи?
Ответы
Ответ 1
Вы можете попробовать:
TimeSpan timeSpan = endDate - startDate;
var randomTest = new Random();
TimeSpan newSpan = new TimeSpan(0, randomTest.Next(0, (int)timeSpan.TotalMinutes), 0);
DateTime newDate = startDate + newSpan;
Это даст вам разное время до минуты. Если вам нужно 100 (или любая вещь более 1) DateTime
, то только создайте объект Random
один раз. Страница конструктор MSDN времени TimeSpan:
TimeSpan (Int64). Инициализирует новый TimeSpan для указанного количества тиков.
TimeSpan (Int32, Int32, Int32). Инициализирует новый TimeSpan до заданного количества часов, минут и секунд.
TimeSpan (Int32, Int32, Int32, Int32) Инициализирует новый TimeSpan до указанного количества дней, часов, минут и секунд.
TimeSpan (Int32, Int32, Int32, Int32, Int32). Инициализирует новый TimeSpan до заданного количества дней, часов, минут, секунд и миллисекунд.
Ответ 2
Здесь мой алгоритм и код:
- найдите разницу между двумя датами
- для каждой итерации создайте случайное число между двумя датами
-
создать новую дату между ними. Просто добавьте это случайное число как минут в начало 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 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
Действительно быстро:
- конвертировать ваши даты в TotalHours
- Вычтите одно число из другого и используйте Abs, чтобы сделать положительный
- Создайте случайное число в диапазоне 1 и результат 2. выше
- Добавьте полученное случайное число часов назад к более ранним из двух дат.
Ответ 4
Сначала выясните, какая точность вы хотите в случайном DateTime (часы, минуты, секунды, мс и т.д.).
Затем определите разницу между двумя датами в этом блоке.
Создайте случайное целое число от 0 до этой разницы.
Добавьте случайное целое число в единицы к исходной дате.
Учитывая используемый вами вариант использования, вы указали выше, вычислите разницу вне в цикле for.
Внутри цикла for получить случайный int и построить случайную дату.
Ответ 5
Это то, что я использую:
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;
}
}
Я использовал подход в принятом ответе, но немного изменил его, поскольку у меня были проблемы с ним.
Ответ 6
Однострочный фильтр на основе решения ChrisF
var newDate = startDate.AddHours(new Random(Convert.ToInt32(DateTime.Now.Ticks / int.MaxValue)).Next(0, (int)(endDate - startDate).TotalHours));
Ответ 7
Здесь используется метод с использованием случайного числа тиков:
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);
Этот метод является исключительной последней датой и включает первый. Вы можете легко включить последнюю дату, добавив по одному тику к базовому количеству (endDate - startDate).Ticks
.