为了数清还有几天到周末,我用python绘制了日历

日历的秘密

昨天,在看小侄子写作业的时候,发现了一个秘密:他在“演算纸”(计算数学题用的草纸)上画了非常多的日历。对此我感到了非常的困惑,“这是做什么的?”

后来,经过了我不懈的追问,小侄子终于说出了实情,“在学校太无聊,所以经常画日历,看看还有几天放假。”

哦!原来是这样!虽然这种行为不值得提倡,但是,小侄子想要放假的心情是可以理解的。所以,我决定帮帮他,研究一下怎么用python绘制出日历。

计算节假日

节假日

众所周知,一周有7天,其中周一到周五是工作日,周六周日是双休日。

每年元旦休息1天,春节休息3天,中秋,端午,清明节各休息1天,劳动节休息1天,国庆节休息3天,总共休息11天。

看起来,只要掌握了节日的规律,就可以知道假期了。但是,由于“调休”,周六周日也不总是休息日,其他工作日也可能变成休息日,所以,不能简单的这样做。

那么,要如何才能够计算出哪些日子是假日呢?答案是,必须要等到每年公布节假日才行。然后,根据公布的结果,进行手动标注。这听起来很麻烦,有没有什么更好的办法可以一劳永逸的解决问题呢?

使用中国日历库

安装:pip install chinesecalendar

升级:pip install -U chinesecalendar

中国日历是一个现有的库,可以方便的提供每一天是否是中国的节假日,是什么假日。其实现原理是,该日历库的作者为我们标注好了每一年的节假日,只需要调用即可。

import datetime
import calendar
import chinese_calendar as cc


def day_in_month(year, month):
    info = []
    days_in_month = calendar.monthrange(year, month)[1]
    for day in range(1, days_in_month + 1):
        date = datetime.datetime(year, month, day)
        weekday = date.weekday()
        on_holiday, holiday_name = cc.get_holiday_detail(date)
        info.append({
            "day": f"{year}-{month}-{day}",
            "weekday": weekday + 1,
            "on_holiday": on_holiday,
            "holiday_name": holiday_name
        })
    return info

print(day_in_month(2024, 11))

不过需要注意的是:由于该库中的节假日都是作者添加的,所以,在不更新升级的情况下,节假日是不会增多的。例如,现在还没有公布2025年的节假日,那么该库就不能处理2025年的节假日。需要在该库更新以后,手动更新该库,才可以用上最新实现,这听起来不太友好。毕竟,如果在网络受限的环境中,或者没有及时更新,即使已经到了新的年份,旧有的程序也不能很好工作。

使用爬虫程序

另一种想法就是,通过发送网络请求,从网络信息上得到最新的节假日信息。这样,信息总是新的,而且,也不需要更新库,就可以一直使用旧有程序(假设网络地址持续有效,且结构没有发生更改)。

当然,我是非常不推荐这种方法的,与之前的方法不同,该方法虽然可以在不主动更新的情况下持续有效,但是没办法用于没有网络的环境。当然更重要的是,未经许可的爬虫行为并非是一种好的行为,如无必要应该尽量减少或者避免。

有一位作者也发布了一个库,用于爬虫的方式得到节假日信息,该库叫做china_calendar,爬取信息的地址选择的便民查询

import china_calendar


is_holiday = china_calendar.is_holiday("2025-01-28")
print(is_holiday)

倒计时工具

计算时间差

虽然倒计时并不算是日历的一部分,但是可以快速帮助我们得知距离某天还有多久(比如说,还有几天放假)。首先,我们可以计算两个日期的时间差。

from datetime import datetime


def calculate_days_difference(date1, date2):
    difference = date2 - date1
    return difference.days


date1 = datetime(2024, 11, 11)
date2 = datetime(2025, 1, 28)

days_diff = calculate_days_difference(date1, date2)
print(f"两日期相差{days_diff}天")

计算倒计时

当然,如果是计算某个日期距离今天的时间差,就变成了倒计时功能了。

def countdown_to_date(target_date):
    today = datetime.now().date()
    difference = target_date.date() - today
    return difference.days


date = datetime(2025, 1, 28)
days_diff = countdown_to_date(date)
print(f"距离2025年除夕还有{days_diff}天")

