Python 实现日期计算与日历格式化输出(万年历)

目录

一、引言

二、需求分析

三、实现思路

四、代码实现

五、代码分析

六、测试与验证

七、总结与展望


         在日常的编程中,我们经常会遇到与日期相关的问题,比如计算两个日期之间的天数差、确定某个特定日期是星期几以及格式化输出日历等。本文将详细介绍如何使用 Python 实现这些功能,并通过一个完整的示例代码进行演示。

一、引言

        日期在我们的生活中无处不在,无论是在项目管理、日程安排还是历史研究等领域,都需要对日期进行准确的计算和处理。Python 作为一种强大的编程语言,提供了丰富的工具和库来处理日期和时间相关的任务。在本文中,我们将使用 Python 的基本语法和逻辑来实现对日期的计算和日历的格式化输出。

二、需求分析

我们的目标是实现以下功能:

  1. 判断给定的年份是否为闰年。
  2. 根据给定的年份和月份,计算该月份的天数。
  3. 计算给定年份和月份距离 1900 年 1 月 1 日的总天数。
  4. 确定给定年份和月份的第一天是星期几。
  5. 格式化输出给定年份和月份的日历。

三、实现思路

  1. 判断闰年

    • 闰年的判断规则是能被 4 整除但不能被 100 整除的年份为闰年,或者能被 400 整除的年份也是闰年。
    • 使用 Python 的条件判断语句来实现这个规则。
  2. 计算月份天数

    • 对于 1、3、5、7、8、10、12 这几个月份,天数为 31 天。
    • 对于 4、6、9、11 这几个月份,天数为 30 天。
    • 对于 2 月份,需要根据是否为闰年来确定天数,闰年为 29 天,非闰年为 28 天。
  3. 计算总天数

    • 首先计算从 1900 年到给定年份之间的总天数,对于闰年的年份,总天数加 366 天,非闰年的年份加 365 天。
    • 然后计算从给定年份的 1 月份到给定月份之间的总天数,根据每个月的天数进行累加。
  4. 确定第一天是星期几

    • 使用总天数对 7 取余,得到的结果即为给定日期是星期几。
    • 根据余数的值进行相应的输出,确定第一天是星期几。
  5. 格式化输出日历

    • 首先输出星期几的表头,即 “星期日 \t 星期一 \t 星期二 \t 星期三 \t 星期四 \t 星期五 \t 星期六 \t”。
    • 根据给定月份的第一天是星期几,在输出日期之前先输出相应数量的制表符,以实现对齐。
    • 然后循环输出每个日期,每输出一个日期后输出两个制表符,以保持格式整齐。
    • 每输出 7 个日期后进行换行,以实现日历的格式化输出。

四、代码实现

以下是实现上述功能的 Python 代码:

# 判断是否为闰年的
def isLeapYear(year):
    if year % 4 == 0 and (year % 100!= 0 or year % 400 == 0):
        return True
    else:
        return False

# 给定月份,算出来该月份有几天
def getDayOfMonth(year, month):
    if month == 1 or month == 3 or month == 5 or month == 7 or month == 8 or month == 10 or month == 12:
        return 31
    elif month == 4 or month == 6 or month == 9 or month == 11:
        return 30
    else:
        if isLeapYear(year):
            return 29
        else:
            return 28

while True:
    yearStr = input("请输入年份(数字|年份大于 1900)输入 q 退出:")
    if yearStr == "q":
        print("你已退出,欢迎下次再来")
        break
    elif yearStr.isdigit():
        year = int(yearStr)
        monthStr = input("请输入月份(1-12):")
        if monthStr.isdigit() and 1 <= int(monthStr) <= 12:
            month = int(monthStr)
            # 计算该年月距离 1900-01-01 的总天数
            totalDays = 0
            for y in range(1900, year):
                if isLeapYear(y):
                    totalDays += 366
                else:
                    totalDays += 365
            # 将剩余月份的天数相加
            for m in range(1, month):
                totalDays += getDayOfMonth(year, m)

            print(f"{yearStr}年{monthStr}距离 1900-01-01 相差{totalDays}天")
            # 该年该月的第一天是星期几
            firstDayOfMonth = (totalDays + 1) % 7
            match firstDayOfMonth:
                case 0:
                    print(f"{yearStr}年{monthStr}月的第一天是星期日")
                case 1:
                    print(f"{yearStr}年{monthStr}月的第一天是星期一")
                case 2:
                    print(f"{yearStr}年{monthStr}月的第一天是星期二")
                case 3:
                    print(f"{yearStr}年{monthStr}月的第一天是星期三")
                case 4:
                    print(f"{yearStr}年{monthStr}月的第一天是星期四")
                case 5:
                    print(f"{yearStr}年{monthStr}月的第一天是星期五")
                case 6:
                    print(f"{yearStr}年{monthStr}月的第一天是星期六")
            # 接着进行格式化输出
            print("星期日\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六\t")
            # 规律 星期几就打印几个空格
            # 一个 tab 两个汉字
            # print("\t"*2)
            counter = firstDayOfMonth
            print("\t" * 2 * firstDayOfMonth, end="")
            # 打印几号
            dayOfMonth = getDayOfMonth(year, month)
            for day in range(1, dayOfMonth + 1):
                print(day, end="\t\t")
                counter += 1
                # 控制换行,没打印 7 个值包括空白都换行
                if counter % 7 == 0:
                    print()
            print()

        else:
            print("输入的数据不合法,请输入 1~12 之间的数字")
    else:
        print("请输入数字")

