如何用Python结合JSON检测预订时间是否已被占用并提供备选建议
预订时间检测问题修正
需求说明
需要实现以下功能:
- 检查用户选择的时间在JSON预订数据中是否可用
- 若该时间已被预订,推荐下一个可用时间并询问用户是否预订
- 用户选择“否”则返回选择时间的步骤
现有预订数据
CSV格式
name, start_time, end_time Michał Najman, 23.03.2023 14:00, 23.03.2023 15:00 Marcin Wiśniewski, 23.03.2023 17:00, 23.03.2023 18:00 Tadeusz Stockinger, 24.03.2023 11:00, 24.03.2023 12:30 Robert Brzozowski, 24.03.2023 12:30, 24.03.2023 14:00 Norman Dudziuk, 24.03.2023 16:30, 24.03.2023 17:00 Klaus Sevkovic, 25.03.2023 14:00, 25.03.2023 14:30 Paweł Gulczyński, 26.03.2023 12:00, 26.03.2023 13:30 Mieczysław Okniński, 26.03.2023 13:30, 26.03.2023 14:00
JSON格式
{"23.03": [{ "name": "Michał Najman", "start_time": "14:00", "end_time": "15:00" }, {"name": "Marcin Wiśniewski", "start_time": "17:00", "end_time": "18:00" }], "24.03": [{ "name": "Tadeusz Stockinger", "start_time": "11:00", "end_time": "12:30" }, {"name": "Robert Brzozowski", "start_time": "12:30", "end_time": "14:00" }, {"name": "Norman Dudziuk", "start_time": "16:30", "end_time": "17:00" }], "25.03": [{ "name": "Klaus Sevkovic", "start_time": "14:00", "end_time": "14:30" }], "26.03": [{ "name": "Paweł Gulczyński", "start_time": "12:00", "end_time": "13:30" }, {"name": "Mieczysław Okniński", "start_time": "13:30", "end_time": "14:00" }], "27.03": [], "28.03": [], "29.03": [], "30.03": [] }
原代码及问题
原代码
import json class Make_aReservation: # print('$ Make a reservation ') # name = input("What's your Name?\n") book = input("When would you like to book? {DD.MM.YYYY HH:MM}\n") def __init__(self): self.filename = '23.03-30.03.json' def file_to_text(self): with open(self.filename, "r") as file_opened: text = json.load(file_opened) return text def reservation(self): # print(self.file_to_text()) if self.book[:5] in self.file_to_text(): # print(self.file_to_text()[self.book[:5]]) # print(self.file_to_text()[self.book[:5]]) for i in self.file_to_text()[self.book[:5]]: print(i) print(self.book[11:16]) if self.book[11:16] in i['end_time']: print(True) else: print(False) make_aReservation = Make_aReservation() print(make_aReservation.reservation())
原代码运行结果
When would you like to book? {DD.MM.YYYY HH:MM} 23.03.2023 15:00 {'name': 'Michał Najman', 'start_time': '14:00', 'end_time': '15:00'} 15:00 True {'name': 'Marcin Wiśniewski', 'start_time': '17:00', 'end_time': '18:00'} 15:00 False None Process finished with exit code 0
原代码问题
- 冲突检测逻辑错误:仅检查用户输入时间是否等于某个预订的结束时间,无法判断时间段是否重叠(比如用户预订14:30-15:30,会和14:00-15:00的预订冲突,但原代码检测不出来)
- 类结构不合理:
book作为类属性会在类加载时就触发输入,不符合面向对象设计规范 - 未使用时间对象比较:直接用字符串比较时间,容易出现逻辑漏洞(比如"10:00"和"9:00"的字符串比较结果不正确)
修正后的代码
import json from datetime import datetime, timedelta class ReservationSystem: def __init__(self, filename='23.03-30.03.json'): self.filename = filename self.bookings = self._load_bookings() # 默认预订时长1小时,可根据需求调整 self.default_duration = timedelta(hours=1) def _load_bookings(self): """加载JSON中的预订数据""" with open(self.filename, 'r', encoding='utf-8') as f: return json.load(f) def _parse_user_time(self, user_input): """解析用户输入的时间为datetime对象""" try: return datetime.strptime(user_input, "%d.%m.%Y %H:%M") except ValueError: print("输入格式错误,请按照DD.MM.YYYY HH:MM格式输入") return None def _is_time_available(self, user_start, date_key): """检查用户预订时间段是否可用""" user_end = user_start + self.default_duration # 获取当天的所有预订 day_bookings = self.bookings.get(date_key, []) for booking in day_bookings: # 解析预订的时间为datetime对象 booking_start = datetime.strptime(f"{date_key}.2023 {booking['start_time']}", "%d.%m.%Y %H:%M") booking_end = datetime.strptime(f"{date_key}.2023 {booking['end_time']}", "%d.%m.%Y %H:%M") # 检查时间段是否重叠:用户开始时间 < 预订结束时间,且用户结束时间 > 预订开始时间 if user_start < booking_end and user_end > booking_start: return False, booking_end return True, None def _get_next_available_time(self, date_key): """获取当天的下一个可用时间""" day_bookings = self.bookings.get(date_key, []) if not day_bookings: # 当天无预订,默认最早可用时间为09:00 return datetime.strptime(f"{date_key}.2023 09:00", "%d.%m.%Y %H:%M") # 按结束时间排序预订 sorted_bookings = sorted(day_bookings, key=lambda x: x['end_time']) last_end_time = sorted_bookings[-1]['end_time'] next_start = datetime.strptime(f"{date_key}.2023 {last_end_time}", "%d.%m.%Y %H:%M") # 检查下一个时间是否在合理时间段内(比如到18:00) if next_start.time() <= datetime.strptime("18:00", "%H:%M").time(): return next_start else: print("当天剩余时间已无可用时段,请选择其他日期") return None def start(self): """启动预订流程""" while True: user_input = input("When would you like to book? {DD.MM.YYYY HH:MM}\n") user_start = self._parse_user_time(user_input) if not user_start: continue # 提取日期键(DD.MM) date_key = user_start.strftime("%d.%m") if date_key not in self.bookings: print("该日期不在可预订范围内,请选择23.03-30.03之间的日期") continue # 检查时间是否可用 available, conflicting_end = self._is_time_available(user_start, date_key) if available: confirm = input(f"时间{user_start.strftime('%d.%m.%Y %H:%M')}可用,是否确认预订?(是/否)\n") if confirm.lower() in ['是', 'y', 'yes']: # 这里可以添加保存预订到JSON的逻辑 print("预订成功!") break else: print("返回时间选择步骤") continue else: print(f"时间{user_start.strftime('%d.%m.%Y %H:%M')}已被预订") next_time = self._get_next_available_time(date_key) if next_time: confirm = input(f"推荐下一个可用时间:{next_time.strftime('%d.%m.%Y %H:%M')},是否预订?(是/否)\n") if confirm.lower() in ['是', 'y', 'yes']: # 添加保存逻辑 print("预订成功!") break else: print("返回时间选择步骤") continue else: continue if __name__ == "__main__": system = ReservationSystem() system.start()
代码说明
- 重构类结构:将输入逻辑移到
start方法中,类初始化时仅加载预订数据,符合面向对象设计 - 时间解析与比较:使用
datetime模块解析时间字符串为可比较的对象,避免字符串比较的漏洞 - 正确的冲突检测:通过时间段重叠逻辑判断是否可用,覆盖所有可能的冲突场景
- 下一个可用时间推荐:根据当天最后一个预订的结束时间推荐,若当天无预订则默认09:00
- 完整流程控制:实现了用户输入验证、确认预订、返回重选的完整逻辑
内容的提问来源于stack exchange,提问作者Marcin
相关产品推荐
相关产品推荐

