C # 中的随机日期

我正在寻找一些简洁、现代的 C # 代码,以生成1995年1月1日至当前日期之间的随机日期。

我在考虑一种利用 Enumable 的解决方案。

125204 次浏览

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

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)变量 在外面

这是对 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));
}

如果你要提出替代优化,我们也可以使用迭代器:

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

我已经采纳了@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个随机日期时间写入控制台的示例:

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

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

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

基于@Jeremy Thompson 的解决方案的有用扩展

public static class RandomExtensions
{
public static DateTime Next(this Random random, DateTime start, DateTime? end = null)
{
end ??= new DateTime();
int range = (end.Value - start).Days;
return start.AddDays(random.Next(range));
}
}
Random rnd = new Random();
DateTime datetoday = DateTime.Now;


int rndYear = rnd.Next(1995, datetoday.Year);
int rndMonth = rnd.Next(1, 12);
int rndDay = rnd.Next(1, 31);


DateTime generateDate = new DateTime(rndYear, rndMonth, rndDay);
Console.WriteLine(generateDate);

//这可能不是最好的方法,但是很快,很容易理解

这个问题的另一个解决方案是,这次使用一个类,您可以为其提供一个需要日期的范围。结果只剩下随机的几分钟。

/// <summary>
/// A random date/time class that provides random dates within a given range
/// </summary>
public class RandomDateTime
{
private readonly Random rng = new Random();
private readonly int totalMinutes;
private readonly DateTime startDateTime;


/// <summary>
/// Initializes a new instance of the <see cref="RandomDateTime"/> class.
/// </summary>
/// <param name="startDate">The start date.</param>
/// <param name="endDate">The end date.</param>
public RandomDateTime(DateTime startDate, DateTime endDate)
{
this.startDateTime = startDate;
TimeSpan timeSpan = endDate - startDate;
this.totalMinutes = (int)timeSpan.TotalMinutes;
}


/// <summary>
/// Gets the next random datetime object within the range of startDate and endDate provided in the ctor
/// </summary>
/// <returns>A DateTime.</returns>
public DateTime NextDateTime
{
get
{
TimeSpan newSpan = new TimeSpan(0, rng.Next(0, this.totalMinutes), 0);
return this.startDateTime + newSpan;
}
}
}

像这样用它吐出2020年1月1日到2022年12月31日之间的5个随机日期:

RandomDateTime rdt = new RandomDateTime(DateTime.Parse("01/01/2020"), DateTime.Parse("31/12/2022"));


for (int i = 0; i < 5; i++)
Debug.WriteLine(rdt.NextDateTime);