绘制日历

画一个日历并不困难,但是想要画的好看,美观,需要考虑的就比较多了。不过,我们也可以用一个现成的日历实现,比如说fullcalendar,其可以在html的页面中,通过js代码,快速绘制一个功能丰富的日历。

我们可以通过script标签引入,然后,通过适当的js代码,就可以得到功能丰富的日历了,比如说,其官方网站提供的例子:

节假日信息的日历

结合之前的chinese_calendar库,我们就可以轻松实现一个带有节假日信息的日历了,我们将背景颜色设置为红色,当作假期。并且,通过flask作为后端,搭建一个web页面。

import datetime
import calendar

import chinese_calendar as cc
from flask import Flask, render_template, request, jsonify


app = Flask(__name__)

def add_holiday_info(year, month):
    info = []
    days_in_month = calendar.monthrange(year, month)[1]
    for day in range(1, days_in_month + 1):
        date = datetime.datetime(year, month, day)
        on_holiday, holiday_name = cc.get_holiday_detail(date)
        if on_holiday:
            info.append({
                "start": f"{year}-{month:02d}-{day:02d}",
                "title": "",
                "display": "background",
                "backgroundColor": "#ff0000"
            })

            if holiday_name:
                info.append({
                    "start": f"{year}-{month:02d}-{day:02d}",
                    "title": holiday_name
                })
    return info


def add_surrounding_year(year):
    info = []
    last_year = year - 1
    next_year = year + 1

    for month in range(1, 13):
        try:
            info.extend(add_holiday_info(last_year, month))
            info.extend(add_holiday_info(year, month))
            info.extend(add_holiday_info(next_year, month))
        except NotImplementedError as e:
            pass

    return info


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/api/events")
def get_events():
    year = int(request.args.get("year"))
    return jsonify(add_surrounding_year(year))

同样,我们需要创建一个index.html作为页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>带有假期显示的日历</title>
    <script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js'></script>
    <style>
        #calendar {
            max-width: 900px;
            margin: 0 auto;
        }
    </style>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            var calendarEl = document.getElementById('calendar');

            var calendar = new FullCalendar.Calendar(calendarEl, {
              initialView: 'dayGridMonth',
              locale: 'zh-cn',

              datesSet: function(info) {
                  var year = info.start.getFullYear();
                  var month = ('0' + (info.start.getMonth())).slice(-2);

                  fetch('/api/events?year=' + year + '&month=' + month)
                    .then(response => response.json())
                    .then(events => {
                        calendar.removeAllEvents();
                        calendar.addEventSource(events);
                    })
                    .catch(error => console.error('Error fetching events:', error));
              }
            });

            calendar.render();
        });
    </script>
</head>
<body>
    <div id="calendar"></div>
</body>
</html>

很好,现在,我们就得到了一个带有节假日信息的日历了!虽然看起来好像和常见的日历不太一样。不过正确且清晰。

 添加额外信息

日历上只有节假日信息,肯定不能让人满意,我们还可以在日历上添加一些自己的备注信息,让其在日历上显示出来。对于这个需求,我们不需要改动页面,只需要添加备注信息即可。

import datetime
import calendar

import chinese_calendar as cc
from flask import Flask, render_template, request, jsonify


app = Flask(__name__)


extra_info = [
    ("2024-12-12", "双十二购物"),
    ("2024-12-21", "冬至活动"),
    ("2024-12-24", "约女神看电影"),
    ("2024-12-25", "抓捕麋鹿老人")
]


def add_extra_info():
    info = []
    for i in extra_info:
        info.append({
            "start": i[0],
            "title": i[1]
        })
    return info


def add_holiday_info(year, month):
    info = []
    days_in_month = calendar.monthrange(year, month)[1]
    for day in range(1, days_in_month + 1):
        date = datetime.datetime(year, month, day)
        on_holiday, holiday_name = cc.get_holiday_detail(date)
        if on_holiday:
            info.append({
                "start": f"{year}-{month:02d}-{day:02d}",
                "title": "",
                "display": "background",
                "backgroundColor": "#ff0000"
            })
    return info


