如何为Python Calendar模块生成的文本日历中含事件的日期添加标记
如何为Python Calendar模块生成的文本日历中含事件的日期添加标记
嗨,这个需求完全可以实现!我来一步步给你讲怎么做~
核心思路
我们可以分两步走:先从CSV文件里提取出目标月份有事件的日期,然后自定义日历的生成逻辑,在对应日期后加上*标记;如果你不想完全重写日历生成逻辑,也可以修改formatmonth输出的字符串来实现。
方法一:自定义生成带标记的日历(推荐)
这种方法更灵活,能精准控制每个日期的显示样式,避免字符串替换可能带来的问题。
步骤1:读取CSV文件,提取有事件的日期
假设你的CSV文件有一列叫date,日期格式是YYYY-MM-DD,我们先把目标月份的事件日期(仅“日”部分)存到一个集合里:
import csv from calendar import TextCalendar # 目标年月(你原来代码里的correct_year和correct_month) correct_year = 2023 correct_month = 1 # 存储有事件的日期(日) event_days = set() # 读取CSV文件 with open('events.csv', 'r', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: date_parts = row['date'].split('-') # 只保留目标年月的日期 if int(date_parts[0]) == correct_year and int(date_parts[1]) == correct_month: event_days.add(int(date_parts[2]))
步骤2:生成带标记的文本日历
利用TextCalendar的monthdayscalendar方法获取当月的日期矩阵(每个子列表代表一周,0表示非当月日期),然后逐行排版,给有事件的日期添加*:
# 初始化日历对象(周一为一周第一天) text_cal = TextCalendar(firstweekday=0) # 获取当月的日期矩阵 month_calendar = text_cal.monthdayscalendar(correct_year, correct_month) # 打印月份标题 print(text_cal.formatmonthname(correct_year, correct_month, width=20)) # 打印星期表头 print("Mon Tue Wed Thu Fri Sat Sun") # 遍历每一周,生成带标记的行 for week in month_calendar: week_line = [] for day in week: if day == 0: # 非当月日期,填充5个空格占位 week_line.append(" ") else: if day in event_days: # 有事件的日期,添加*并右对齐到5个字符 formatted_day = f"{day}*".rjust(5) else: # 无事件的日期,直接右对齐到5个字符 formatted_day = f"{day}".rjust(5) week_line.append(formatted_day) # 拼接一周的日期并打印 print(''.join(week_line))
运行后,有事件的日期就会显示成类似 5*这样的样式,完美对齐原日历格式。
方法二:修改formatmonth生成的字符串
如果想直接基于你原来的代码修改,可以把formatmonth输出的字符串拆分成行,再逐行替换有事件的日期:
# 先生成原始日历字符串 cal_str = text_cal.formatmonth(correct_year, correct_month, 5) lines = cal_str.split('\n') # 从第三行开始处理(前两行是标题和表头) for i in range(2, len(lines)): line = lines[i] if not line: continue # 把行转成列表方便修改 new_line = list(line) # 每5个字符对应一个日期列 for pos in range(0, 35, 5): day_str = line[pos:pos+5].strip() if day_str.isdigit(): day = int(day_str) if day in event_days: # 在日期末尾插入* day_pos = line[pos:pos+5].find(day_str) if day_pos != -1: insert_pos = pos + day_pos + len(day_str) if insert_pos < len(new_line): new_line.insert(insert_pos, '*') lines[i] = ''.join(new_line) # 打印修改后的日历 print('\n'.join(lines))
这种方法适合不想改动太多原有代码的场景,但要注意日期的对齐问题,遇到两位数日期时需要确保样式一致。
备注:内容来源于stack exchange,提问作者FrogFlex
相关产品推荐
相关产品推荐

