150 votes

Date aléatoire en C#

Je cherche un code C# succinct et moderne pour générer une date aléatoire entre le 1er janvier 1995 et la date actuelle.

Je pense qu'une solution qui utilise Enumerable.Range d'une manière ou d'une autre pourrait rendre cela plus succinct.

0 votes

Réponse en DateTime aléatoire entre deux plages - sortie non unifiée a une méthode d'aide avec les paramètres de date "From/To".

260voto

Joel Coehoorn Points 190579
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));
}

Pour de meilleures performances, si cette fonction est appelée de manière répétée, créez l'attribut start y gen (et peut-être même range ) variables à l'extérieur de de la fonction.

1 votes

Le caractère aléatoire n'est que pseudo-aléatoire. Si vous avez besoin d'un caractère vraiment aléatoire, essayez d'utiliser RNGCryptoServiceProvider de l'espace de noms System.Security.Cryptography.

0 votes

Merci tvanfosson. Le pseudo-aléatoire est suffisant pour ce problème.

6 votes

En fait, Random n'est même pas particulièrement pseudo-aléatoire, à moins que vous ne conserviez l'instance pendant un certain temps et que vous continuiez à en tirer des valeurs.

28voto

JaredPar Points 333733

Ceci est une légère réponse au commentaire de Joel concernant la création d'une version légèrement plus optimisée. Au lieu de renvoyer directement une date aléatoire, pourquoi ne pas renvoyer une fonction de générateur qui peut être appelée à plusieurs reprises pour créer une date aléatoire.

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 votes

Pouvez-vous expliquer en quoi cela est bénéfique ? Start, Gen et Range ne pourraient-ils pas être des membres de la classe à la place ?

0 votes

Ils pourraient et dans ce cas, ils le font. Sous le capot, cela va générer une fermeture lexicale qui est une classe contenant start, gen et range comme membres. C'est simplement plus concis.

3 votes

Belle fonction, j'espère juste que personne ne l'utilisera comme.. : for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }

13voto

prespic Points 984

J'ai pris la réponse de @Joel Coehoorn et fait les changements qu'il a conseillés - mettre la variable hors de la méthode et mettre tout en classe. De plus, l'heure est maintenant aléatoire aussi. Voici le résultat.

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

Et un exemple d'utilisation pour écrire 100 DateTimes aléatoires dans la console :

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

5voto

James Curran Points 55356

Eh bien, si vous voulez présenter une autre optimisation, nous pouvons aussi opter pour un itérateur :

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

vous pourriez l'utiliser comme ceci :

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

1 votes

Une chose à considérer entre un itérateur et une fonction de générateur est que la solution de l'itérateur produira une valeur IDisposable. Cela oblige l'appelant à se débarrasser de la valeur ou à payer le prix de la présence d'un finisseur dans la GC. Le générateur n'a pas besoin de disposer

2 votes

@JaredPar, ce n'est pas tout à fait exact. Ce n'est pas parce qu'un type implémente IDisposable qu'il est finalisable.

3voto

friol Points 4806

Commencez avec un objet à date fixe (1er janvier 1995), et ajoutez un nombre aléatoire de jours avec AddDays (évidemment, faites attention à ne pas dépasser la date actuelle).

0 votes

Merci Friol. J'allais demander comment limiter le nombre passé en aléatoire. Joel a posté un exemple avec un extrait de code, je vais donc marquer sa réponse comme étant la réponse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X