五、代码分析

  1. 判断闰年函数

    • isLeapYear(year)函数接受一个年份作为参数,使用条件判断语句判断该年份是否为闰年。
    • 如果年份能被 4 整除但不能被 100 整除,或者能被 400 整除,则返回True,表示是闰年;否则返回False,表示不是闰年。
  2. 计算月份天数函数

    • getDayOfMonth(year, month)函数接受年份和月份作为参数,根据月份的不同返回相应的天数。
    • 对于 1、3、5、7、8、10、12 这几个月份,直接返回 31 天。
    • 对于 4、6、9、11 这几个月份,直接返回 30 天。
    • 对于 2 月份,根据是否为闰年调用isLeapYear(year)函数来确定天数,闰年返回 29 天,非闰年返回 28 天。
  3. 主循环部分

    • 使用while True循环,以便用户可以多次输入年份和月份进行计算。
    • 首先接收用户输入的年份,如果用户输入q,则退出循环,打印退出信息。
    • 如果用户输入的是数字,则将其转换为整数类型,并继续接收用户输入的月份。
    • 如果月份输入合法(1-12 之间的数字),则进行日期计算和日历格式化输出。
    • 如果月份输入不合法,则打印错误信息,提示用户重新输入。
  4. 计算总天数部分

    • 首先计算从 1900 年到给定年份之间的总天数,使用一个循环遍历从 1900 年到给定年份之间的每一年,如果是闰年,则总天数加 366 天,非闰年则加 365 天。
    • 然后计算从给定年份的 1 月份到给定月份之间的总天数,使用另一个循环遍历从 1 月份到给定月份之间的每一个月,根据每个月的天数调用getDayOfMonth(year, m)函数进行累加。
  5. 确定第一天是星期几部分

    • 使用总天数加 1 对 7 取余,得到的结果即为给定日期是星期几。
    • 使用match语句根据余数的值进行相应的输出,确定第一天是星期几。
  6. 格式化输出日历部分

    • 首先输出星期几的表头,即 “星期日 \t 星期一 \t 星期二 \t 星期三 \t 星期四 \t 星期五 \t 星期六 \t”。
    • 根据给定月份的第一天是星期几,在输出日期之前先输出相应数量的制表符,以实现对齐。使用counter变量记录已经输出的日期数量,初始值为第一天是星期几的值。
    • 然后循环输出每个日期,每输出一个日期后输出两个制表符,以保持格式整齐。
    • 每输出 7 个日期后进行换行,以实现日历的格式化输出。使用counter变量对 7 取余,当余数为 0 时进行换行。

六、测试与验证

为了验证我们的代码是否正确,我们可以进行以下测试:

  1. 输入合法的年份和月份,检查输出的总天数、第一天是星期几以及日历格式是否正确。
  2. 输入闰年和非闰年的年份,检查 2 月份的天数是否正确。
  3. 输入不合法的年份或月份,检查是否能正确提示用户重新输入。

以下是一些测试示例:

测试 1:输入 2024 年 10 月

输入:

2024
10

输出:

请输入年份(数字|年份大于1900)输入q退出:2024
请输入月份(1-12):10
2024年10距离 1900-01-01相差45564天
2024年10月的第一天是星期二
星期日	星期一	星期二	星期三	星期四	星期五	星期六	
				1		2		3		4		5		
6		7		8		9		10		11		12		
13		14		15		16		17		18		19		
20		21		22		23		24		25		26		
27		28		29		30		31		

测试 2:输入 2023 年 2 月

输入:

2023
2

输出:

请输入年份(数字|年份大于1900)输入q退出:2023
请输入月份(1-12):2
2023年2距离 1900-01-01相差44956天
2023年2月的第一天是星期三
星期日	星期一	星期二	星期三	星期四	星期五	星期六	
						1		2		3		4		
5		6		7		8		9		10		11		
12		13		14		15		16		17		18		
19		20		21		22		23		24		25		
26		27		28		

