2013-01-24 13 views
5

I wdrożone poniżej RandomDate, ale zawsze uzyskanie wartości zamknięte do „Z” data, prawdopodobnie brakuje czegoś tutaj ....Losowe DateTime między zakresie - nie zunifikowany wyjście

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

Chociaż nie (tylko) powodem do błędu, 'var RND = new random()' linia będzie powodować bóle głowy, jeśli zamierzają wywołać tej metody często. –

+0

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

Odpowiedz

20

Można zmienić na:

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

Objaśnienie: Kiedyś NextDouble() ponieważ daje liczbę pomiędzy 0.0 i 1.0. Twoja wartość zwrotna nie będzie całkowitą liczbą sekund w moim rozwiązaniu. I przeniosłem rnd do pola w klasie/strukturze. Ponieważ najlepiej jest ponownie użyć jednej instancji Random i nie tworzyć nowej za każdym razem, gdy potrzebna jest tylko jedna dodatkowa liczba losowa.

+0

wziął ten pomysł, dzięki. Miałem także Random Member jako ThreadLocal jak zasugerował Alexx – user1025852

4

Problem polega na tym, że :

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

tworzy TimeSpan z TICKS, a nie z SECONDS.

potrzebował:

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

(proszę sprawdzić obsady też - to musi być dwukrotnie przeszedł do FromSeconds)

+0

Losowe powinno być również pole w klasie lub argument w tej metodzie, w przeciwnym razie jest zawsze tworzone z tym samym nasieniem, gdy ta metoda jest nazywana bardzo szybko (np. w pętli). –

+0

Może to powodować ArgumentOutOfRangeException, gdy zakres.TotalSeconds jest większy Int32.MaxValue – musium

+0

@ user1320170 Rzeczywiście, będzie działać tylko do około 68 lat zasięgu; wydaje się jednak, że to wystarczy dla PO. –

0

Fixed ArgumentOutOfRangeException:

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

to pracuje dla mnie. Interwał dni wynosi do 28, aby uniknąć wyjątku z lutego.

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

Mój pomysł jest po prostu trzeba trochę losową liczbę kleszczy dodawanych do rozpoczęcia datetime dostać losowy datę pomiędzy początkiem i końcem. Tak więc moje rozwiązanie nie tworzy żadnych obiektów TimeSpan.

private static readonly Random random = new Random(); 
private static readonly object syncLock = new object(); 

public static DateTime RandomDate(DateTime from, DateTime to) 
{ 
    lock (syncLock) 
    { 
     return from.AddTicks ((long) (random.NextDouble() * (to.Ticks - from.Ticks))); 
    } 
} 
Powiązane problemy