2009-09-27 27 views
11

Estoy tratando de aleatorizar el valor para un simple campo de datos DateTime.¿Cuál es la mejor práctica para obtener un DateTime aleatorio entre dos fechas y horas?

Deseo obtener una fecha/hora al azar entre dos fechas/horas (por ejemplo, fecha/hora min y fecha/hora máximas).

por lo que permite imaginar que estoy después de una fecha al azar/tiempo entre

1/1/2000 10:00:00am y 1/1/2000 5:00:00pm.

Además, este código se usará en un bucle for, con 100 elementos ... lo que significa que los 100 elementos tendrán una fecha/horas aleatorias entre el período de fecha/hora mínimo/máximo.

¿Alguna idea?

+1

Véase también http://stackoverflow.com/questions/194863/random-date-in-c – adrianbanks

+0

Nod - se trata de un duplicado. He votado para cerrar mi propia pregunta :) –

Respuesta

26

Usted podría tratar de usar:

TimeSpan timeSpan = endDate - startDate; 
var randomTest = new Random(); 
TimeSpan newSpan = new TimeSpan(0, randomTest.Next(0, (int)timeSpan.TotalMinutes), 0); 
DateTime newDate = startDate + newSpan; 

esto le dará diferentes tiempos hasta el último minuto. Si quiere 100 (o algo más que 1) DateTime s, solo cree el objeto Random una vez. El MSDN page on Random explica en detalle por qué crear varios objetos Random en sucesión rápida es una mala idea.

El uso de un constructor diferente TimeSpan le dará una granularidad diferente. Desde el TimeSpan constructor MSDN:

TimeSpan (Int64) Inicializa una nueva TimeSpan al número especificado de garrapatas.
TimeSpan (Int32, Int32, Int32) Inicializa un nuevo TimeSpan a un número específico de horas, minutos y segundos.
TimeSpan (Int32, Int32, Int32, Int32) Inicializa un nuevo TimeSpan a un número especificado de días, horas, minutos y segundos.
TimeSpan (Int32, Int32, Int32, Int32, Int32) Inicializa un nuevo TimeSpan a un número especificado de días, horas, minutos, segundos y milisegundos.

2

muy rápido:

  1. convertir la fecha para totalhours
  2. restar un número de la otra y utilizar Abs para hacer positivo
  3. crear un número aleatorio dentro de la gama de 1 y el resultado de 2. arriba
  4. Agregue el número aleatorio resultante de horas al anterior de sus dos fechas
+0

Estaba dando la misma respuesta cuando la tuya apareció;) – slashmais

+0

Estaba tratando de adjuntar este comentario a la última publicación ... recuerda que Random.Next en .NET no incluye a el límite superior. –

1

Primero, descubra cuál es la precisión que desea en DateTime aleatorio (horas, minutos, segundos, ms, etc.).

A continuación, determine la diferencia entre las dos fechas en esa unidad.

Crea un entero aleatorio entre 0 y esa diferencia.

Agregue el entero aleatorio en unidades a la fecha original.

Dado el caso de uso que indicó anteriormente, calcule la diferencia en el ciclo for.

Dentro del bucle for, obtenga el int aleatorio y construya la fecha aleatoria.

3

Aquí es mi algoritmo y código:

  • ver la diferencia entre las dos fechas
  • para cada iteración, crear un número aleatorio entre las dos fechas
  • crear una nueva fecha entre ellos. Simplemente agregue ese número aleatorio como minutos a la fecha de inicio de la fecha.  

    Random randNum = new Random(); 
    
    DateTime minDt = new DateTime(2000,1,1,10,0,0); 
    DateTime maxDt = new DateTime(2000,1,1,17,0,0); 
    List<DateTime> myDates = new List<DateTime>(); 
    //Random.Next in .NET is non-inclusive to the upper bound (@NickLarsen) 
    int minutesDiff = Convert.ToInt32(maxDt.Subtract(minDt).TotalMinutes+1); 
    
    for (int i = 0; i < 100; i++) 
    { 
        // some random number that's no larger than minutesDiff, no smaller than 1 
        int r= randNum.Next(1, minutesDiff); 
        myDates.Add(minDt.AddMinutes(r)); 
    } 
    
    foreach (DateTime d in myDates) 
    { 
        Console.WriteLine(string.Format("{0:dd-MMM-yyyy hh:mm}",d)); 
    } 
    
0

Aquí es un método que utiliza un número aleatorio de las garrapatas:

Random r= new Random(); 
    //for better randomness don't recreate a new Random() too frequently. 
long rand62bit = (((long)r.Next())<<31) + r.Next(); 
    // 62bits suffices for random datetimes, 31 does not! 
DateTime newDate = startDate + new TimeSpan(rand62bit % (endDate - startDate).Ticks); 

Este método es exclusivo de la última fecha de la primera e inclusivo. Puede incluir fácilmente la última fecha agregando una marca a la cantidad básica de (endDate - startDate).Ticks.

1

Esto es lo que estoy usando:

class RandomDates 
{ 
    private Random random = new Random(); 

    public DateTime Date(DateTime? start = null, DateTime? end = null) 
    { 
     if (start.HasValue && end.HasValue && start.Value >= end.Value) 
      throw new Exception("start date must be less than end date!"); 

     DateTime min = start ?? DateTime.MinValue; 
     DateTime max = end ?? DateTime.MaxValue; 

     // for timespan approach see: http://stackoverflow.com/q/1483670/1698987 
     TimeSpan timeSpan = max - min; 

     // for random long see: http://stackoverflow.com/a/677384/1698987 
     byte[] bytes = new byte[8]; 
     random.NextBytes(bytes); 

     long int64 = Math.Abs(BitConverter.ToInt64(bytes, 0)) % timeSpan.Ticks; 

     TimeSpan newSpan = new TimeSpan(int64); 

     return min + newSpan; 
    } 
} 

que utiliza el enfoque en la respuesta aceptada pero modificado ligeramente, ya que tenía problemas con él.

+0

El método probablemente debería llamarse 'DateTime' en lugar de' Date'; tenía fechas simples en la mente pero, por supuesto, devuelve un 'DateTime'. – Cymen

1

Una sola línea basado en la solución de ChrisF

var newDate = startDate.AddHours(new Random(Convert.ToInt32(DateTime.Now.Ticks/int.MaxValue)).Next(0, (int)(endDate - startDate).TotalHours)); 
Cuestiones relacionadas