洛谷题单2-P5716 【深基3.例9】月份天数-python-流程图重构

部署运行你感兴趣的模型镜像

题目描述

输入年份和月份,输出这一年的这一月有多少天。需要考虑闰年。

输入格式

输入两个正整数,分别表示年份 yyy 和月数 mmm,以空格隔开。

输出格式

输出一行一个正整数,表示这个月有多少天。

输入输出样例

输入

1926 8

输出

31

说明/提示

数据保证 1583≤y≤20201583 \leq y \leq 20201583y20201≤m≤121 \leq m \leq 121m12

方式-先判断是不是闰年

代码

class Solution:
    @staticmethod
    def oi_input():
        """从标准输入读取数据"""
        y, m = map(int, input().split())
        return y, m

    @staticmethod
    def oi_test():
        """提供测试数据"""
        return 1926, 8

    @staticmethod
    def solution(y, m):
        is_leap_year = True if y % 400 == 0 or y % 4 == 0 and y % 100 != 0 else False

        if m == 2:
            if is_leap_year:
                print(29)
            else:
                print(28)
        elif m in [1, 3, 5, 7, 8, 10, 12]:
            print(31)
        else:
            print(30)


oi_input = Solution.oi_input
oi_test = Solution.oi_test
solution = Solution.solution

if __name__ == '__main__':
    y, m = oi_test()
    # y, m = oi_input()
    solution(y, m)

流程图

月份处理
m == 2?
闰年判断
是闰年?
输出29天
输出28天
m是否在
[1,3,5,7,8,10,12]
输出31天
输出30天
开始
主函数调用
获取输入数据
y, m = map(int, input().split())
结束

方式-内置模块的函数

代码

class Solution:
    @staticmethod
    def oi_input():
        """从标准输入读取数据"""
        y, m = map(int, input().split())
        return y, m

    @staticmethod
    def oi_test():
        """提供测试数据"""
        return 1926, 8

    @staticmethod
    def solution(y, m):
        '''calendar.monthrange 函数 返回元组 (该月第一天的星期, 该月天数)'''
        import calendar

        print(calendar.monthrange(y, m)[1])


oi_input = Solution.oi_input
oi_test = Solution.oi_test
solution = Solution.solution

if __name__ == '__main__':
    y, m = oi_test()
    # y, m = oi_input()
    solution(y, m)

流程图

