如何在Python中验证单日排班JSON数据的时间有效性?
单日排班定价时段的完整验证实现方案
需求背景
我们有一个存储单日排班信息的JSON对象,其中timings字段记录店铺的营业起止时间,pricings是一个时段定价列表,每个元素包含peak_hours标识、时段起止时间和价格信息。需要完成两项核心验证:
pricings中所有时段的起止时间必须完全落在timings规定的营业时间范围内;pricings的各个时段之间不能存在重叠(允许首尾衔接,比如前一个时段的结束时间等于后一个的开始时间)。
现有代码仅能完成第一项规则的部分校验,需要补充重叠验证逻辑,实现完整的校验功能。
示例数据
- 有效数据:店铺营业时间1:00-11:00,
pricings时段依次为1:00-4:00(高峰)、4:00-7:00(非高峰)、7:00-11:00(高峰) - 无效数据示例1:
pricings时段1:00-5:00(高峰)与4:00-7:00(非高峰)存在重叠 - 无效数据示例2:
pricings时段17:00-23:00超出店铺00:00-22:00的营业时间
现有部分校验代码
for time in closeTime: if time > close : print("Not Valid") for time in startTime: if time < start: print("Not Valid")
完整实现方案
核心思路
- 统一时间格式:将所有时间字符串(营业时间、定价时段)转换为当天的总分钟数,用数值比较替代字符串比较,避免格式问题;
- 完善范围校验:不仅要检查时段是否在营业时间内,还要确保每个时段的开始时间不晚于结束时间;
- 重叠校验逻辑:先将定价时段按开始时间排序,再依次检查后一个时段的开始时间是否大于等于前一个时段的结束时间,确保无重叠。
完整代码实现
def time_to_minutes(time_str): """将HH:MM格式的时间字符串转换为当天的总分钟数""" hours, minutes = map(int, time_str.split(":")) return hours * 60 + minutes def validate_pricings(timings, pricings): # 转换店铺营业时间为分钟数 shop_open = time_to_minutes(timings["start"]) shop_close = time_to_minutes(timings["end"]) converted_pricings = [] for pricing in pricings: # 转换当前定价时段的起止时间为分钟数 start = time_to_minutes(pricing["start"]) end = time_to_minutes(pricing["end"]) # 校验:时段自身合法性(开始时间不能晚于结束时间) if start > end: return False, "存在开始时间晚于结束时间的无效定价时段" # 校验:时段是否在店铺营业时间范围内 if start < shop_open or end > shop_close: return False, f"定价时段{pricing['start']}-{pricing['end']}超出店铺营业时间" converted_pricings.append((start, end)) # 按开始时间对定价时段排序 converted_pricings.sort(key=lambda x: x[0]) # 校验:时段之间是否存在重叠 for i in range(1, len(converted_pricings)): prev_end = converted_pricings[i-1][1] curr_start = converted_pricings[i][0] if curr_start < prev_end: # 转换回时间字符串,生成明确的错误提示 prev_start = f"{converted_pricings[i-1][0]//60}:{converted_pricings[i-1][0]%60:02d}" prev_end_str = f"{prev_end//60}:{prev_end%60:02d}" curr_start_str = f"{curr_start//60}:{curr_start%60:02d}" curr_end = f"{converted_pricings[i][1]//60}:{converted_pricings[i][1]%60:02d}" return False, f"定价时段{prev_start}-{prev_end_str}与{curr_start_str}-{curr_end}存在重叠" return True, "所有校验通过" # 测试用例 # 有效数据测试 valid_timings = {"start": "01:00", "end": "11:00"} valid_pricings = [ {"peak_hours": True, "start": "01:00", "end": "04:00", "price": 20}, {"peak_hours": False, "start": "04:00", "end": "07:00", "price": 15}, {"peak_hours": True, "start": "07:00", "end": "11:00", "price": 20} ] print(validate_pricings(valid_timings, valid_pricings)) # 输出 (True, '所有校验通过') # 重叠时段测试 invalid1_timings = {"start": "01:00", "end": "11:00"} invalid1_pricings = [ {"peak_hours": True, "start": "01:00", "end": "05:00", "price": 20}, {"peak_hours": False, "start": "04:00", "end": "07:00", "price": 15} ] print(validate_pricings(invalid1_timings, invalid1_pricings)) # 输出 (False, '定价时段01:00-05:00与04:00-07:00存在重叠') # 超出营业时间测试 invalid2_timings = {"start": "00:00", "end": "22:00"} invalid2_pricings = [ {"peak_hours": True, "start": "17:00", "end": "23:00", "price": 20} ] print(validate_pricings(invalid2_timings, invalid2_pricings)) # 输出 (False, '定价时段17:00-23:00超出店铺营业时间')
代码说明
- 时间转换函数:把
HH:MM格式的时间转成分钟数,让时间比较变成简单的数值运算,避免字符串比较的各种问题; - 多维度校验:先检查单个时段的合法性,再检查是否在营业时间内,最后检查时段重叠,层层递进;
- 排序后校验重叠:排序后只需要检查相邻时段,逻辑简单且效率高,同时支持任意顺序的时段输入;
- 明确错误提示:返回具体的错误信息,方便快速定位问题。
内容的提问来源于Stack Exchange,提问作者Ahmed Yasin
相关产品推荐
相关产品推荐