def add_surrounding_year(year):
    info = []
    last_year = year - 1
    next_year = year + 1

    for month in range(1, 13):
        try:
            info.extend(add_holiday_info(last_year, month))
            info.extend(add_holiday_info(year, month))
            info.extend(add_holiday_info(next_year, month))
        except NotImplementedError as e:
            pass

    return info


def add_all_info(year):
    info = []
    info.extend(add_extra_info())
    info.extend(add_surrounding_year(year))
    return info


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/api/events")
def get_events():
    year = int(request.args.get("year"))
    return jsonify(add_all_info(year))

经过简单的修改以后,我们成功添加了备注信息。

引用与致谢

chinese_calendar的pypi地址

 china_calendar的pypi地址

 fullcalendar的官方地址

P.S.虽然我们成功绘制了日历,但是小侄子看了并不感到开心,“在学校里画日历,也是一种消磨时间的好办法,你都用程序画好了,我在学校干嘛?”,当然是要好好学习啊喂! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/899532.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习面试笔试知识点-线性回归、逻辑回归(Logistics Regression)和支持向量机(SVM)

机器学习面试笔试知识点-线性回归、逻辑回归Logistics Regression和支持向量机SVM 一、线性回归1.线性回归的假设函数2.线性回归的损失函数(Loss Function)两者区别3.简述岭回归与Lasso回归以及使用场景4.什么场景下用L1、L2正则化5.什么是ElasticNet回归6.ElasticNet回归的使…

【设计模式】MyBatis 与经典设计模式:从ORM到设计的智慧

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 姊妹篇&#xff1a; 【设计模式】揭秘Spri…

计算机网络:数据链路层 —— 以太网(Ethernet)

文章目录 局域网局域网的主要特征 以太网以太网的发展100BASE-T 以太网物理层标准 吉比特以太网载波延伸物理层标准 10吉比特以太网汇聚层交换机物理层标准 40/100吉比特以太网传输媒体 局域网 局域网&#xff08;Local Area Network, LAN&#xff09;是一种计算机网络&#x…

GitLab-删除仓库分支(删除远程分支)

进入对应仓库选择对应的分支进行删除操作。

为什么学习使用数控加工中心吗?

现代制造业现代制造业对高精度、高效率的加工需求日益增长&#xff0c;数控加工中心作为核心设备&#xff0c;其操作和维护技能成为企业招聘的重要考量。企业需要能够熟练操作数控加工中心&#xff0c;并具备解决复杂加工问题的能力的人才。 学校通过系学习和实践&#xff0c;学…

不用编程,快速实现多台西门子PLC跟三菱PLC之间数据通讯

PLC通讯智能网关IGT-DSER模块支持汇川、西门子、三菱、欧姆龙、罗克韦尔AB、GE等各种品牌的PLC之间通讯&#xff0c;同时也支持PLC与Modbus协议的变频器、智能仪表等设备通讯。网关有多个网口、串口&#xff0c;也可选择WIFI无线通讯。PLC内无需编程开发&#xff0c;在智能网关…

基于SSM健身国际俱乐部系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;场地类别管理&#xff0c;场地信息管理&#xff0c;运动项目管理&#xff0c;场地类型管理&#xff0c;项目类型管理 用户账号功能包括&#xff1a;系统首页&#xff0c;个人中心…

使用SearXNG-搭建个人搜索引擎(附国内可用Docker镜像源)

介绍 SearXNG是聚合了七十多种搜索服务的开源搜索工具。我们可以匿名浏览页面&#xff0c;不会被记录和追踪。作为开发者&#xff0c;SearXNG也提供了清晰的API接口以及完整的开发文档。 部署 我们可以很方便地使用Docker和Docker compose部署SearXNG。下面给出Docker部署Se…

ChartCheck: Explainable Fact-Checking over Real-World Chart Images

论文地址: https://aclanthology.org/2024.findings-acl.828.pdfhttps://aclanthology.org/2024.findings-acl.828.pdf 1.概述 事实验证技术在自然语言处理领域获得了广泛关注,尤其是在针对误导性陈述的检查方面。然而,利用图表等数据可视化来传播信息误导的情况却很少受到…

反弹shell的小汇总

