1995年1月1日から現在の日付までの間にランダムな日付を生成する、簡潔で現代的なC#コードを探しています。
私は、Enumerable.Rangeを利用するソリューションが何らかの形でこれをより簡潔にするかもしれないと考えています。
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
)変数outsideを作成します。
これは、少し最適化されたバージョンを作成するという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));
}
@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個のランダムなDateTimeを書き込む方法の例:
RandomDateTime date = new RandomDateTime();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(date.Next());
}
代替の最適化を提示する場合は、イテレーターを使用することもできます。
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;
}
固定日付オブジェクト(1995年1月1日)から開始し、AddDaysでランダムな日数を追加します(当然、現在の日付を超えないように注意してください)。
私はゲームに少し遅れていますが、ここでうまくいく1つの解決策があります:
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;
}
}
}