views:

3409

answers:

5
+8  Q: 

Random date in C#

I'm looking for some succinct C# 3 code to generate a random date between Jan 1 1995 and the current date.

I'm thinking some solution that utilizes Enumerable.Range somehow may make this more succinct.

+1  A: 

Start with a fixed date object (Jan 1, 1995), and add a random number of days with AddDays (obviusly, pay attention not surpassing the current date).

friol
Thanks Friol. I was gonna ask how to limit the number passed into random. Joel has posted an example with code sample, so I'll mark his response as the answer.
Judah Himango
+24  A: 
    DateTime RandomDay()
    {
        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 better performance if this will be called repeatedly, create the start and gen (and maybe even range) variables outside of the function.

Joel Coehoorn
Thanks, Joel! That's what I was looking for.
Judah Himango
Random is only pseudo-random. If you need truly random, try using RNGCryptoServiceProvider from the System.Security.Cryptography namespace.
tvanfosson
Thanks tvanfosson. Pseudo-random is sufficient for this problem.
Judah Himango
Actually, Random isn't even particularly pseudo-random unless you keep the instance around for a while and keep getting values out of it.
David Mitchell
+1 for David's comment. If you call the above method twice in quick succession then it's more than likely to return the same value. The Random constructor above uses the current time as a seed, which is DateTime.Now. That value only increments every 15 milliseconds. A field would be better.
Drew Noakes
Which is why this is only a sample, rather than production code.
Joel Coehoorn
Yep, that works for me; my real-world code will have the Random instance outside the method itself.
Judah Himango
+1  A: 

This is in slight response to Joel's comment about making a slighly more optimized version. Instead of returning a random date directly, why not return a generator function which can be called repeatedly to create a random date.



        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));
        }
JaredPar
Can you explain how this is beneficial? Couldn't start, gen, and range be class members instead?
Mark A. Nicolosi
They could and in this case they are. Under the hood this will generate a lexical closure which is a clrass containing start,gen and range as members. This is just more concise.
JaredPar
Nice encapsulation.
Drew Noakes
+1  A: 

Well, if you gonna present alternate optimization, we can also go for an iterator:

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

you could use it like this:

int i=0;
foreach(DateTime dt in RandomDay())
{
    Console.WriteLine(dt);
    if (++i == 10)
     break;
}
James Curran
One thing to consider between an iterator vs. a generator function is that the iterator solution will produce an IDisposable value. This forces the caller to dispose or pay the price of having a finalizer live in the GC. The generator needs no disposing
JaredPar
@JaredPar, that's not quite right. Just because a type implements IDisposable does not mean it is finalizable.
Drew Noakes
+1  A: 
// Chosen by a random dice roll. Guaranteed to be random.
return DateTime.Parse("10/07/2001");

That's the problem with random numbers, you can never be sure.

tsilb
gave it an upvote for making me laugh
Kevin
http://xkcd.com/221/http://content3.clipmarks.com/image_cache/xofxof/512/405B2A78-5499-474D-89B9-17F420F175C5.gifFunny things are funny, but probably better served as a comment to the original post so as not to add noise to serious answers ;p
ICR
Ah, touché.
tsilb