如何基于DataFrame字段值为每行批量计算对应月份的指定日期?
实现方案
步骤1:建立星期字符串到calendar常量的映射
解决你遇到的字符串'SUNDAY'和calendar.SUNDAY不等价的问题,直接通过动态属性获取构建全量映射字典,无需硬编码每个星期的对应关系:
import calendar import pandas as pd import datetime # 自动构建星期字符串到calendar常量的映射,支持所有星期(MONDAY-SUNDAY) WEEKDAY_MAP = { attr: getattr(calendar, attr) for attr in dir(calendar) if attr.isupper() and isinstance(getattr(calendar, attr), int) and 0 <= getattr(calendar, attr) <= 6 }
步骤2:封装通用夏令时日期计算函数
支持任意月份、任意周序(第一周/最后一周/倒数第二周等)、任意星期的日期计算,比你现有的仅支持最后一个周日的逻辑更通用:
def calculate_dst_date(target_year: int, target_month: int, week_order: int, weekday_code: int) -> datetime.date: """ 计算指定年份的夏令时变更日期 :param target_year: 要计算的年份 :param target_month: 变更所在月份 :param week_order: 周序,1代表当月第一个符合要求的星期,-1代表最后一个,-2代表倒数第二个,以此类推 :param weekday_code: 星期对应的calendar常量,比如calendar.SUNDAY :return: 对应的日期对象 """ # 获取当月的日历矩阵,不存在的日期值为0 month_calendar = calendar.monthcalendar(target_year, target_month) # 提取所有符合星期要求的有效日期 valid_days = [ week[weekday_code] for week in month_calendar if week[weekday_code] != 0 ] # 按周序取对应日期 target_day = valid_days[week_order - 1] if week_order > 0 else valid_days[week_order] return datetime.date(target_year, target_month, target_day)
步骤3:批量计算所有城市的夏令时区间
假设你读取的CSV数据集包含以下列:城市名称city、夏令时开始月份dst_start_month、夏令时开始周序dst_start_week、夏令时开始星期dst_start_weekday、夏令时结束月份dst_end_month、夏令时结束周序dst_end_week、夏令时结束星期dst_end_weekday,通过pandas apply批量计算:
# 读取数据集 df = pd.read_csv("你的夏令时规则文件路径.csv") # 转换星期字符串为calendar常量 df['start_weekday_code'] = df['dst_start_weekday'].map(WEEKDAY_MAP) df['end_weekday_code'] = df['dst_end_weekday'].map(WEEKDAY_MAP) # 定义行级计算函数,批量生成对应年份的夏令时开始/结束日期 def calc_city_dst(row, target_year): start_date = calculate_dst_date(target_year, row['dst_start_month'], row['dst_start_week'], row['start_weekday_code']) end_date = calculate_dst_date(target_year, row['dst_end_month'], row['dst_end_week'], row['end_weekday_code']) return pd.Series([start_date, end_date]) # 计算当前年份的所有城市夏令时日期 current_year = datetime.date.today().year df[['dst_start_date', 'dst_end_date']] = df.apply(calc_city_dst, target_year=current_year, axis=1) # 可选:判断当日是否处于夏令时区间 today = datetime.date.today() df['is_dst_now'] = df.apply(lambda x: x['dst_start_date'] <= today <= x['dst_end_date'], axis=1)
方案优势
- 完全数据驱动,新增城市仅需在CSV中补充对应的规则行,无需修改代码
- 支持所有通用夏令时规则,包括第N个周X、倒数第N个周X的场景
- 可适配任意年份的计算,满足日常定时运行的需求
内容的提问来源于stack exchange,提问作者ariana20
相关产品推荐
相关产品推荐

