【问题标题】:Why my random DateTime generator make dates outside of range?为什么我的随机 DateTime 生成器会使日期超出范围?
【发布时间】:2017-12-14 01:42:14
【问题描述】:

我有一个函数可以在两个日期之间的范围内生成随机日期时间......并且它以某种方式使随机日期出现在最小日期之前。我的代码有什么问题?

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

【问题讨论】:

  • 1) 不要忘记检查` if (dt1 > dt2)` ? 2)DateTime random_dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(random_sec).AddSeconds(dt1_sec);
  • 你的BuyersManager.RNG.Next会发生什么?
  • @krillgar - 抱歉,忘记指出这只是普通的 Random 实例。
  • 你得到的随机值是否在你期望的范围内?
  • 什么是dt1dt2,这是本地时间还是UTC 时间?我想这是当地时间。当您致电ToUniversalTime 时,您将获得 2016 年的 UTC 日期。从你的例子 1483214400 是 2016-12-31T20:00:00+00:00。

标签: c# .net datetime utc


【解决方案1】:

这里的问题是ToUniversalTime()。如果您的日期类型为 LocalUnspecified - ToUniversalTime 会将它们转换为 UTC 假设(在 Unspecified 的情况下)它们是本地的。通过这样做,您的dt1(即 2017 年 1 月 1 日)将以 UTC 表示为 2016 年的日期。当随机值接近最小值时 - 结果也将在 2016 年。要修复 - 只需删除对 ToUniversalTime() 的调用即可。您可以将其删除,因为通过 Substract 方法的文档:

System.DateTime.Subtract(System.DateTime) 方法不 考虑两者的 System.DateTime.Kind 属性的值 执行减法时的 System.DateTime 值

但是请注意,最好返回与输入相同类型的结果,因此:

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

因为否则,如果您的输入代表当地时间并且结果是 UTC - 没有多大意义。

【讨论】:

  • 谢谢。我按照你说的做了,我不再有外人了。
猜你喜欢
  • 1970-01-01
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
  • 2013-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-28
相关资源
最近更新 更多