判断时间段重合最直接的逻辑是start1
用
DateTime比较判断重合最直接只要两个时间段不满足「完全分离」,就是有交集。核心逻辑是:
start1 。别写成 <code>start1 ——端点相等是否算重合,得看业务。比如会议预约通常「9:00结束」和「9:00开始」不算冲突,此时必须用严格小于。实操建议:
- 统一用
DateTime(而非DateTimeOffset)避免时区干扰,除非明确要跨时区比较- 提前校验输入:任一时间段的
Start >= End应抛异常或返回 false,否则后续比较无意义- 若涉及数据库读取,注意 SQL Server 的
datetime精度只有 3.33ms,datetime2(7)才支持纳秒级,C# 中用DateTime默认精度足够,但比对前最好截断到毫秒级以防浮点误差封装成扩展方法让调用更干净
把判断逻辑收进
TimeSpan或DateTimeRange类型的扩展方法里,比每次手写条件清晰得多。不要在业务代码里反复写a.Start 。示例(轻量级):
public static bool Overlaps(this (DateTime Start, DateTime End) a, (DateTime Start, DateTime End) b) => a.Start <p>使用时:<code>var isBusy = (start1, end1).Overlaps((start2, end2));</code></p><p>注意点:</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2795" title="C#"><img src="https://img.php.cn/upload/skill/000/000/081/178936933912641.jpg" alt="C#" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill2795" title="C#" class="overflowclass">C#</a> <p class="overflowclass">"避开 C# 常见错误——空陷阱、异步陷阱、LINQ 陷阱及资源泄漏。"</p> </div> <a rel="nofollow" href="/xiazai/skill2795" title="C#" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
- 元组解构虽简洁,但命名不直观;生产环境建议定义
struct DateTimeRange并重载operator &&或提供IsOverlapping(DateTimeRange other)- 别用
TimeSpan表示时间段——它只表示「持续时长」,不含起始时间,无法直接用于重合判断处理包含 null 的时间段要提前防御
数据库字段或 API 输入常有可空时间(
DateTime?),直接解包会崩。不能假设EndTime.HasValue就一定合法——比如StartTime = null且EndTime = DateTime.Now,这种「半空」区间语义模糊,必须明确定义规则。常见策略:
- 全空 → 视为不参与比较(返回 false)
- 仅 Start 为空 → 当作「无限早」,仅当另一段 End 也为空才可能不重合(极少场景)
- 仅 End 为空 → 当作「无限晚」,此时只要另一段非空,几乎必然重合(例如排班系统中「长期有效」与任意时段都冲突)
- 推荐做法:统一转成有效区间再比较,例如用
startTime ?? DateTime.MinValue和endTime ?? DateTime.MaxValue,但需文档注明该转换含义性能敏感场景避免装箱和重复计算
高频调用(如每秒千次以上排程检查)时,
ValueTuple或匿名类型会触发装箱,struct更稳。另外,别在循环内反复调用DateTime.Now——它不是常量,两次调用可能值不同,导致本不该重合的被误判。关键提醒:
- 用
DateTime.UtcNow替代DateTime.Now减少时区切换开销(尤其服务器跨多时区部署)- 若比较基于「当前时间」的动态窗口(如「未来2小时」),把
DateTime.UtcNow.AddHours(2)提前算好复用,别塞进判断表达式里- .NET 6+ 可用
TimeOnly+DateOnly处理纯日期/纯时间逻辑,但二者相加不等于DateTime,混用会丢信息重合判断本身极快,真正的坑都在边界定义和数据质量上——端点是否含等号、null 怎么解释、时区怎么对齐,这些不写清楚,代码越「极简」越容易出错。