测试 3:输入不合法的年份或月份

输入:

abc
10

输出:

请输入年份(数字|年份大于1900)输入q退出:abc
请输入数字

输入:

2024
13

输出:

请输入年份(数字|年份大于1900)输入q退出:2024
请输入月份(1-12):13
输入的数据不合法,请输入1~12之间的数字

测试 4:输入q退出

 输入:

q

输出:

请输入年份(数字|年份大于1900)输入q退出:q
你已退出,欢迎下次再来

通过以上测试,我们可以看到代码能够正确地处理各种输入情况,并输出正确的结果。

七、总结与展望

        本文介绍了如何使用 Python 实现日期计算和日历格式化输出的功能。通过判断闰年、计算月份天数、计算总天数、确定第一天是星期几以及格式化输出日历等步骤,我们成功地实现了一个简单而实用的日期处理程序。

        这个程序可以应用于各种场景,比如日程安排、项目管理、历史研究等。同时,我们也可以对程序进行进一步的扩展和优化,比如添加更多的功能,如计算两个日期之间的间隔天数、判断某个日期是否在特定的时间段内等。

        此外,我们还可以使用 Python 的第三方库来处理日期和时间相关的任务,比如datetime模块和pandas库等。这些库提供了更强大的功能和更方便的接口,可以大大提高我们的开发效率。

        Python 是一种非常强大的编程语言,它提供了丰富的工具和库来处理各种任务。通过本文的介绍,希望读者能够对 Python 的日期处理有更深入的了解,并能够在实际的项目中应用这些知识。

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

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

相关文章

深度学习:SGD的缺点

首先看下述函数&#xff1a; 最小值为x0&#xff0c;y0处 先了解下它的梯度特征。了理解其梯度特征&#xff0c;我们需要计算其梯度向量。 梯度向量 ∇f 是函数 f 在每个变量方向上的偏导数组成的向量。具体来说&#xff1a; ∇f(∂f/∂x,∂f∂/y) 首先&#xff0c;我们计算 f …

R语言机器学习算法实战系列(十二)线性判别分析分类算法 (Linear Discriminant Analysis)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍LDA的原理LDA的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve保存模型总结优点:缺…

如何用猿大师办公助手实现OA系统中Word公文/合同在线编辑及流转?

在OA系统或者合同管理系统中&#xff0c;我们会经常遇到网页在线编辑Word文档形式的公文及合同的情况&#xff0c;并且需要上级对下级的公文进行批注等操作&#xff0c;或者不同部门的人需要签字审核&#xff0c;这就需要用到文档流转功能&#xff0c;如何用猿大师办公助手实现…

3DS MAX三维建模平面基础与修改工具(图形编辑与二维建模修改工具)

又是一年1024祝大家程序员节日快乐 3DS MAX三维建模平面基础与修改工具&#xff08;图形编辑与二维建模修改工具&#xff09; 欢迎大家来学习3DS MAX教程&#xff0c;在这里先说一下研究好3ds Max一定要一边看教程一边要自己学的操作才能更快的进步&#xff0c;预祝大家学习顺利…

医疗保健知识中台:引领医疗行业智能化转型的新篇章

前言 随着科技的迅猛进步&#xff0c;医疗保健领域正迎来一场深刻的智能化变革。在这场变革中&#xff0c;知识中台作为医疗行业智能化升级的重要基石&#xff0c;正逐步成为提升医疗服务质量和效率的关键驱动力。本文将深入剖析医疗保健知识中台的内容构成、应用场景以及更新…

控制回撤哪家强?魔改DMA指标,比MACD更强大!

一、DMA的基本原理 前边我们讲过MACD&#xff0c;它利用了短期EMA和长期EMA的偏离来做文章&#xff0c;今天要讲的DMA也是类似的思路。DMA和MACD的本质区别在于&#xff0c;它在计算均线时将EMA替换为了SMA&#xff0c;其他的两者基本一致。 其完整的计算公式如下。很明显&am…

C++设计模式创建型模式———简单工厂模式、工厂方法模式、抽象工厂模式

文章目录 一、引言二、简单工厂模式三、工厂方法模式三、抽象工厂模式四、总结 一、引言 创建一个类对象的传统方式是使用关键字new &#xff0c; 因为用 new 创建的类对象是一个堆对象&#xff0c;可以实现多态。工厂模式通过把创建对象的代码包装起来&#xff0c;实现创建对…

生成式 AI 与向量搜索如何扩大零售运营:巨大潜力尚待挖掘

在竞争日益激烈的零售领域&#xff0c;行业领导者始终在探索革新客户体验和优化运营的新途径&#xff0c;而生成式 AI 和向量搜索在这方面将大有可为。从个性化营销到高效库存管理&#xff0c;二者在零售领域的诸多应用场景中都展现出变革性潜力&#xff0c;已成为保持行业领先…

