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);
我需要计算可能跨越午夜的两次之间的持续时间。
用例是允许用户设置轮班计划,例如“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);