privateRandom gen =newRandom();DateTimeRandomDay(){DateTime start =newDateTime(1995,1,1);int range =(DateTime.Today- start).Days;return start.AddDays(gen.Next(range));}
Pour de meilleures performances si cela est appelé à plusieurs reprises, créez les variables startand gen(et peut-être même range) en dehors de la fonction.
L'aléatoire n'est que pseudo-aléatoire. Si vous avez besoin de vraiment aléatoire, essayez d'utiliser RNGCryptoServiceProvider à partir de l'espace de noms System.Security.Cryptography.
tvanfosson
Merci tvanfosson. Le pseudo-aléatoire est suffisant pour ce problème.
Judah Gabriel Himango
5
En fait, Random n'est même pas particulièrement pseudo-aléatoire à moins que vous ne gardiez l'instance pendant un moment et que vous continuiez à en tirer des valeurs.
David Mitchell
2
C'est pourquoi il ne s'agit que d'un exemple plutôt que d'un code de production.
Joel Coehoorn
1
Oui, cela fonctionne pour moi; mon code réel aura l'instance Random en dehors de la méthode elle-même.
Judah Gabriel Himango
25
C'est en légère réponse au commentaire de Joel sur 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 =newDateTime(1995,1,1);Random gen =newRandom();int range =((TimeSpan)(DateTime.Today- start)).Days;return()=> start.AddDays(gen.Next(range));}
Pouvez-vous expliquer en quoi cela est bénéfique? Le début, la génération et la plage ne pourraient-ils pas être des membres de la classe à la place?
Mark A. Nicolosi
Ils pourraient et dans ce cas ils le sont. Sous le capot, cela générera une fermeture lexicale qui est une classe contenant start, gen et range comme membres. C'est juste plus concis.
JaredPar
Belle fonction, j'espère juste que personne ne l'utilisera comme:for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
Aidiakapi
2
Comment cette fonction est-elle utilisée, quelqu'un peut-il expliquer? Je veux dire comment puis-je l'appeler?
Burak Karakuş
2
@ BurakKarakuş: Vous obtenez d'abord une usine: var getRandomDate = RandomDayFunc();puis vous l'appelez pour obtenir des dates aléatoires: var randomDate = getRandomDate();sachez que vous devez réutiliser getRandomDate pour que cela soit plus utile que la réponse de Joel.
Şafak Gür
8
J'ai pris la réponse de @Joel Coehoorn et apporté les modifications qu'il m'a conseillées - mettre la variable hors de la méthode et tout mettre en classe. De plus, maintenant, le temps est également aléatoire. Voici le résultat.
classRandomDateTime{DateTime start;Random gen;int range;publicRandomDateTime(){
start =newDateTime(1995,1,1);
gen =newRandom();
range =(DateTime.Today- start).Days;}publicDateTimeNext(){return start.AddDays(gen.Next(range)).AddHours(gen.Next(0,24)).AddMinutes(gen.Next(0,60)).AddSeconds(gen.Next(0,60));}}
Et exemple comment utiliser pour écrire 100 DateTimes aléatoires sur la console:
RandomDateTime date =newRandomDateTime();for(int i =0; i <100; i++){Console.WriteLine(date.Next());}
Pourquoi créez-vous Random () deux fois? Une fois dans la déclaration de génération de variable de classe et autre fois dans le c-tor?
pixel
Ouais, une fois suffit. Je l'ai corrigé.
prépic
1
Il est environ quatre fois plus rapide de générer un seul nombre aléatoire de secondes et de l'ajouter à votre date de début: range = (int)(DateTime.Today - start).TotalSeconds;et return start.AddSeconds(gen.Next(range));.
Jurgy
5
Eh bien, si vous voulez présenter une optimisation alternative, nous pouvons également opter pour un itérateur:
staticIEnumerable<DateTime>RandomDay(){DateTime start =newDateTime(1995,1,1);Random gen =newRandom();int range =((TimeSpan)(DateTime.Today- start)).Days;while(true)yieldreturn start.AddDays(gen.Next(range));}
vous pouvez l'utiliser comme ceci:
int i=0;foreach(DateTime dt inRandomDay()){Console.WriteLine(dt);if(++i ==10)break;}
Une chose à considérer entre un itérateur et une fonction de générateur est que la solution d'itérateur produira une valeur IDisposable. Cela oblige l'appelant à disposer ou à payer le prix d'avoir un finaliseur en direct dans le GC. Le générateur n'a pas besoin d'être éliminé
JaredPar
2
@JaredPar, ce n'est pas tout à fait vrai. Ce n'est pas parce qu'un type implémente IDisposable qu'il est finalisable.
Drew Noakes
3
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).
Merci Friol. J'allais demander comment limiter le nombre passé au hasard. Joel a publié un exemple avec un exemple de code, donc je marquerai sa réponse comme réponse.
Judah Gabriel Himango
0
Je suis un peu en retard dans le jeu, mais voici une solution qui fonctionne bien:
voidMain(){var dateResult =GetRandomDates(newDateTime(1995,1,1),DateTime.UtcNow,100);foreach(var r in dateResult)Console.WriteLine(r);}publicstaticIList<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;}publicstaticIEnumerable<int>GetRandomNumbers(int size){var data =newbyte[4];
using (var rng =newSystem.Security.Cryptography.RNGCryptoServiceProvider(data)){for(int i =0; i < size; i++){
rng.GetBytes(data);varvalue=BitConverter.ToInt32(data,0);yieldreturnvalue<0?value*-1:value;}}}
Petite méthode qui renvoie une date aléatoire sous forme de chaîne, basée sur quelques paramètres d'entrée simples. Construit sur la base de variations des réponses ci-dessus:
publicstringRandomDate(int startYear =1960,string outputDateFormat ="yyyy-MM-dd"){DateTime start =newDateTime(startYear,1,1);Random gen =newRandom(Guid.NewGuid().GetHashCode());int range =(DateTime.Today- start).Days;return start.AddDays(gen.Next(range)).ToString(outputDateFormat);}
Réponses:
Pour de meilleures performances si cela est appelé à plusieurs reprises, créez les variables
start
andgen
(et peut-être mêmerange
) en dehors de la fonction.la source
C'est en légère réponse au commentaire de Joel sur 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.
la source
for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
var getRandomDate = RandomDayFunc();
puis vous l'appelez pour obtenir des dates aléatoires:var randomDate = getRandomDate();
sachez que vous devez réutiliser getRandomDate pour que cela soit plus utile que la réponse de Joel.J'ai pris la réponse de @Joel Coehoorn et apporté les modifications qu'il m'a conseillées - mettre la variable hors de la méthode et tout mettre en classe. De plus, maintenant, le temps est également aléatoire. Voici le résultat.
Et exemple comment utiliser pour écrire 100 DateTimes aléatoires sur la console:
la source
range = (int)(DateTime.Today - start).TotalSeconds;
etreturn start.AddSeconds(gen.Next(range));
.Eh bien, si vous voulez présenter une optimisation alternative, nous pouvons également opter pour un itérateur:
vous pouvez l'utiliser comme ceci:
la source
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).
la source
Je suis un peu en retard dans le jeu, mais voici une solution qui fonctionne bien:
la source
Petite méthode qui renvoie une date aléatoire sous forme de chaîne, basée sur quelques paramètres d'entrée simples. Construit sur la base de variations des réponses ci-dessus:
la source