2008-10-12 71 views
110

Estoy buscando un código C# sucinto y moderno para generar una fecha aleatoria entre el 1 de enero de 1995 y la fecha actual.Fecha aleatoria en C#

Estoy pensando en alguna solución que utiliza Enumerable.Range de alguna manera puede hacer esto más breve.

+0

respuesta en [aleatoria entre DateTime gama - salida no unificado] (http://stackoverflow.com/a/14511053) tiene un método de ayuda con los parámetros Desde/hasta la fecha –

Respuesta

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

Para un mejor rendimiento si esto va a ser llamado en repetidas ocasiones, crear el start y gen (e incluso tal vez range) las variables externas de la función.

+0

Aleatorio es solo pseudoaleatorio. Si realmente necesita algo aleatorio, intente utilizar RNGCryptoServiceProvider desde el espacio de nombres System.Security.Cryptography. – tvanfosson

+0

Gracias tvanfosson. Pseudoaleatorio es suficiente para este problema. –

+5

En realidad, Random ni siquiera es particularmente pseudoaleatorio a menos que mantenga la instancia por un tiempo y continúe obteniendo valores de ella. –

3

Comience con un objeto de fecha fijo (1 de enero de 1995) y agregue un número aleatorio de días con AddDays (obviamente, preste atención que no sobrepase la fecha actual).

+0

Gracias Friol. Iba a preguntar cómo limitar el número pasado al azar. Joel ha publicado un ejemplo con una muestra de código, por lo que marcaré su respuesta como la respuesta. –

18

Esto es en ligera respuesta al comentario de Joel sobre hacer una versión ligeramente más optimizada. En lugar de devolver una fecha aleatoria directamente, ¿por qué no devuelve una función de generador que puede repetirse para crear una fecha aleatoria?

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

¿Puedes explicarme cómo esto es beneficioso? No se pudo iniciar, gen y rango ser miembros de la clase en su lugar? –

+0

Podrían y en este caso lo son. Debajo del capó esto generará un cierre léxico que es un clrass que contiene inicio, gen y rango como miembros.Esto es solo más conciso. – JaredPar

+0

Bonita encapsulación. –

4

Bueno, si usted va a la optimización presente alternativo, podemos también ir para un iterador:

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

se podría utilizar de esta manera:

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

Una cosa a considerar entre un iterador frente a una función del generador es que la solución del iterador producirá un valor IDisposable. Esto obliga a la persona que llama a deshacerse o pagar el precio de tener un finalizador en vivo en el GC. El generador no necesita eliminar – JaredPar

+1

@JaredPar, eso no está del todo bien. El hecho de que un tipo implemente IDisposable no significa que sea finalizable. –

5

he tomado @ Joel Coehoorn respondió e hizo los cambios que él aconsejó: coloque la variable fuera del método y ponga todo en clase. Además, ahora el tiempo también es aleatorio. Aquí está el resultado.

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

Y ejemplo de cómo utilizar para escribir 100 DateTime al azar a la consola:

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

¿Por qué creas Random() dos veces? Una vez en clase, declaración de gen variable y otro tiempo en el c-tor? – pixel

+0

Sí, una vez es suficiente. Lo arreglé. – prespic