判断第几天/判断第几天(1)

去社区提问

简介:今天起进入一个新的案例学习,我们将实现一些对日期的操作。

案例描述

欢迎继续学习Python认知打卡课~今天起我们将了解一个新的案例,通过它你会掌握更多有趣的Python知识,让我们开始今天的旅程吧。

前面的课程中,我们已经用Python实现了汇率兑换、基础代谢率计算(减肥助手)、存钱挑战三个日常生活中的实用小工具。今天的案例和日期有关,我们先来看看具体要求:

用户输入某年某月某日的信息,用程序计算出这一天是一年中的第几天。

(就是这么一行简单直白的要求)

例如用户输入日期2017/02/05,请判断这是17年的第几天?

输入日期2021/04/21,这是2021年的第几天?

你可以自己先想一想问题的解决思路,再往下看案例的分析~

案例分析

细心的我们会发觉,想通过日期判断天数将面临下面三个严肃的问题:

1.每个月的天数不同,在相加时需要根据实际情况来判断。

2.闰年与平年二月份的天数不同。

3.有了问题二就会引出问题三,如何判断年份是平年闰年。

别慌,稳住,我们来一个个解决它~

每个月天数不同

由于每个月的天数不同,例如输入日期是2021/06/05,我们不能简单粗暴地把6月之前的每天都假想为30天,用30✖️5代替1-5月的天数总和。

此时大脑飞速旋转,想想之前学过的知识有没有能用来解决这个问题的呢?

突然灵光一闪!列表好像…可以拿来用一下。

可以在列表中放置12个元素,分别是12个月的天数,然后操作列表中的元素相加得到天数信息。

当然没问题!不过今天我要为你介绍一个新的序列类型:元组

  • 元组(tuple)是一个特殊的序列类型,使用圆括号来表示,用逗号分隔元素,如:
  1. t1 = ('red','blue','green')
  2. t2 = (31,28,31,40)

它的大多数操作都和列表相同。

和列表一样,元组中的元素可以是不同类型的,元素之间也存在先后关联,可以通过索引访问元组中的元素。

访问方式和列表相同都使用方括号[]来完成。我们来看个小例子:

代码练习:

编程区

  1. t = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
  2. print('元组的第一个元素:',t[0])
  3. print('元组第2-5个元素:',t[1:5])

终端区

相比于列表,元组有一个突出的特点在于它一旦被创建就不能修改,这就使得代码更安全。

一般用于表达固定数据项(数据内容固定不变)和函数多返回值(当函数的返回值不止一个时,就是元组类型)等情况。

关于函数多返回值的内容在后面的课程中会为大家详细讲解。

我们要记住元组创建后不能修改这个关键点。来看下面两个例子。

首先定义一个列表,尝试改变其中的元素看看结果:

代码练习:

编程区

  1. l = [1,2,3,4,5]
  2. l[0] = 100
  3. print(l)

终端区

列表的第一个元素被修改成了100,再定义一个元组进行同样操作,又会怎样呢?

代码练习:

编程区

  1. t = (1,2,3,4,5)
  2. t[0] = 100
  3. print(t)

终端区

当我们企图修改元组中的元素时,程序就报错了~

好啦现在我们可以创建一个元组,把每个月的天数存放进去:

  1. days_in_month_tup = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

判断平年闰年

上面的元组中我们将二月天数设定为28,而闰年时二月的天数应该是29。如何判断一个年份是否是闰年呢?

判断闰年有一句口诀是:‘四年一闰,百年不闰,四百年再闰’

下面我们来解读这句话,它应该被拆解为两个条件,满足其中任意一项,都能判断年份是闰年:

一个数能被4整除,也就是这个数字➗4余数是0。Python中也有专门获取除法余数的方式:%

%百分号代表取余,来看下面的例子:

代码练习:

编程区

  1. print(6%3)
  2. print(10%3)

终端区

上面两行代码分别得到了6/3和10/3的余数。

因此,判断年份year是否能被4、100、400整除,只需要看year%4year%100year%400是否等于0。

代码练习:

编程区

  1. year = 2021
  2. if ((year % 4 == 0) and (year % 100 !=0)) or (year % 400 ==0):
  3. print('是闰年')
  4. else:
  5. print('不是闰年')

终端区

逻辑运算符or表示或者,两个条件满足一个就成立;and表示与,需要左右两边的条件均为真才能成立。关于逻辑运算符我们也会在后续的课程为你详细解读~

