VB.NET中时区依赖信息处理:业务时段任务调度优化咨询
优化营业时间判断的延迟计算方案
我有一个业务场景:需要判断任务应延迟至后续日期排队还是立即提交处理。判断逻辑基于客户本地时区的业务营业时间(例如早8:00营业、晚5:00打烊),客户时区需单独存储。任务记录的创建时间是服务器UTC时间,我先将其转换为客户时区时间,再通过遍历一周内的小时数计算延迟时长——延迟为0则立即执行,大于0则将服务器UTC时间偏移对应时长。当前实现代码如下,求更优方案:
Private Function CalcDelay() As Integer Dim d = _localTime '// 当前客户本地时间 Dim n = d.DayOfWeek() Dim now = d.Hour() & "." & d.Minute() Dim delayHours As Integer = 0 Dim _day For i = 0 To 168 d = _localTime.AddHours(i) n = d.DayOfWeek() now = d.Hour() & "." & d.Minute() _day = _bh.Hours(n) If (ConvertTime(now) >= ConvertTime(_bh.Hours(n).Open1c) And ConvertTime(now) < ConvertTime(_bh.Hours(n).Close1c)) _ Or (ConvertTime(now) >= ConvertTime(_bh.Hours(n).Open2c) And ConvertTime(now) < ConvertTime(_bh.Hours(n).Close2c)) Then delayHours = i Exit For End If Next Return delayHours End Function
注:ConvertTime用于将客户的营业时间(格式为HH.MM,如08.00、15.00等)转换为可比较的数值
优化思路与方案
1. 干掉冗余的字符串拼接与重复转换
原代码把小时和分钟拼接成字符串再转数值,完全是多此一举。直接把客户的营业时间(HH.MM)转成TimeSpan,和当前时间的TimeOfDay做比较,既高效又不容易出错。
2. 减少循环次数,直接计算最近营业时段
逐小时遍历整整一周(168次)太浪费性能。我们可以先判断当前时间是否在营业时段内:
- 如果是,直接返回0;
- 如果不是,先算当天剩余的营业时段(如果当天还有没结束的时段),再不行就算到次日营业开始的时间,依次往后找,直到找到最近的营业时段。
优化后的代码示例
Private Function CalcDelay() As Integer Dim currentLocalTime = _localTime Dim currentDayOfWeek = currentLocalTime.DayOfWeek Dim currentTimeOfDay = currentLocalTime.TimeOfDay ' 先检查当前时间是否在营业时段内,是的话直接返回0 Dim todayHours = _bh.Hours(currentDayOfWeek) If IsInBusinessHours(currentTimeOfDay, todayHours) Then Return 0 End If Dim delayHours As Integer = 0 Dim checkTime = currentLocalTime ' 从下一小时开始找,最多遍历一周防止死循环 For i = 1 To 168 checkTime = checkTime.AddHours(1) Dim checkDayOfWeek = checkTime.DayOfWeek Dim checkTimeOfDay = checkTime.TimeOfDay Dim dayHours = _bh.Hours(checkDayOfWeek) If IsInBusinessHours(checkTimeOfDay, dayHours) Then delayHours = i Exit For End If Next Return delayHours End Function ' 辅助函数:判断当前时间是否属于该日的营业时段 Private Function IsInBusinessHours(currentTime As TimeSpan, dayHours As BusinessHours) As Boolean ' 把HH.MM格式的营业时间转成TimeSpan Dim open1 = ParseTimeString(dayHours.Open1c) Dim close1 = ParseTimeString(dayHours.Close1c) Dim open2 = ParseTimeString(dayHours.Open2c) Dim close2 = ParseTimeString(dayHours.Close2c) ' 检查是否在第一个或第二个营业时段内 Return (currentTime >= open1 AndAlso currentTime < close1) OrElse (currentTime >= open2 AndAlso currentTime < close2) End Function ' 辅助函数:解析HH.MM格式的字符串为TimeSpan Private Function ParseTimeString(timeStr As String) As TimeSpan Dim parts = timeStr.Split("."c) Dim hours = Integer.Parse(parts(0)) Dim minutes = Integer.Parse(parts(1)) Return New TimeSpan(hours, minutes, 0) End Function
额外优化点
- 可以缓存
ParseTimeString的解析结果,毕竟同一周的同一天营业时间是固定的,不用每次循环都重复解析; - 如果业务允许,还可以提前计算出一周内所有营业时段的时间范围,直接查找当前时间之后的第一个时段,进一步减少循环次数。
内容的提问来源于stack exchange,提问作者DDulla
相关产品推荐
相关产品推荐

