You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 13:07:38