2013-01-24 4 views
5

ho implementato il seguito RandomDate, ma ho sempre continuo a ricevere valori chiusa al "Da" data, probabilmente manca qualcosa qui ....a caso DateTime tra gamma - non uscita unificato

public static DateTime GetRandomDate(DateTime from, DateTime to) 
    { 
     var range = new TimeSpan(to.Ticks - from.Ticks); 

     var rnd = new Random(); 

     var randTimeSpan = new TimeSpan((long)(range.TotalSeconds - rnd.Next(0, (int)range.TotalSeconds))); 

     return from + randTimeSpan; 
    } 
+1

Sebbene non sia la (sola) ragione del tuo errore, la riga 'var rnd = new Random()' causerà mal di testa se si intende chiamare frequentemente questo metodo. –

+0

vedi questo post? http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number- – Alexxx

risposta

20

Si potrebbe cambiare a:

static readonly Random rnd = new Random(); 
public static DateTime GetRandomDate(DateTime from, DateTime to) 
{ 
    var range = to - from; 

    var randTimeSpan = new TimeSpan((long)(rnd.NextDouble() * range.Ticks)); 

    return from + randTimeSpan; 
} 

Spiegazione: ho usato NextDouble() perché dà un numero compreso tra 0.0 e 1.0. Il tuo valore di ritorno non sarà un numero intero di secondi nella mia soluzione. E ho spostato rnd in un campo della classe/struct. Perché è meglio riutilizzare un'istanza Random e non crearne una nuova ogni volta che è necessario un solo numero casuale aggiuntivo.

+0

ha preso questa idea, grazie. Ho anche avuto il Random Member come ThreadLocal come suggerito da Alexx – user1025852

4

Il problema è che :

var randTimeSpan = new TimeSpan((long)(range.TotalSeconds - rnd.Next(0, (int)range.TotalSeconds))); 

sta creando un TimeSpan da TICKS, non da SECONDI.

è necessario scaricare:

var randTimeSpan = TimeSpan.FromSeconds((long)(range.TotalSeconds - rnd.Next(0, (int)range.TotalSeconds))); 

(Si prega di controllare il cast troppo - ha bisogno di essere un doppio passato a FromSeconds)

+0

Il random dovrebbe anche essere un campo nella classe o un argomento in questo metodo, altrimenti è sempre creato con lo stesso seme quando questo metodo è chiamato molto veloce (fe in un ciclo). –

+0

Questo può causare ArgumentOutOfRangeException quando range.TotalSeconds è maggiore Int32.MaxValue – musium

+0

@ user1320170 Infatti, funzionerà solo fino a circa 68 anni di intervallo; tuttavia, sembra che questo sia sufficiente per l'OP. –

0

ArgumentOutOfRangeException fisso:

public static DateTime GetRandomDateTime(DateTime? min = null, DateTime? max = null) 
{ 
    min = min ?? new DateTime(1753, 01, 01); 
    max = max ?? new DateTime(9999, 12, 31); 

    var range = max.Value - min.Value; 
    var randomUpperBound = (Int32) range.TotalSeconds; 
    if (randomUpperBound <= 0) 
     randomUpperBound = Rnd.Next(1, Int32.MaxValue); 

    var randTimeSpan = TimeSpan.FromSeconds((Int64) (range.TotalSeconds - Rnd.Next(0, randomUpperBound))); 
    return min.Value.Add(randTimeSpan); 
} 
0

Questo sta lavorando per me. L'intervallo di giorni è fino al 28 per evitare l'eccezione con febbraio.

Random r = new Random(); 
DateTime rDate = new DateTime(r.Next(1900, 2010), r.Next(1, 12), r.Next(1, 28)); 
0

La mia idea è che abbiamo solo bisogno di un po 'di numeri casuali di zecche aggiunti per iniziare datetime per ottenere una data casuale tra inizio e fine. Quindi la mia soluzione non crea alcun oggetto TimeSpan.