C#のランダムな日付


141

1995年1月1日から現在の日付までの間にランダムな日付を生成する、簡潔で最新のC#コードを探しています。

Enumerable.Rangeを利用するいくつかのソリューションは、どういうわけかこれをより簡潔にするかもしれないと考えています。


範囲間のランダムなDateTimeで回答-統一されいない出力にはFrom / To日付パラメーターを持つヘルパーメソッドがあります
Michael Freidgeim

回答:


241
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)変数を作成します。


1
ランダムは疑似ランダムのみです。本当にランダムが必要な場合は、System.Security.Cryptography名前空間のRNGCryptoServiceProviderを使用してみてください。
tvanfosson 2008年

ありがとうtvanfosson。この問題には、疑似ランダムで十分です。
ユダガブリエルヒマンゴ08年

5
実際、ランダムは、インスタンスをしばらくの間保持し続け、値を取得しない限り、特に疑似ランダムでさえありません。
David Mitchell、

2
これが、本番コードではなくサンプルにすぎない理由です。
Joel Coehoorn、2008年

1
うん、それは私にとってはうまくいきます。実際のコードでは、メソッド自体の外側にRandomインスタンスが含まれます。
ユダガブリエルヒマンゴ2009年

25

これは、やや最適化されたバージョンの作成に関する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));
}

これがどのように有益かを説明できますか?代わりに、開始、生成、および範囲をクラスメンバーにできませんでしたか?
マークA.ニコロージ

彼らは可能であり、この場合はそうです。これにより、start、gen、およびrangeをメンバーとして含むクラスである語彙的クロージャが生成されます。これはもっと簡潔です。
JaredPar 2008年

ニースの機能は、私はちょうど誰もとしてそれを使用しようとしていないことを願っています:for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
Aidiakapi

2
この機能はどのように使用されますか、誰か説明できますか?どうやって呼べばいいの?
BurakKarakuş16年

2
@BurakKarakuş:最初にファクトリを取得し、var getRandomDate = RandomDayFunc();次にそれを呼び出してランダムな日付を取得します。var randomDate = getRandomDate();これがJoelの回答よりも役立つようにするには、getRandomDateを再利用する必要があることに注意してください。
–ŞafakGür2018

8

私は@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());
}

なぜRandom()を2回作成するのですか?クラス変数gen宣言で一度、他の時間でc-torで?
ピクセル

ええ、一度で十分です。それを私が直した。
壮大な2017

1
それは秒の1つだけ乱数を生成し、あなたの開始日にそれを追加して4倍の速さについてです:range = (int)(DateTime.Today - start).TotalSeconds;return start.AddSeconds(gen.Next(range));
ジャージー

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)
        yield return  start.AddDays(gen.Next(range));        
}

次のように使用できます。

int i=0;
foreach(DateTime dt in RandomDay())
{
    Console.WriteLine(dt);
    if (++i == 10)
        break;
}

1
イテレータとジェネレータ関数の間で考慮すべき1つのことは、イテレータソリューションがIDisposable値を生成することです。これにより、呼び出し元は、ファイナライザをGCに常駐させるコストを処分または支払う必要があります。ジェネレーターは処分する必要はありません
JaredPar '12年

2
@JaredPar、それは正しくありません。型がIDisposableを実装しているからといって、それがファイナライズ可能であるとは限りません。
Drew Noakes、

3

固定日付オブジェクト(1995年1月1日)から始め、AddDaysを使用してランダムな日数を追加します(当然、現在の日付を超えないように注意してください)。


ありがとうFriol。ランダムに渡される数を制限する方法を尋ねるつもりでした。Joelはコードサンプルの例を投稿しているので、彼の応答を回答としてマークします。
ユダガブリエルヒマンゴ08年

0

私は少し遅れていますが、うまくいく解決策が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;
            }
        }
    }

0

いくつかの単純な入力パラメーターに基づいて、ランダムな日付を文字列として返す小さなメソッド。上記の回答のバリエーションに基づいて構築されています:

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);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.