两个 DateTimeOffset 之间的差异返回意外的负值

问题描述 投票:0回答:2

以下 C# 代码应该返回一个时间跨度,指示当前时间与下一次事件发生(假设发生在凌晨 5 点)之间的时间间隔。它必须处理凌晨 5 点之前或之后调用代码的情况。

代码设法在凌晨 4 点到 5 点之间在我们的服务器 (+1GMT) 上返回负延迟,这是我无法理解的。有谁知道解释是什么吗?

TimeSpan EverydayAt(int hourOfDay)
{
    DateTimeOffset now = DateTimeOffset.UtcNow;
    DateTimeOffset nextTime = now.Date.AddDays(now.Hour < hourOfDay ? 0 : 1).AddHours(hourOfDay);
    TimeSpan delay = nextTime - now;
    return delay;
}
c# .net timezone datetimeoffset
2个回答
2
投票

提供的代码正在检查当前时间是否小于一天中的指定时间。如果是在那个小时之前,则不会向 now.Date 添加额外的一天,这在当前时间接近凌晨 5 点时可能会导致问题。

TimeSpan EverydayAt(int hourOfDay)
{
    DateTimeOffset now = DateTimeOffset.UtcNow;
    
    DateTimeOffset nextTime = now.Date.AddHours(hourOfDay);
    if (now.Hour >= hourOfDay)
    {
        nextTime = nextTime.AddDays(1);
    }

    TimeSpan delay = nextTime - now;
    return delay;
}

以上代码检查当前时间是否大于或等于指定时间(上午 5 点)。如果是,则会在计算出的

nextTime
上添加 1 天。


0
投票

有人知道解释是什么吗?

阐述这个问题是从这一行开始的。

now.Date.AddDays(now.Hour < hourOfDay ? 0 : 1).AddHours(hourOfDay);

这是一个您不知道的

DateTime
对象,您实际上正在转换为
DateTimeOffset
对象
nextTime

创建的此

nextTime
对象自“
我们的服务器(+1GMT)
”以来的 Offset 将为 1 小时。

因此,基本上早上 5 点之前的任何时间都将是当天的

DateTimeOffset
对象,其
Offset
为 1 小时,您可以将其与
now
(当天的
DateTimeOffset
为 0 小时的
Offset
对象进行比较) ).

替代解决方案:

就是将其转换回带有零的

DateTimeOffset
Offset

int hourOfDay = 15;
DateTimeOffset now = DateTimeOffset.UtcNow;
DateTimeOffset nextTime = new DateTimeOffset(now.Date.AddDays(now.Hour < hourOfDay ? 0 : 1).AddHours(hourOfDay), TimeSpan.Zero);
TimeSpan delay = nextTime - now;
Console.WriteLine("Delay! = " + delay.ToString());
© www.soinside.com 2019 - 2024. All rights reserved.