NodaTime - 计算跨越午夜的两个 LocalTime 变量之间的持续时间

NodaTime - Calculate duration between two LocalTime variables that span midnight

我需要计算可能跨越午夜的两次之间的持续时间。

用例是允许用户设置轮班计划,例如“09:00至17:00”或“22:00至06:00”并计算约定时间

对于“09:00 到 17:00”,我可以使用:

LocalTime inAt = new LocalTime(9, 0);
LocalTime outAt = new LocalTime(17, 0);

var period = Period.Between(inAt, outAt);

8 小时后的结果,我正在寻找的答案。

对于“22:00 到 06:00”,周期 returns 16 小时(无论参数的顺序如何)。

LocalTime inAt = new LocalTime(22, 0);
LocalTime outAt = new LocalTime(6, 0);

var period = Period.Between(inAt, outAt);
var period2 = Period.Between(outAt, inAt);

我猜这与夏令时有关,除非您知道日期,否则您不能确定答案总是 8 小时。如果时钟向前是 7,向后是 9。

我如何确保无论使用什么 LocalTime 值,该期间都会忽略任何夏令时?我应该使用 LocalDateTime 和任意日期,例如 2021-01-01 吗?

此外,我使用 Period 是否正确,还是应该使用 Duration

更新

这似乎可行,但我仍然想知道是否有更简单的方法?

LocalTime inAt = new LocalTime(22, 0);
LocalTime outAt = new LocalTime(6, 0);

var period = Period.Between(inAt, outAt, PeriodUnits.Ticks);
LocalTime? midnightAdjustedTime = null;

if (period.Ticks < 0)
{
  midnightAdjustedTime = LocalTime.Midnight + period;  
}

var duration = Duration.FromTicks(midnightAdjustedTime?.TickOfDay ?? period.Ticks);

这与夏令时无关 - 它不能这样做,因为一切都是根据 LocalTime。这是关于消极时期。

For “22:00 to 06:00” the period returns 16 hours (regardless of the order of the parameters)

不,不是。一个 returns 16 小时,另一个 returns -16 小时:

using NodaTime;

var start = new LocalTime(22, 0);
var end = new LocalTime(6, 0);

var startToEnd = Period.Between(start, end);
var endToStart = Period.Between(end, start);

Console.WriteLine(startToEnd);
Console.WriteLine(endToStart);

输出:

PT-16H
PT16H

我不清楚你是如何得出两者 return 具有相同值的结论,但事实上它们 没有 return 相同的值对于解决问题至关重要。如果周期为负,简单的方法就是增加 1 天(24 小时)。你得到的代码几乎是正确的,但它可以做得更简单 - 并且根本不使用 Ticks 单元:

// Note: Period.ToDuration() isn't "generally safe" due to variable lengths
// of months etc, but is okay here.
var duration = startToEnd.ToDuration();
if (duration < Duration.Zero)
{
    duration += Duration.FromDays(1);
}

Console.WriteLine(duration);