【问题标题】:Comparing DateTimes in C# producing unexpected results比较 C# 中的 DateTimes 产生意外结果
【发布时间】:2016-04-21 16:54:51
【问题描述】:

我试图比较运行时变量是否在现在和一分钟后。代码如下:

if (RunTime.ToUniversalTime() >= now.ToUniversalTime() && 
    RunTime.ToUniversalTime() < now.AddMinutes(1).ToUniversalTime())
{
    //Do Stuff 
}

但是,这比我预期的要早一分钟评估为真。例如,如果我的运行时间为 9:30,它从 9:29 到 9:30 而不是 9:30 - 9:31 评估为真。我在这里想念什么?我理解代码的方式是,当运行时大于或等于现在并且小于现在加一分钟时,它会评估为真。

【问题讨论】:

  • 我假设 now 等于 DateTime.Now 在代码发布之前?
  • 是的,我现在只是设置为一个变量,因为这是在一个 foreach 循环中,我希望现在对每个迭代的项目都相同。
  • 您在哪个时区工作(它们都相同)? ToUniversalTime() 调用是否为您提供了您期望的值?
  • 您现在使用的是两个不同的时间。它们可能很接近,但并不完全相同。始终将 now 设置为变量,因此现在两者都相同。
  • @jdweng now 是一个变量。

标签: c# datetime-comparison


【解决方案1】:
RunTime.ToUniversalTime() >= now.ToUniversalTime() && 
RunTime.ToUniversalTime() < now.AddMinutes(1).ToUniversalTime()

让我们重写这个条件:

now.ToUniversalTime() <= RunTime.ToUniversalTime() &&
now.ToUniversalTime() > RunTime.AddMinutes(-1).ToUniversalTime()

所以当RunTime 是9:30 时,从RunTime.AddMinutes(-1) (9:29) 到RunTime (9:30) 包括在内,条件应该为真。就像您在帖子中所说的那样。

如果您在 9:30 到 9:31 之间满足条件,那么您应该使用不同的条件:

now.ToUniversalTime() >= RunTime.ToUniversalTime() &&
now.ToUniversalTime() < RunTime.AddMinutes(1).ToUniversalTime()

【讨论】:

  • 谢谢!这个逻辑对我来说有点模糊。
【解决方案2】:

由于您使用的是DateTime.Now,因此您永远不会在完全相同的时间精确着陆。考虑以下两种情况:

Case 1 (what you're experiencing)
now:     9:29:01
runtime: 9:30:00
now+1:   9:30:01

Case 2 (what you want but doesn't work)
now:     9:30:01
runtime: 9:30:00
now+1:   9:31:01

尝试显式设置您的 now 变量,并制作一些应该发生的事情的逻辑表。您将更好地了解要创建的规则。

【讨论】:

  • 具体来说,在变量中保存 now 的副本可能会有所帮助。例如,nowCopy = (int)(now),比较 nowCopy 和 nowCopy + 1。所以有一个副本,临时变量不会随着时间的流逝而前进。
  • OP 已经将Now 保存在一个变量中。他说:“我现在刚刚设置为一个变量,因为这是在一个 foreach 循环中,我希望现在对于迭代的每个项目都相同。-”
  • @MatthewWatson 是对的,但是 OP 是否将其设置为指向在后台滴答作响的日期时间的指针?
  • 还是在一个保持不变的变量中?
  • 我敢打赌他的now 只是一个DateTime 结构。
【解决方案3】:

以下代码按预期工作(即它打印“第二个真”而不是“第一个真”):

DateTime nine29  = new DateTime(2015, 01, 01, 09, 29, 00);
DateTime nine30  = new DateTime(2015, 01, 01, 09, 30, 00);
DateTime runtime = nine30;

if (runtime.ToUniversalTime() >= nine29.ToUniversalTime() && runtime.ToUniversalTime() < nine29.AddMinutes(1).ToUniversalTime())
    Console.WriteLine("First true");

if (runtime.ToUniversalTime() >= nine30.ToUniversalTime() && runtime.ToUniversalTime() < nine30.AddMinutes(1).ToUniversalTime())
    Console.WriteLine("Second true");

因此,当您说 “如果我的运行时间为 9:30,它从 9:29 到 9:30 而不是 9:30 - 9:31 的计算结果为 true。” /em>

把你所有的时间放到变量中,打印到调试窗口或控制台,或者在调试器下运行并检查它们。并注意秒数!

【讨论】:

  • 尝试使用该值:DateTime nine2901 = new DateTime(2015, 01, 01, 09, 29, 01);
  • 当我的 if 计算结果为 true 时,我在这里使用断点:?RunTime.ToUniversalTime() {4/21/2016 5:33:00 PM} 日期:{4/21/2016 12:00 :00 am} DateAta:5247654586227387904日:21 Dayofweek:星期四Dayofyear:112小时:17 Internalkind:4611686018427387904 InternalTicks:635968567800000000种类:UTC Millisecond:0分:33个月:4秒:0滴答:63596856780000000000 Timeofday:{17:33: 00} 年:2016 年
  • ?now.ToUniversalTime() {4/21/2016 5:32:03 PM} 日期:{4/21/2016 12:00:00 AM} dateData:5247654585659202448 Day:21 DayOfWeek:星期四 DayOfYear: 112 Hour: 17 InternalKind: 4611686018427387904 InternalTicks: 635968567231814544 Kind: Utc 毫秒: 181 Minute: 32 Month: 4 Second: 3 Ticks: 635968567231814544 TimeOfDay: {17:32:03.
  • 所以是的,当现在是 时,它确实正在评估为 true
  • RunTime.ToUniversalTime() 是下午 5:33:00 而 now.ToUniversalTime() 是 5:32:03,所以它满足这两个条件。减去 (Runtime - now ).TotalSeconds
【解决方案4】:

我喜欢在进行日期时间比较时使用 TimeSpan 类型。

TimeSpan timeSpan = Runtime.ToUniversalTime().Subtract(now.ToUniversalTime());

if (timeSpan > 0 && timeSpan <= 1)
{
   //Code here
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多