影刀RPA Excel日期函数详解:天数与工作日计算
影刀RPA Excel日期函数详解天数与工作日计算作者林焱什么情况用什么计算合同到期天数、统计本月工作日数量、算两个日期之间隔了多少天、推算N个工作日后的日期——这些日期计算在Excel里用DATEDIF、NETWORKDAYS、WORKDAY等函数但在影刀RPA自动化流程中用Python的datetime模块更精确、更灵活还能处理节假日。适用场景合同到期提醒、项目工期计算、考勤天数统计、付款日期推算、报表时间范围筛选。怎么做基础日期计算fromdatetimeimportdatetime,timedelta# 当前日期todaydatetime.now().date()# 或在影刀中用【设置变量】获取当前日期# 日期加减天数future_datetodaytimedelta(days30)# 30天后past_datetoday-timedelta(days7)# 7天前# 计算两个日期间隔天数date1datetime(2026,7,1).date()date2datetime(2026,12,31).date()diff_days(date2-date1).days# 结果183[video(video-o1bFon0g-1783501765240)(type-csdn)(url-https://live.csdn.net/v/embed/525000)(image-https://v-blog.csdnimg.cn/asset/23da3fe1f67a47106d725406cfde9a97/cover/Cover0.jpg)(title-拼多多店群自动化上架方案)]# 推算月底fromdatetimeimportcalendarimportcalendarascaldefget_month_end(year,month):获取某月最后一天_,last_daycal.monthrange(year,month)returndatetime(year,month,last_day).date()month_endget_month_end(2026,7)# 2026-07-31工作日计算importnumpyasnpdefcount_workdays(start_date,end_date,holidaysNone):计算两个日期之间的工作日数排除周末和节假日ifholidaysisNone:holidays[]# 生成日期范围date_rangepd.date_range(start_date,end_date,freqD)# 排除周末周六5, 周日6workdays[dfordindate_rangeifd.weekday()5]# 排除节假日holiday_setset(pd.to_datetime(holidays).date)workdays[dfordinworkdaysifd.date()notinholiday_set]returnlen(workdays)defadd_workdays(start_date,days,holidaysNone):从起始日期推算N个工作日后的日期ifholidaysisNone:holidays[]holiday_setset(pd.to_datetime(holidays).date)currentpd.to_datetime(start_date).date()added0whileaddeddays:currenttimedelta(days1)# 跳过周末ifcurrent.weekday()5andcurrentnotinholiday_set:added1returncurrent# 2026年节假日列表需手动维护holidays_2026[2026-01-01,2026-02-16,2026-02-17,2026-02-18,# 元旦、春节2026-04-04,2026-04-05,2026-04-06,# 清明2026-05-01,2026-05-02,2026-05-03,# 劳动节2026-06-19,2026-06-20,2026-06-21,# 端午2026-09-25,2026-09-26,2026-09-27,# 中秋2026-10-01,2026-10-02,2026-10-03,# 国庆2026-10-04,2026-10-05,2026-10-06,2026-10-07,]# 计算7月工作日数workdays_julycount_workdays(2026-07-01,2026-07-31,holidays_2026)print(f7月工作日数{workdays_july}天)# 推算5个工作日后的日期deadlineadd_workdays(2026-07-01,5,holidays_2026)print(f5个工作日后{deadline})合同到期提醒importpandasaspddefcontract_expiry_check(file_path,output_path,warning_days30):合同到期检查dfpd.read_excel(file_path)todaydatetime.now().date()df[到期日期]pd.to_datetime(df[到期日期]).dt.date df[剩余天数]df[到期日期].apply(lambdax:(x-today).days)df[状态]df[剩余天数].apply(lambdad:已过期ifd0else紧急ifd7else预警ifdwarning_dayselse正常)# 筛选需要提醒的warningdf[df[状态].isin([已过期,紧急,预警])]warningwarning.sort_values(剩余天数)warning.to_excel(output_path,indexFalse)returnwarning# 在影刀中调用resultcontract_expiry_check(rC:\Data\contracts.xlsx,rC:\Data\contract_warning.xlsx,warning_days30)月度报表日期范围defget_report_date_range(report_monthNone):获取报表日期范围todaydatetime.now().date()ifreport_monthisNone:# 默认上个月iftoday.month1:year,monthtoday.year-1,12else:year,monthtoday.year,today.month-1else:year,monthreport_month# 月初startdatetime(year,month,1).date()# 月末_,last_daycal.monthrange(year,month)enddatetime(year,month,last_day).date()returnstart,end start,endget_report_date_range()print(f报表范围{start}至{end})写入Excel日期公式如果需要在Excel中保留可计算的日期公式importopenpyxl wbopenpyxl.load_workbook(rC:\Data\contracts.xlsx)wswb.activeforrowinrange(2,ws.max_row1):# 计算到期天数Excel公式ws.cell(rowrow,column5).valuefD{row}-TODAY()# 计算工作日数ws.cell(rowrow,column6).valuefNETWORKDAYS(TODAY(),D{row})# 计算月份ws.cell(rowrow,column7).valuefTEXT(D{row},yyyy-mm)wb.save(rC:\Data\contracts.xlsx)有什么坑坑1pandas日期解析格式不一致同一列日期有2026-07-01和2026/7/1和2026年7月1日混合格式pd.to_datetime可能解析错误# 问题混合格式导致解析错误df[日期]pd.to_datetime(df[日期])# 部分行可能NaT# 解决指定format或用errors参数df[日期]pd.to_datetime(df[日期],errorscoerce)# 解析失败的变NaT# 然后处理NaTdfdf.dropna(subset[日期])# 或者指定格式df[日期]pd.to_datetime(df[日期],format%Y-%m-%d,errorscoerce)df[日期].fillna(pd.to_datetime(df[日期],format%Y/%m/%d,errorscoerce),inplaceTrue)坑2Excel日期序列号问题openpyxl读取Excel日期有时返回数字Excel日期序列号而非datetime# 问题读出来是44213.0而不是2026-07-01fromopenpyxl.utils.datetimeimportfrom_excel valuews[A1].valueifisinstance(value,(int,float)):# 是Excel日期序列号需要转换[video(video-wrrGdTcC-1783501771965)(type-csdn)(url-https://live.csdn.net/v/embed/524993)(image-https://v-blog.csdnimg.cn/asset/a547123d88ad712dccba346c9217e237/cover/Cover0.jpg)(title-TEMU店群如何管理运营)]real_datefrom_excel(value)elifisinstance(value,datetime):real_datevalue.date()坑3跨年计算错误计算上个月时1月的上个月是去年12月直接减1会变成0月# 问题月份减1变成0todaydatetime(2026,1,15)last_monthtoday.month-1# 0错误# 解决用replace或relativedeltafromdateutil.relativedeltaimportrelativedelta last_month_datetoday-relativedelta(months1)# 2025-12-15正确# 或者手动处理iftoday.month1:year,monthtoday.year-1,12else:year,monthtoday.year,today.month-1坑4时区差异导致日期偏移datetime.now()有时返回前一天因为时区不是东八区# 问题服务器时区是UTCdatetime.now()比北京时间晚8小时fromdatetimeimporttimezone,timedelta# 解决指定东八区tz_beijingtimezone(timedelta(hours8))now_beijingdatetime.now(tz_beijing)todaynow_beijing.date()# 或者直接用时间戳计算importtime todaydatetime.fromtimestamp(time.time(),tztz_beijing).date()坑5闰年2月29日处理# 问题非闰年没有2月29日datetime(2025,2,29)# ValueError!# 安全创建日期defsafe_date(year,month,day):try:returndatetime(year,month,day).date()exceptValueError:# 如果是2月29日且非闰年取2月28日ifmonth2andday29:returndatetime(year,2,28).date()raise# 推算一年后的同一天defadd_one_year(date):try:returndate.replace(yeardate.year1)exceptValueError:# 2月29日 → 非闰年取2月28日returndate.replace(yeardate.year1,day28)