leetcode438. 找到字符串中所有字母异位词

题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 &quo…

【IC每日一题】

IC每日一题 1 组合逻辑VS时序逻辑1.1 组合逻辑1.1.1 竞争冒险1.1.2 解决方法 1.2 时序逻辑1.3 比较1.4 场景 2 计数器2.1 代码片段法2.2 实现计数器--异步复位&#xff0c;带clear端&#xff0c;计10则归0&#xff1b; 1 组合逻辑VS时序逻辑 1.1 组合逻辑 组合逻辑&#xff1…

MySQL练习题-求连续、累计、环比和同比问题

目录 准备数据 1&#xff09;求不同产品每个月截止当月最近3个月的平均销售额 2&#xff09;求不同产品截止当月的累计销售额 3&#xff09;求环比增长率和同比增长率 准备数据 -- product 表示产品名称&#xff0c;ym 表示年月&#xff0c;amount 表示销售金额&#xff…

【K8S系列】Kubernetes Service 基础知识 详细介绍

在 Kubernetes 中&#xff0c;Service 是一种抽象的资源&#xff0c;用于定义一组 Pod 的访问策略。它为这些 Pod 提供了一个稳定的访问入口&#xff0c;解决了 Pod 可能频繁变化的问题。本文将详细介绍 Kubernetes Service 的类型、功能、使用场景、DNS 和负载均衡等方面。 1.…

react 总结+复习+应用加深

文章目录 一、React生命周期1. 挂载阶段&#xff08;Mounting&#xff09;补充2. 更新阶段&#xff08;Updating&#xff09;补充 static getDerivedStateFromProps 更新阶段应用补充 getSnapshotBeforeUpdate3. 卸载阶段&#xff08;Unmounting&#xff09; 二、React组件间的…

windows 训练yolov8官方数据集

第一步&#xff1a;安装Anaconda3-2024.06-1-Windows-x86_64.exe 下载地址&#xff1a;https://repo.anaconda.com/archive/ 第二步&#xff1a;创建环境 打开Anaconda Prompt 输入 conda info -e 打印&#xff1a; 已经安装了一些环境&#xff0c;然后我们创建新的环境&a…

大模型面试挺水的,面试官听到这些直接过

AI大模型600道面试总结(LLM) 1、目前主流的开源模型体系有哪些? 目前 主流的开源模型体系 分三种: 第一种:prefixDecoder系 介绍:输入双向注意力&#xff0c;输出单向注意力 代表模型:ChatGLM、ChaGLM2、U-PaLM 第二种:causal Decader系 介绍:从左到右的单向注意力 代表…

【状态机DP】力扣1186. 删除一次得到子数组最大和

给你一个整数数组&#xff0c;返回它的某个 非空 子数组&#xff08;连续元素&#xff09;在执行一次可选的删除操作后&#xff0c;所能得到的最大元素总和。换句话说&#xff0c;你可以从原数组中选出一个子数组&#xff0c;并可以决定要不要从中删除一个元素&#xff08;只能…

驱动-----LED

前面我们学习了demo1的驱动的编写,在写LED的时候,我们可以在demo1的基础上修改。 1.首先就是修改名字,把所有的demo改成led,使用一个字符串替换指令。 2.设备号要变 3.想操作硬件,LED的初始化,亮灭 LED的初始化,在open的时候实现。 亮灭在write的时候实现。 现在就是…

技术成神之路:设计模式(二十三)解释器模式

相关文章&#xff1a;技术成神之路&#xff1a;二十三种设计模式(导航页) 介绍 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为设计模式&#xff0c;用于定义一种语言的文法表示&#xff0c;并提供一个解释器来处理这种文法。它用于处理具有特定语法或表达…

移远通信斩获两项车载大奖,引领全球智能网联汽车产业发展

10月24日&#xff0c;由盖世汽车主办的2024第六届金辑奖中国汽车新供应链百强颁奖盛典在上海隆重举行。 作为全球领先的物联网和车联网整体解决方案供应商&#xff0c;移远通信凭借智能座舱模组AG855G、车载5G模组AG59x系列&#xff0c;以及公司在海外市场的优异表现&#xff0…

Mac 上无法烧录 ESP32C3 的问题记录:A fatal error occurred:Failed to write to target RAM

文章目录 问题描述驱动下载地址问题解决&#xff1a;安装 CH343 驱动踩的坑日志是乱码 问题描述 我代码编译可以&#xff0c;但是就是烧录不上去 A fatal error occurred:Failed to write to target RAM(result was 01070000:Operation timed out) Uploaderror:上传失败&…