C#中合并日期与时间字段生成DateTime并计算班次时长问题
C# 班次起止时间合并及跨午夜场景解决方案
核心需求
需要将shiftStartTime的日期与actualShiftStartTime的时间合并,shiftEndTime的日期与actualShiftEndTime的时间合并,以此计算准确的班次时长,同时要处理实际班次启动时间跨午夜的场景。
解决方案代码
以下是健壮性更强的实现,包含异常处理和跨天逻辑:
using System; using System.Globalization; using System.Data; // 获取数据行 DataRow row = theTimecardDataSet.Tables[0].Rows[0]; // 1. 解析基础班次时间(带日期) if (!DateTime.TryParse(row["ShiftStartTime"].ToString(), out DateTime shiftStart)) throw new InvalidOperationException("ShiftStartTime 格式无效"); if (!DateTime.TryParse(row["ShiftEndTime"].ToString(), out DateTime shiftEnd)) throw new InvalidOperationException("ShiftEndTime 格式无效"); // 2. 解析实际班次时间(仅时间部分) if (!TimeSpan.TryParse(row["actualShiftStartTime"].ToString(), out TimeSpan actualStartTs)) throw new InvalidOperationException("actualShiftStartTime 格式无效"); if (!TimeSpan.TryParse(row["actualShiftEndTime"].ToString(), out TimeSpan actualEndTs)) throw new InvalidOperationException("actualShiftEndTime 格式无效"); // 3. 解析午餐扣除时长(默认0分钟) int lessLunchMin = 0; int.TryParse(row["lessLunchMin"].ToString(), out lessLunchMin); // 4. 合并实际开始时间(处理跨午夜场景) DateTime actualStart = shiftStart.Date + actualStartTs; // 如果合并后的时间早于班次计划开始时间,说明实际启动在次日 if (actualStart < shiftStart) actualStart = actualStart.AddDays(1); // 5. 合并实际结束时间(处理跨午夜场景) DateTime actualEnd = shiftEnd.Date + actualEndTs; // 两种跨天判断: // - 实际结束时间早于实际开始时间(必然跨天) // - 实际结束时间早于班次计划结束时间,但实际开始已跨天(说明结束也在次日) if (actualEnd < actualStart || (actualEnd < shiftEnd && actualStart > shiftStart.Date)) actualEnd = actualEnd.AddDays(1); // 6. 计算最终时长和格式化输出 TimeSpan duration = actualEnd - actualStart - TimeSpan.FromMinutes(lessLunchMin); TimeSpan totalHours = actualEnd - actualStart; string dtCreated = actualStart.ToString("M/d/yyyy h:mmtt", CultureInfo.CreateSpecificCulture("en-US")); string dtEnded = actualEnd.ToString("M/d/yyyy h:mmtt", CultureInfo.CreateSpecificCulture("en-US"));
关键逻辑说明
时间合并规则:
- 实际开始时间 = 班次开始时间的日期 + 实际启动的时间部分
- 实际结束时间 = 班次结束时间的日期 + 实际结束的时间部分
跨午夜场景处理:
- 实际启动跨天:如果合并后的实际开始时间早于班次计划开始时间(比如班次计划22:00,实际启动00:30),则将实际开始日期加1天。
- 实际结束跨天:如果实际结束时间早于实际开始时间,或者实际结束时间早于班次计划结束时间但实际开始已跨天,则将实际结束日期加1天。
健壮性优化:
- 使用
TryParse替代Parse,避免因数据格式错误抛出未处理异常。 - 午餐时长解析失败时默认设为0,保证计算流程不中断。
- 使用
测试示例
正常场景
输入:
<shiftStartTime>2023-01-27T06:00:00</shiftStartTime> <shiftEndTime>2023-01-27T14:00:00</shiftEndTime> <actualShiftStartTime>06:07:00</actualShiftStartTime> <actualShiftEndTime>14:01:00</actualShiftEndTime>
输出:
actualStart:2023-01-27 06:07:00actualEnd:2023-01-27 14:01:00- 时长:7小时54分(扣除午餐前为7小时54分)
跨午夜启动场景
输入:
<shiftStartTime>2023-01-27T22:00:00</shiftStartTime> <shiftEndTime>2023-01-28T06:00:00</shiftEndTime> <actualShiftStartTime>00:30:00</actualShiftStartTime> <actualShiftEndTime>06:15:00</actualShiftEndTime>
输出:
actualStart:2023-01-28 00:30:00actualEnd:2023-01-28 06:15:00- 时长:5小时45分
内容的提问来源于stack exchange,提问作者KJM
相关产品推荐
相关产品推荐