前提 理解正向连接和反向连接 正向连接&#xff1a;客户端主动发起连接到服务器或目标系统客户端充当主动方&#xff0c;向服务器发起连接请求&#xff0c;然后服务器接受并处理请求。 反向连接&#xff1a;目标系统&#xff08;通常是受害者&#xff09;主动建立与控制系统…

手机拍证件照,换正装有领衣服及底色的方法

证件照在我们的职业生涯的关键节点是经常会用到的&#xff0c;比如毕业入职、人事档案建立、升迁履历、执业资格考试和领证等&#xff0c;这些重要的证件照往往要求使用正装照&#xff0c;有时候手头没有合适的衣服&#xff0c;或者原先的证件照背景色不符合要求&#xff0c;就…

如何在算家云搭建ControlNext-SVD(视频生成)

一、ControlNext-SVD-V2简介 ControlNext-SVD-V2 是 ControlNext-SVD 的 V2 模型。其中 ControlNext-SVD 模型是通过添加 ControlNet 来控制 Stable Video Diffusion (SVD)&#xff0c;使用高分辨率视频训练&#xff0c;具体来说它可以将图片生成与指定姿态相匹配的高质量视频…

Python异常检测- 单类支持向量机(One-Class SVM)

系列文章目录 Python异常检测- Isolation Forest&#xff08;孤立森林&#xff09; python异常检测 - 随机离群选择Stochastic Outlier Selection (SOS) python异常检测-局部异常因子&#xff08;LOF&#xff09;算法 Python异常检测- DBSCAN 文章目录 系列文章目录前言一、On…

1024程序员日|向改变世界的程序员 致敬!

“给我一行代码&#xff0c;我将点亮整个服务器” “给我一个键盘&#xff0c;我就能征服数字世界” 今天 10月24号 是广大程序员“法定”节日&#xff08;据说是自定的&#xff09; 因为1024是2的十次方 二进制计数的基本计量单位 1GB 1024MB&#xff0c;1MB 1024KB……

机器学习理论系列——线性模型(上)

系列文章目录 文章目录 线性模型线性回归线性回归与线性模型一元和多元线性回归最小二乘法损失函数与均方误差最小二乘与闭式解 正则化为什么引入正则化 L 1 L^1 L1&#xff0c; L 2 L^2 L2正则化 梯度下降什么是梯度下降算法上的体现 附录 线性模型 线性是数学中的基本概念&a…

面试官:Zabbix 和 Prometheus 到底怎么选?

新公司要上监控&#xff0c;面试提到了 Prometheus 是公司需要的监控解决方案&#xff0c;我当然是选择跟风了。 之前主要做的是 Zabbix&#xff0c;既然公司需要 Prometheus&#xff0c;那没办法&#xff0c;只能好好对比一番&#xff0c;了解下&#xff0c;毕竟技多不压身。…

家庭宽带的ip地址是固定的吗?宽带ip地址怎么修改‌

在家庭网络环境中&#xff0c;IP地址的分配和管理是用户常关注的问题。本文将探讨家庭宽带IP地址的固定性&#xff0c;并介绍如何修改宽带IP地址&#xff0c;以满足用户的不同需求。 一、家庭宽带的IP地址是否固定? 关于家庭宽带的IP地址是否固定&#xff0c;答案并非一概而论…

Could not find artifact cn.hutool:hutool-all:jar:8.1 in central 导入Hutool报错

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.9</version></dependency> 引入hutool 8.1版本的工具…

采用 Redis+数据库为建立线上药品销售系统

目录 案例 【说明】 【问题1】(9分) 【问题2】(9分) 【问题3】(7 分) 【答案】 【问题1】答案 【问题2】答案 【问题3】答案 相关推荐 案例 阅读以下关于数据库设计的叙述&#xff0c;回答问题 1 至问题 3 。 【说明】 某医药销售企业因业务发展&#xff0c;需要建立…

Windows图形界面(GUI)-QT-C/C++ - QT基本概念 - 安装配置 - QT Creator

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 QT 基本概念 QT 安装配置 QT Creator 界面布局 快捷操作 QT 基本概念 QT 简介 QT是一个跨平台的C图形用户界面应用程序开发框架。 QT支持多种操作系统&#xff0c;包括Windows、Lin…