开始
主函数调用
获取输入数据
y, m =
map(int, input().split())
导入calendar模块
调用库函数
calendar.monthrange(y, m)
提取元组第2元素
[1]索引操作
打印输出天数
print(result)
结束

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think> 我们遇到的问是:ValueError: time data &#39;2024/1/5&#39; does not match format &#39;%Y-%m-%d&#39; 原因分析:格式字符串(format string)与输入的日期字符串不匹配。 具体来说: - 格式字符串指定的是:%Y-%m-%d,即四位年份-两位月份-两位日期(如:2024-01-05) - 而实际传入的日期字符串是:&#39;2024/1/5&#39;,使用斜杠作为分隔符,且月份和日期为一位数(没有前导零) 解决方案: 方案1:修改格式字符串以匹配输入字符串 将格式字符串改为:&#39;%Y/%m/%d&#39;,但注意这个格式要求月份和日期是两位数(如05而不是5),而输入中月份和日期是一位数(1和5),所以这样改仍然会报错。 方案2:将输入字符串的格式调整为与格式字符串一致 将&#39;2024/1/5&#39;改为&#39;2024-01-05&#39;(即用短横线连接,并补零) 方案3:使用更灵活的解析方法(推荐) 使用pandas的to_datetime函数,它可以自动推断格式,或者使用errors=&#39;coerce&#39;参数使得解析错误时返回NaT,避免程序中断。 根据引用[2]:在to_datetime函数中使用errors=&#39;coerce&#39;可以避免错误,并且能够处理多种格式。 因此,我们修改代码,不再使用datetime.strptime,而是使用pd.to_datetime来解析日期字符串。 针对原代码中函数d_to_jd的修改思路: 原函数: def d_to_jd(time): fmt = &#39;%Y/%m/%d&#39; dt = datetime.strptime(time, fmt) tt = dt.timetuple() return tt.tm_yday 问:这个函数要求输入的字符串必须是&#39;2024/01/05&#39;(两位数月份和日期)格式,但实际传入的字符串可能是&#39;2024/1/5&#39;(一位数)或者是其他格式。 修改方案: 我们可以先使用pd.to_datetime将字符串转换为datetime对象,然后再提取年中的第几天。 重新设计d_to_jd函数: def d_to_jd(time_str): # 使用pd.to_datetime转换,errors=&#39;coerce&#39;会将解析失败的值转为NaT dt = pd.to_datetime(time_str, errors=&#39;coerce&#39;) if pd.isna(dt): return np.nan # 或者根据需求处理 return dt.timetuple().tm_yday 但是,注意原代码中传入d_to_jd的字符串是从datetime对象转换回字符串的?实际上,在原来的pol函数中: years = [datetime.strptime(d,&#39;%Y/%m/%d&#39;).date() for d in date] # 这一行已经会报错,因为date中的字符串格式不一定是&#39;%Y/%m/%d&#39; ... s = list(map(str, years)) # 将datetime.date对象转换为字符串,默认格式为&#39;YYYY-MM-DD&#39; s = list(map(d_to_jd, s)) # 再调用d_to_jd 这里存在两个问: 1. 第一行解析date中的字符串时,格式可能不匹配(因为原始数据可能是&#39;2024/1/5&#39;这样的格式,而这里用了&#39;%Y/%m/%d&#39;,要求两位数) 2. 然后又将解析后的日期对象转为字符串(默认格式为ISO格式,即&#39;YYYY-MM-DD&#39;),再传入d_to_jd,而d_to_jd函数中却要求&#39;%Y/%m/%d&#39;格式(斜杠分隔,且两位数),所以会报错。 因此,我们需要重构整个日期处理流程: 重构步骤: 1. 读取数据时,将日期列直接解析为datetime对象,使用pd.to_datetime(并指定错误处理为&#39;coerce&#39;)。 2. 使用解析后的datetime对象进行后续操作。 具体修改: 原始代码: date = data.iloc[0:38764, 2:3].values.flatten() gcc = data.iloc[0:38764, 3:4].values.flatten() def pol(date, gcc): years = [datetime.strptime(d,&#39;%Y/%m/%d&#39;).date() for d in date] # 这里可能出错 ... 修改后: # 读取数据 data = pd.read_csv(&#39;C:/Users/admin/Desktop/sample_get.csv&#39;) # 将日期列转换为datetime对象 date_col = data.iloc[0:38764, 2] # 假设第2列是日期字符串 # 使用pd.to_datetime转换,注意这里我们使用errors=&#39;coerce&#39;,并将原始字符串传入 dates = pd.to_datetime(date_col, errors=&#39;coerce&#39;) # 检查是否有转换失败的日期 if dates.isna().any(): # 可以选择打印警告或者处理缺失值 print("警告:存在无法解析的日期,将被删除或处理") # 如,删除缺失值,同时对应的gcc值也要删除 valid_indices = ~dates.isna() dates = dates[valid_indices] gcc = data.iloc[0:38764, 3][valid_indices].values else: gcc = data.iloc[0:38764, 3].values # 修改pol函数,使其接受datetime对象列表(或pd.Series)和gcc数组 def pol(dates, gcc): # 将dates转换为matplotlib可以识别的日期格式(实际上,matplotlib可以直接处理datetime对象) # 不需要再转换为字符串再解析,我们已经有datetime对象了 # 计算一年中的第几天(年积日) # 注意:这里我们直接通过datetime对象的timetuple()方法获取 s = np.array([d.timetuple().tm_yday for d in dates]) # d是datetime对象 # 但是,如果我们的数据跨越多个年份,那么年积日将会重复(比如每年都有第1天),所以我们不能直接用年积日。 # 原代码中似乎没有考虑多年度数据?因为只用了年积日,这会导致不同年份的同一天被当作同一个数值。 # 所以,我们实际上需要的是从某个起始日期开始的天数,或者使用年份+年积日? # 原多项式拟合使用的是年积日,但这样对于多年度数据是不合适的。这里我们按照原代码的思路(只使用年积日)进行,但请注意其局限性。 # 由于原代码使用年积日,我们也这样处理,但是注意:如果有多年的数据,那么拟合会忽略年份差异,将不同年份的同一天视为同一点。 # 所以,这里我们假设数据都是同一年份的?或者用户希望忽略年份,只关注年内变化? # 根据用户需求,如果数据是多年的,我们可能需要调整。但原代码没有处理,所以我们先按照原方法。 _x = s # 年积日数组 gcc = np.array(gcc) # 多项式拟合(6次) o = np.polyfit(_x, gcc, 6) g = np.poly1d(o) # 绘图 plt.figure(figsize=(12,6)) # 将日期对象作为横坐标 plt.gca().xaxis.set_major_formatter(mdates.DateFormatter(&#39;%Y/%m/%d&#39;)) plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=30)) # 每隔30天一个刻度 # 由于日期数据可能不是连续的,我们按日期排序,但原数据可能是按日期排序的,所以假设已经排序 plt.plot(dates, g(_x), c=&#39;g&#39;, ls=&#39;-&#39;, label=&#39;拟合曲线&#39;) plt.plot(dates, gcc, c=&#39;r&#39;, ls=&#39;-&#39;, marker=&#39;o&#39;, markersize=2, alpha=0.3, label=&#39;原始数据&#39;) plt.legend() plt.gcf().autofmt_xdate() # 自动旋转日期标记 plt.show() # 调用 result = pol(dates, gcc) 但是,原代码中还有一个函数jd_to_time,在重构中没有用到,如果其他地方不需要,可以忽略。 注意:如果数据跨越多个年份,使用年积日(tm_yday)进行多项式拟合会将不同年份的同一天视为同一点,这通常不是我们想要的。因此,更常见的做法是将日期转换为从某个固定起点(如第一天)开始的天数。 修正:为了支持多年度数据,我们应该使用总天数如从数据的最小日期开始的天数)或者使用年份+小数部分(如年积日/365.25)?但这里我们遵循原代码需求(只使用年积日)可能导致问。如果用户的数据有多年的,我们需要改变策略。 另一种方案:在多项式拟合时,使用一个包含年份和年积日的变量,但这需要多元多项式拟合,比较复杂。或者将日期转换为一个连续数值(如儒略日)。 在当前重构中,我们先按照原代码思路(只使用年积日)进行,但需要明确告知用户这个局限性。 总结修改后的代码步骤: 1. 使用pd.to_datetime解析日期列,处理多种格式和缺失值。 2. 删除或处理解析失败的日期,并同步处理对应的gcc值。 3. 在pol函数中,直接从datetime对象计算年积日(tm_yday)。 4. 进行多项式拟合和绘图。 我们修改后的代码: ```python import pandas as pd import numpy as np from datetime import datetime import matplotlib.pyplot as plt import matplotlib.dates as mdates # 不再需要d_to_jd函数(因为使用pd.to_datetime解析,并在pol函数内直接计算年积日) # 但是jd_to_time函数保留(如果其他地方需要) def jd_to_time(time): # 注意:这个函数输入的是字符串,格式为&#39;%Y%j&#39;(年份+年积日),如&#39;2024001&#39;表示2024年第1天 dt = datetime.strptime(time, &#39;%Y%j&#39;).date() fmt = &#39;%Y/%m/%d&#39; return dt.strftime(fmt) # 读取数据 data = pd.read_csv(&#39;C:/Users/admin/Desktop/sample_get.csv&#39;) # 提取日期列(第三列)和gcc列(第四列) # 注意:iloc的列索引是位置索引,从0开始,所以第三列索引为2,第四列索引为3 date_col = data.iloc[0:38764, 2] # 第三列,假设是日期字符串 gcc_col = data.iloc[0:38764, 3] # 第四列 # 将日期字符串转换为datetime对象 dates = pd.to_datetime(date_col, errors=&#39;coerce&#39;) # 检查是否有转换失败的日期 if dates.isna().any(): print("警告:存在无法解析的日期,将删除这些行") # 创建有效索引(非空) valid_mask = ~dates.isna() dates = dates[valid_mask] gcc_values = gcc_col[valid_mask].values.astype(float) # 确保gcc是浮点型 else: gcc_values = gcc_col.values.astype(float) # 删除gcc中的NaN(如果有的话) # 假设gcc列也可能有缺失值,我们用np.nan表示,然后同时删除日期和gcc都为缺失的行?但实际上日期已经处理过,这里只处理gcc的缺失 # 注意:原始gcc_col可能包含非数值,所以用astype(float)转换,转换失败会变成NaN nan_mask_gcc = np.isnan(gcc_values) if nan_mask_gcc.any(): print("警告:gcc列存在缺失值,将删除这些行") # 同时删除日期和gcc中的缺失值(这里gcc缺失对应的日期也要删除) valid_mask = ~nan_mask_gcc dates = dates[valid_mask] gcc_values = gcc_values[valid_mask] # 定义pol函数 def pol(dates, gcc): # 将datetime64[ns]序列转换为datetime对象的列表(如果需要,但实际上pd.Series也可以直接用于timetuple?) # 计算年积日(一年中的第几天) # 注意:dates是pd.Series,每个元素是Timestamp,可以调用to_pydatetime()转换为datetime对象,但Timestamp也有timetuple方法 # 所以可以直接:d.timetuple().tm_yday s = np.array([d.timetuple().tm_yday for d in dates]) # 多项式拟合 o = np.polyfit(s, gcc, 6) # 6次多项式拟合 g = np.poly1d(o) # 创建图形 fig, ax = plt.subplots(figsize=(12,6)) # 设置x轴为日期格式 ax.xaxis.set_major_formatter(mdates.DateFormatter(&#39;%Y/%m/%d&#39;)) ax.xaxis.set_major_locator(mdates.DayLocator(interval=30)) # 每30天一个主刻度 # 绘制拟合曲线和原始数据 ax.plot(dates, g(s), c=&#39;g&#39;, ls=&#39;-&#39;, label=&#39;拟合曲线&#39;) ax.plot(dates, gcc, c=&#39;r&#39;, ls=&#39;-&#39;, marker=&#39;o&#39;, markersize=2, alpha=0.3, label=&#39;原始数据&#39;) ax.legend() fig.autofmt_xdate() # 自动旋转日期标签 plt.show() # 调用函数 pol(dates, gcc_values) ``` 注意:如果数据包含多个年份,使用年积日(s)作为自变量进行多项式拟合,会忽略年份信息,即所有年份的第1天都被视为同一天。这可能导致拟合曲线在跨年时出现跳跃(因为下一年的第一天又回到了起点附近)。如果数据包含多个年份,建议使用总天数如从数据的最小日期开始计算天数)作为自变量。 如果有多个年份的数据,我们可以这样修改: start_date = dates.min() s = (dates - start_date).dt.days # 转换为从开始日期的天数 这样,横坐标就是连续的整数。 如果用户希望使用总天数,则修改pol函数中s的计算方式: start_date = min(dates) # 注意dates是pd.Series,可以直接取最小值 s = (dates - start_date).dt.days.values # 转换为天数差(整数) 然后进行多项式拟合。 考虑到原代码意图,我们保留使用年积日的做法,但用户可以根据需要自行修改。 最后,关于FutureWarning:我们可以按照提示注册转换器,在代码开头添加: from pandas.plotting import register_matplotlib_converters register_matplotlib_converters() 这可以避免警告。 完整代码整合: ```python import pandas as pd import numpy as np from datetime import datetime import matplotlib.pyplot as plt import matplotlib.dates as mdates from pandas.plotting import register_matplotlib_converters # 注册matplotlib的日期转换器,避免警告 register_matplotlib_converters() def jd_to_time(time): # 这个函数用于将年份+年积日的字符串转换为日期字符串(原功能保留) dt = datetime.strptime(time, &#39;%Y%j&#39;).date() fmt = &#39;%Y/%m/%d&#39; return dt.strftime(fmt) # 读取数据 data = pd.read_csv(&#39;C:/Users/admin/Desktop/sample_get.csv&#39;) # 提取需要的部分 date_col = data.iloc[0:38764, 2] # 第三列,日期 gcc_col = data.iloc[0:38764, 3] # 第四列,gcc # 转换日期 dates = pd.to_datetime(date_col, errors=&#39;coerce&#39;) # 处理缺失的日期 valid_mask_dates = ~dates.isna() dates = dates[valid_mask_dates] gcc_values = gcc_col[valid_mask_dates].values # 转换gcc为浮点数,并处理可能的缺失(非数字字符串) try: gcc_values = gcc_values.astype(float) except: # 如果转换失败,说明有非数字,我们将非数字转换为NaN gcc_values = pd.to_numeric(gcc_values, errors=&#39;coerce&#39;) # 再次检查NaN valid_mask_gcc = ~np.isnan(gcc_values) dates = dates[valid_mask_gcc] gcc_values = gcc_values[valid_mask_gcc] # 定义pol函数 def pol(dates, gcc): # 计算年积日(一年中的第几天) s = np.array([d.timetuple().tm_yday for d in dates]) # 使用年积日进行多项式拟合 o = np.polyfit(s, gcc, 6) g = np.poly1d(o) # 创建图形 fig, ax = plt.subplots(figsize=(12,6)) # 设置日期格式 ax.xaxis.set_major_formatter(mdates.DateFormatter(&#39;%Y/%m/%d&#39;)) ax.xaxis.set_major_locator(mdates.DayLocator(interval=30)) # 绘制 ax.plot(dates, g(s), &#39;g-&#39;, label=&#39;拟合曲线&#39;) ax.plot(dates, gcc, &#39;r-&#39;, marker=&#39;o&#39;, markersize=2, alpha=0.3, label=&#39;原始数据&#39;) ax.legend() fig.autofmt_xdate() plt.show() # 调用函数 pol(dates, gcc_values) ``` 注意:如果数据包含多个年份,建议使用总天数(连续变量)作为自变量,修改pol函数中s的计算方式(如上面所述)。 以上代码应该能够解决日期解析错误的问,并处理缺失值和无效值。 §§相关问§§ 1. 如何处理包含时间信息的日期字符串(如年月日时分秒)? 2. 多项式拟合的阶数如何选择?6阶多项式是否合理? 3. 如果数据包含多个年份,如何改进年积日的计算方法以避免跨年问? </think> ### 解决Python中datetime.strptime的ValueError错误 #### 问原因分析 当使用`datetime.strptime()`函数时出现`ValueError: time data &#39;2024/1/5&#39; does not match format &#39;%Y-%m-%d&#39;`错误,根本原因是**日期字符串格式与指定的格式字符串不匹配**[^1][^2]。具体表现为: 1. **分隔符不匹配**:格式字符串使用短横线`-`(`%Y-%m-%d`),而实际数据使用斜杠`/`(`2024/1/5`) 2. **位数不匹配**:格式字符串要求月份/日期为两位数(01),实际数据是一位数(1) 3. **格式规范不一致**:Python的日期格式标识符区分大小写(如`%m` vs `%M`)[^1] --- ### 解决方案 #### 方法1:修改格式字符串(推荐) ```python # 原错误代码 datetime.strptime(&#39;2024/1/5&#39;, &#39;%Y-%m-%d&#39;) # ValueError # 正确格式(匹配斜杠和1位日期) datetime.strptime(&#39;2024/1/5&#39;, &#39;%Y/%m/%d&#39;) # ✅ 成功解析 ``` - **关键修改**:`%Y/%m/%d` → 匹配`年/月/日`格式 - **注意事项**: - `%m` 允许解析1位或2月份(自动补零) - 使用 `/` 而非 `-` 匹配实际数据格式 - 格式字符串必须与输入数据**完全一致**(包括分隔符)[^1] #### 方法2:使用pd.to_datetime自动解析 ```python import pandas as pd # 自动推断日期格式(推荐) date_str = &#39;2024/1/5&#39; dt = pd.to_datetime(date_str) # 自动转换为Timestamp # 带错误处理(无效日期返回NaT) dt = pd.to_datetime(date_str, errors=&#39;coerce&#39;) # ✅ 安全解析[^2] ``` #### 方法3:统一预处理日期格式 ```python def normalize_date(date_str): """标准化日期格式:YYYY/MM/DD → YYYY-MM-DD""" parts = date_str.split(&#39;/&#39;) return f"{parts[0]}-{int(parts[1]):02d}-{int(parts[2]):02d}" # 使用示 normalized = normalize_date(&#39;2024/1/5&#39;) # &#39;2024-01-05&#39; datetime.strptime(normalized, &#39;%Y-%m-%d&#39;) # ✅ 成功解析 ``` --- ### 完整代码修复方案 ```python import pandas as pd from datetime import datetime # 修复后的d_to_jd函数 def d_to_jd(time): try: # 尝试多种格式兼容解析 dt = pd.to_datetime(time, errors=&#39;coerce&#39;) return dt.timetuple().tm_yday except: return None # 错误处理 # 在pol函数中应用 def pol(date, gcc): # 直接使用pd.to_datetime解析日期 dates = pd.to_datetime(date, errors=&#39;coerce&#39;) valid_mask = ~dates.isna() # 计算年积日 s = np.array([d.timetuple().tm_yday for d in dates[valid_mask]]) gcc = gcc[valid_mask] # 同步筛选有效数据 # ...后续多项式拟合代码不变... ``` --- ### 关键修复原理 1. **格式兼容性**:使用 `%Y/%m/%d` 匹配输入数据的 `2024/1/5` 格式 2. **错误处理**:`errors=&#39;coerce&#39;` 将无效日期转为`NaT`避免崩溃[^2] 3. **自动类型转换**:`pd.to_datetime()` 可智能处理: - 多种分隔符(`/`, `-`, `.`等) - 1位/2月份日期 - 跨年日期识别 $$ \text{日期字符串} \xrightarrow{\text{pd.to_datetime}} \text{datetime对象} $$ 4. **数据清洗**:通过`valid_mask`过滤无效日期,保证拟合数据质量 > **数学表达**:日期解析本质是字符串模式匹配 > 设输入字符串 $S$,格式模式 $P$,则解析函数 $f(S,P)$ 满足: > $$ \forall S \in \text{有效日期}, \exists P \text{ 使 } f(S,P) = \text{datetime对象} $$ > 当 $P \not\equiv S$ 时触发 `ValueError`[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值