如何确定循环时间区间内当前时间的位置?技术求助
嘿,我来帮你搞定这个问题!你的思路方向完全没错——用减法算时间差、取模求周期内位置确实是正确的路子,问题出在负数时间跨度的取模处理上,另外我也会给你梳理下DateTime支持的数学操作和适用场景。
为什么你的代码没得到预期结果?
你当前的代码里,(now - anchor).Ticks % interval.Ticks 会在now早于anchor时得到负数的Ticks值,因为C#中整数取模会保留被除数的符号。这时候转换成TimeSpan就会是负的,显然不符合“周期内位置”的预期(我们需要的是0到周期长度之间的正时间跨度)。
举个例子:如果now是2018-01-05 06:59:00(比锚点早1分49秒),now - anchor的Ticks是负数,取模后余数也是负数,得到的TimeSpan会是-00:01:49,但我们实际想要的是00:41:11(也就是43分钟减去1分49秒的结果)。
正确的实现方式
我们只需要在取模后处理负数余数的情况,把它调整为正的即可:
using System; public class Program { public static void Main() { TimeSpan interval = new TimeSpan(0, 43, 0); DateTime anchor = new DateTime(2018, 1, 5, 7, 0, 49); DateTime now = DateTime.Now; // 计算锚点到当前时间的总跨度 TimeSpan totalElapsed = now - anchor; long intervalTicks = interval.Ticks; long totalTicks = totalElapsed.Ticks; // 计算余数,处理负数情况 long remainderTicks = totalTicks % intervalTicks; if (remainderTicks < 0) { remainderTicks += intervalTicks; } TimeSpan positionInCycle = new TimeSpan(remainderTicks); Console.WriteLine($"当前时间在周期内的位置:{positionInCycle}"); } }
这段代码不管当前时间在锚点之前还是之后,都会输出0到43分钟之间的正时间跨度,完美符合需求。
DateTime支持的数学操作与适用场景
DateTime和TimeSpan的数学操作是严格区分时间点和时间段的,以下是常用操作:
1. 减法操作
DateTime - DateTime → TimeSpan:计算两个时间点之间的间隔,适用于求时间差(比如“从订单创建到现在过了多久”)。DateTime - TimeSpan → DateTime:得到指定时间点之前的某个时间,比如“三天前的这个时候”。
2. 加法操作
DateTime + TimeSpan → DateTime:得到指定时间点之后的某个时间,比如“两小时后的会议时间”。
3. 比较操作
DateTime对象之间可以直接用>、<、==等比较运算符,用来判断时间先后顺序(比如“当前时间是否超过截止日期”)。
4. 注意事项
DateTime本身不支持直接的乘法、除法或取模运算——因为这些运算只对**时间段(TimeSpan)**有意义。如果需要做这类运算,你需要把时间差转换成Ticks(长整型)或者直接对TimeSpan的Ticks进行操作,就像我们在上面的代码里做的那样。
内容的提问来源于stack exchange,提问作者LoxBro