两个棘手的问题都解决了,现在可以着手写判断天数的程序了!

我们的大致思路是:

用户输入日期信息:

  1. input_date_str = input('请输入日期(yyyy/mm/dd):')

上节课我们学习过处理时间的模块:datetime,它提供了解析字符串的方法datetime.strptime()。我们来导入模块,完成日期格式转换:

  1. import datetime
  2. input_date_str = input('请输入日期(yyyy/mm/dd):')
  3. input_date = datetime.datetime.strptime(input_date_str,'%Y/%m/%d')

我们可以把处理后日期打印出来看看是否转换成功,验证前面代码操作的正确性:

  1. import datetime
  2. input_date_str = input('请输入日期(yyyy/mm/dd):')
  3. input_date = datetime.datetime.strptime(input_date_str,'%Y/%m/%d')
  4. print(input_date)

日期被转换为标准的datetime格式,接下来就可以获取年、月、日的数字了:

  1. year = input_date.year
  2. month = input_date.month
  3. day = input_date.day

假设输入2021/04/05,计算这个日期是一年中的第几天,可以将1、2、3月的天数加和,再加上4月额外的5天得到结果。

同样的思路,假设输入日期2020/06/21,则需要求和1、2、3、4、5月的天数,再加6月的21天,就是最终答案。

把每个月的天数存放在元组days_in_month_tup中:

  1. days_in_month_tup = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

月份month如果是3,求元组前2个元素即1、2月的天数和

月份month如果是6,求元组前5个元素即1、2、3、4、5月天数和

利用元组的区间索引,得到需求和的元组元素:

  1. days_in_month_tup[:month-1]

:冒号左边为空白代表从元组第一个元素开始,取到:冒号右边索引month-1的前一个元素。下面这个例子能更直观地看出这行代码的作用。

代码练习:

编程区

  1. month = 4
  2. days_in_month_tup = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
  3. print(days_in_month_tup[:month-1])

终端区

我们用sum()函数来求和,再加上天数得到结果,存放在变量days中:

  1. days = sum(days_in_month_tup[: month - 1]) + day

目前为止,我们已经完成了大部分工作,距离成功只有一步之遥啦。

  1. import datetime
  2. input_date_str = input('请输入日期(yyyy/mm/dd):')
  3. input_date = datetime.datetime.strptime(input_date_str, '%Y/%m/%d')
  4. print(input_date)
  5. year = input_date.year
  6. month = input_date.month
  7. day = input_date.day
  8. # 计算之前月份天数的总和以及当前月份天数
  9. days_in_month_tup = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
  10. # print(days_in_month_tup[: month - 1])
  11. days = sum(days_in_month_tup[: month - 1]) + day

有没有发现?我们在元组中设置2月的天数是28,而实际情况中,用户输入年份是闰年时,2月应该是29天。

所以当用户输入年份为闰年,并且月份大于2时,还应该给总天数days+1,才得到正确结果。

  1. # 判断闰年
  2. if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)):
  3. if month > 2:
  4. days += 1

最后利用格式化输出打印天数:

  1. import datetime
  2. input_date_str = input('请输入日期(yyyy/mm/dd):')
  3. input_date = datetime.datetime.strptime(input_date_str, '%Y/%m/%d')
  4. print(input_date)
  5. year = input_date.year
  6. month = input_date.month
  7. day = input_date.day
  8. # 计算之前月份天数的总和以及当前月份天数
  9. days_in_month_tup = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
  10. days = sum(days_in_month_tup[: month - 1]) + day
  11. # 判断闰年
  12. if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)):
  13. if month > 2:
  14. days += 1
  15. print('这是第{}天。'.format(days))
本关总结
  • 元组
  • 复习datetime模块

解析字符串格式为标准datetime时间格式:datetime.strptime()

下节预告

这节课的最后留给你一个小思考题:如果用列表替换元组,应该如何操作呢?

请你先自己思考这个问题,下节课我们会揭晓答案~

想要获取课程资料,和更多同学一起交流学习,欢迎添加班主任老师微信,我们下节课不见不散哦。

扫描二维码添加班主任微信

已经添加班主任的同学无需重复添加,直接联系对应老师即可。

判断第几天 1/3

判断第几天(1)

1.0x

恭喜完成本课时的学习!
坚持学习

行动力超过

累计学习

学习下一课时