生日、纪念日多功能日子记录和提醒网站

一、创作原因

因为家里人口比较多,有时候会忘记某人的生日或者是重要的日子,所以做了一个记录、提醒的网站。

二、制作分享

# 导入必要的库
import lunardate  # 处理农历日期转换
from datetime import datetime, date  # 处理公历日期和当前时间
import warnings

warnings.filterwarnings('ignore')  # 忽略无关警告


def lunar_to_current_solar(lunar_month: int, lunar_day: int) -> date | None:
    """
    将指定的农历月日转换为今年对应的公历日期
    :param lunar_month: 农历月(整数)
    :param lunar_day: 农历日(整数)
    :return: 今年对应的公历日期(date对象),转换失败返回None
    """
    try:
        current_year = datetime.now().year
        # 创建今年的农历日期对象(自动处理闰月等特殊情况)
        lunar_date_obj = lunardate.LunarDate(current_year, lunar_month, lunar_day)
        # 转换为公历日期
        solar_date_obj = lunar_date_obj.toSolarDate()
        return solar_date_obj
    except ValueError as e:
        print(f"⚠️  农历日期转换失败:{e}")
        return None


def calculate_age(birth_lunar_year: int) -> int:
    """
    根据农历出生年计算今年的年龄
    :param birth_lunar_year: 农历出生年(整数)
    :return: 今年的年龄(整数)
    """
    current_year = datetime.now().year
    return current_year - birth_lunar_year


def input_lunar_date(prompt: str) -> tuple[int, int, int] | None:
    """
    通用的农历日期输入函数(格式:年-月-日 或 月-日)
    :param prompt: 输入提示语
    :return: (年, 月, 日) 或 None(输入失败);重要日子返回(0, 月, 日)
    """
    while True:
        user_input = input(prompt).strip()
        if not user_input:
            print("❌ 输入不能为空,请重新输入!")
            continue

        # 拆分输入(支持 年-月-日 或 月-日 两种格式)
        parts = user_input.split('-')
        try:
            if len(parts) == 3:
                # 生日场景:年-月-日
                year, month, day = map(int, parts)
                if 1 <= month <= 12 and 1 <= day <= 30:  # 农历日期基础校验
                    return year, month, day
                else:
                    print("❌ 月份需1-12,日期需1-30,请重新输入!")
            elif len(parts) == 2:
                # 重要日子场景:月-日(无年份)
                month, day = map(int, parts)
                if 1 <= month <= 12 and 1 <= day <= 30:
                    return 0, month, day  # 用0标记无年份
                else:
                    print("❌ 月份需1-12,日期需1-30,请重新输入!")
            else:
                print("❌ 格式错误!请按指定格式输入(年-月-日 或 月-日)")
        except ValueError:
            print("❌ 输入必须为数字,请重新输入!")


def batch_input_family_birthdays() -> dict:
    """
    批量输入家庭成员生日信息
    :return: 家庭成员字典 {姓名: (农历年, 农历月, 农历日)}
    """
    family_birthdays = {}
    print("\n===== 开始输入家庭成员生日(输入完成后按回车结束)=====")
    while True:
        name = input("请输入家庭成员姓名(直接回车结束输入):").strip()
        if not name:
            break  # 空输入则结束

        # 输入该成员的农历生日
        date_result = input_lunar_date(f"请输入{name}的农历生日(格式:年-月-日,例如:1995-8-15):")
        if date_result:
            family_birthdays[name] = date_result
            print(f"✅ 已记录 {name} 的生日:{date_result[0]}年{date_result[1]}月{date_result[2]}日")
    return family_birthdays


def batch_input_important_days() -> dict:
    """
    批量输入重要日子信息
    :return: 重要日子字典 {日子名称: (农历月, 农历日)}
    """
    important_days = {}
    print("\n===== 开始输入重要日子(输入完成后按回车结束)=====")
    while True:
        day_name = input("请输入重要日子名称(如:结婚纪念日、春节,直接回车结束输入):").strip()
        if not day_name:
            break

        # 输入该日子的农历日期(仅月-日)
        date_result = input_lunar_date(f"请输入{day_name}的公历日期(格式:月-日,例如:1-1):")
        if date_result:
            _, month, day = date_result
            important_days[day_name] = (month, day)
            print(f"✅ 已记录 {day_name}:公历{month}月{day}日")
    return important_days


def generate_reminder(date_obj: date, title: str) -> str:
    """
    生成通用的提醒文案
    :param date_obj: 公历日期对象
    :param title: 提醒标题(如“张三的生日”、“春节”)
    :return: 提醒文案字符串
    """
    today = datetime.now().date()
    days_diff = (date_obj - today).days

    if days_diff == 0:
        return f"🎉 今日提醒:{title}(公历{date_obj}),今天就是当天!"
    elif days_diff > 0:
        return f"🎯 即将到来:{title}(公历{date_obj}),还有{days_diff}天!"
    else:
        # 今年已过,计算明年的日期
        next_year = today.year + 1
        next_lunar_date = lunardate.LunarDate(next_year, date_obj.month, date_obj.day)
        next_solar_date = next_lunar_date.toSolarDate()
        next_days_diff = (next_solar_date - today).days
        return f"📝 已过备忘:{title}今年(公历{date_obj})已过,明年是{next_solar_date},还有{next_days_diff}天!"

主函数:

def main():
    """主函数:整合所有功能"""
    print("===== 家庭生日&重要日子提醒工具 =====")

    # 1. 批量输入家庭成员生日
    family_birthdays = batch_input_family_birthdays()
    # 2. 批量输入重要日子
    important_days = batch_input_important_days()

    # 3. 输出并提醒家庭成员生日
    if family_birthdays:
        print("\n" + "=" * 80)
        print("🎂 家庭成员今年生日信息汇总")
        print("=" * 80)
        for name, (birth_year, lunar_month, lunar_day) in family_birthdays.items():
            # 转换为今年的公历生日
            solar_birthday = lunar_to_current_solar(lunar_month, lunar_day)
            if solar_birthday:
                age = calculate_age(birth_year)
                reminder = generate_reminder(solar_birthday, f"{name}的{age}岁生日")
                print(f"\n【{name}】")
                print(f"  农历生日:{birth_year}年{lunar_month}月{lunar_day}日")
                print(f"  今年公历生日:{solar_birthday}")
                print(f"  今年年龄:{age}岁")
                print(f"  提醒:{reminder}")

    # 4. 输出并提醒重要日子
    if important_days:
        print("\n" + "=" * 80)
        print("🎊 重要日子今年日期汇总")
        print("=" * 80)
        current_year = datetime.now().year

        for day_name, (lunar_month, lunar_day) in important_days.items():
            # 创建今年的公历日期对象(自动处理闰月等特殊情况)

            solar_day = datetime(current_year, lunar_month, lunar_day).date()

            if solar_day:
                reminder = generate_reminder(solar_day, day_name)
                print(f"\n【{day_name}】")
                print(f"  公历日期:{lunar_month}月{lunar_day}日")
                print(f"  今年公历日期:{solar_day}")
                print(f"  提醒:{reminder}")

    # 无数据提示
    if not family_birthdays and not important_days:
        print("\n⚠️  未记录任何家庭成员生日或重要日子!")


if __name__ == "__main__":
    # 安装依赖(首次运行需执行)
    # pip install lunardate
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EricZhengX

感谢大佬投喂!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值