2017-07-10 2 views
1

J'ai une fonction pour générer des DateTime aléatoires entre deux dates ... et en quelque sorte, elle fait des dates aléatoires avant la date minimale. Qu'est ce qui ne va pas avec mon code?Pourquoi mon générateur DateTime aléatoire fait-il des dates en dehors de la plage?

public void TestFunct() 
{ 
    GenerateRandomTimeBetweenDates(new Random(), DateTime.ParseExact("01.01.2017 00:00:00", "dd.MM.yyyy HH:mm:ss", CultureInfo.InvariantCulture), DateTime.ParseExact("01.02.2017 00:00:00", "dd.MM.yyyy HH:mm:ss", CultureInfo.InvariantCulture)); 
} 

public DateTime GenerateRandomTimeBetweenDates(Random RNG, DateTime dt1, DateTime dt2) 
{ 
    int dt1_sec = (int)dt1.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; //calc seconds since Unix epoch 
    int dt2_sec = (int)dt2.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; 
    int random_sec = RNG.Next(Math.Min(dt1_sec, dt2_sec), Math.Max(dt1_sec, dt2_sec)); //RNG is Random instance. Here I generate seconds amount between two amounts - minimal and maximal. 

    DateTime random_dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(random_sec); //I try to recreate date by adding generated seconds amount to Unix epoch. 

    if (random_dt.Year == 2016) 
     random_dt = random_dt; //this I use to trigger breakpoint 

    return random_dt; 
} 

enter image description here

+0

1) N'oubliez pas de vérifier si (dt1> dt2) '? 2) 'DateTime random_dt = nouveau DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) .AddSeconds (random_sec) .AddSeconds (dt1_sec);' – KamikyIT

+0

Que se passe-t-il dans votre 'BuyersManager.RNG.Next' ? – krillgar

+0

@krillgar - désolé, j'ai oublié de signaler que c'est juste une instance aléatoire normale. – Kosmos

Répondre

2

Le problème est ici ToUniversalTime(). Si vos dates ont une sorte de Local ou Unspecified - ToUniversalTime va les convertir en UTC en supposant (dans le cas de Unspecified) qu'ils sont locaux. En faisant cela, votre dt1, soit le 1er janvier 2017, sera représentée à l'UTC comme une date dans l'année 2016. Lorsque la valeur aléatoire est proche de la valeur minimale - le résultat sera également en 2016 année. Pour corriger - il suffit de supprimer l'appel à ToUniversalTime(). Vous pouvez simplement le supprimer, parce que, par la documentation de la méthode Substract:

La méthode System.DateTime.Subtract (System.DateTime) n'a pas considérer la valeur de la propriété System.DateTime.Kind des deux valeurs System.DateTime lors de l'exécution de la soustraction

Notez cependant qu'il est préférable de revenir résultat avec le même genre que les entrées, donc:

DateTime random_dt = new DateTime(1970, 1, 1, 0, 0, 0, dt1.Kind).AddSeconds(random_sec); 

Parce que o si votre entrée représente l'heure locale et que le résultat est en UTC, cela n'a pas beaucoup de sens.

+0

Merci. J'ai fait comme tu l'as dit et plus d'outsiders pour moi. – Kosmos