影刀RPA 时间日期处理:定时任务与日期计算完全攻略
影刀RPA 时间日期处理定时任务与日期计算完全攻略作者林焱什么情况用RPA流程几乎离不开时间处理每天凌晨2点自动执行、只处理最近7天的数据、计算两个日期之间的工作日天数、将「3天前」「上周五」这种自然语言转成具体日期。影刀内置了「定时运行」和「等待」节点但遇到复杂的日期计算——比如「本月第三个工作日」、「排除节假日的截止日期」——就需要Python的datetime模块出手。核心场景流程中涉及日期计算、定时调度、工作日统计等。怎么做拼多多店群自动化上架方案第一步datetime模块速查fromdatetimeimportdatetime,date,timedeltaimportcalendar# 获取当前时间 nowdatetime.now()# 2024-06-26 14:30:00.123456todaydate.today()# 2024-06-26# 创建指定日期 ddatetime(2024,6,26,14,30,0)ddatetime.strptime(2024-06-26,%Y-%m-%d)# 格式化输出 print(now.strftime(%Y-%m-%d %H:%M:%S))# 2024-06-26 14:30:00print(now.strftime(%Y年%m月%d日))# 2024年06月26日print(now.strftime(%A))# Wednesday星期几# 日期加减 yesterdaytoday-timedelta(days1)next_weektodaytimedelta(days7)one_hour_agonow-timedelta(hours1)three_months_latertodaytimedelta(days90)# 粗略用90天代替3个月# 日期差 diffdatetime(2024,12,31)-datetime(2024,1,1)print(f相差{diff.days}天)# 相差 365 天第二步常用日期计算函数库classDateUtils:RPA常用日期工具staticmethoddefget_this_week_range():获取本周一和周日的日期todaydate.today()mondaytoday-timedelta(daystoday.weekday())sundaymondaytimedelta(days6)returnmonday,sundaystaticmethoddefget_this_month_range():获取本月第一天和最后一天todaydate.today()first_daytoday.replace(day1)last_daytoday.replace(daycalendar.monthrange(today.year,today.month)[1])returnfirst_day,last_daystaticmethoddefget_last_month_range():获取上月第一天和最后一天todaydate.today()# 上月最后一天 本月第一天 - 1天first_of_this_monthtoday.replace(day1)last_of_last_monthfirst_of_this_month-timedelta(days1)first_of_last_monthlast_of_last_month.replace(day1)returnfirst_of_last_month,last_of_last_monthstaticmethoddefget_quarter_range():获取本季度第一天和最后一天todaydate.today()quarter_month((today.month-1)//3)*31first_daytoday.replace(monthquarter_month,day1)last_monthquarter_month2last_daytoday.replace(monthlast_month,daycalendar.monthrange(today.year,last_month)[1])returnfirst_day,last_daystaticmethoddefis_weekend(d):判断是否是周末returnd.weekday()5staticmethoddefadd_workdays(start_date,days):增加N个工作日跳过周末currentstart_date added0whileaddeddays:currenttimedelta(days1)ifcurrent.weekday()5:# 周一到周五added1returncurrentstaticmethoddefcount_workdays(start_date,end_date):计算两个日期之间的工作日天数days0currentstart_datewhilecurrentend_date:ifcurrent.weekday()5:days1currenttimedelta(days1)returndaysstaticmethoddefget_recent_days(num_days):获取最近N天的日期列表todaydate.today()return[(today-timedelta(daysi)).strftime(%Y-%m-%d)foriinrange(num_days)]staticmethoddefparse_relative_date(text): 解析相对日期表达 今天 → 今天日期 昨天 → 昨天日期 3天前 → 3天前的日期 上周一 → 上周一日期 todaydate.today()texttext.strip()iftextin(今天,今日):returntodayiftextin(昨天,昨日):returntoday-timedelta(days1)iftextin(前天,):returntoday-timedelta(days2)iftextin(明天,明日):returntodaytimedelta(days1)importre# N天前 / N天后matchre.match(r(\d)\s*天[前后],text)ifmatch:nint(match.group(1))if后intext:returntodaytimedelta(daysn)else:returntoday-timedelta(daysn)# 上周Xweekdays{一:0,二:1,三:2,四:3,五:4,六:5,日:6}matchre.match(r上周([一二三四五六日]),text)ifmatch:targetweekdays[match.group(1)]days_since_mondaytoday.weekday()last_mondaytoday-timedelta(daysdays_since_monday7)returnlast_mondaytimedelta(daystarget)returnNone# 测试duDateUtils()print(f本周{du.get_this_week_range()})print(f本月{du.get_this_month_range()})print(f10个工作日后{du.add_workdays(date.today(),10)})print(f本月工作日{du.count_workdays(*du.get_this_month_range())})print(f「3天前」{du.parse_relative_date(3天前)})print(f「上周五」{du.parse_relative_date(上周五)})第三步影刀定时任务的最佳实践影刀支持cron定时但有几个常见需求需要自定义importschedule# pip install scheduleimporttimeclassTaskScheduler:自定义定时任务调度器def__init__(self):self.tasks[]defrun_at(self,time_str,task_func,*args):每天在指定时间运行schedule.every().day.at(time_str).do(task_func,*args)defrun_every_n_minutes(self,minutes,task_func,*args):每N分钟运行schedule.every(minutes).minutes.do(task_func,*args)defrun_at_weekday(self,weekday,time_str,task_func,*args):每周某天某时运行day_map{monday:schedule.every().monday,tuesday:schedule.every().tuesday,wednesday:schedule.every().wednesday,thursday:schedule.every().thursday,friday:schedule.every().friday,saturday:schedule.every().saturday,sunday:schedule.every().sunday}day_map[weekday.lower()].at(time_str).do(task_func,*args)defrun_on_month_day(self,day,time_str,task_func,*args):每月某天某时运行如每月1号凌晨生成报表# schedule库不直接支持「每月第N天」# 变通方案每天检查是否是目标日期defwrapper():ifdatetime.now().dayday:task_func(*args)schedule.every().day.at(time_str).do(wrapper)defstart(self):开始调度循环print(定时调度器已启动...)whileTrue:schedule.run_pending()time.sleep(30)# 每30秒检查一次# 示例——生成报表的调度# scheduler TaskScheduler()# scheduler.run_at(08:00, generate_daily_report) # 每天8点生成日报# scheduler.run_at_weekday(monday, 09:00, generate_weekly_report) # 每周一9点生成周报# scheduler.run_on_month_day(1, 08:00, generate_monthly_report) # 每月1号8点生成月报# scheduler.start()第四步超时控制——别让流程无限等待importthreadingdefrun_with_timeout(func,timeout_seconds,*args,**kwargs): 给函数调用加超时限制 超时后抛出 TimeoutError result[None]exception[None]deftarget():try:result[0]func(*args,**kwargs)exceptExceptionase:exception[0]e threadthreading.Thread(targettarget)thread.daemonTruethread.start()thread.join(timeouttimeout_seconds)ifthread.is_alive():raiseTimeoutError(f操作超时{timeout_seconds}秒)ifexception[0]:raiseexception[0]returnresult[0]# 使用try:datarun_with_timeout(fetch_large_dataset,120,urlhttps://api.example.com)print(f获取到{len(data)}条数据)exceptTimeoutError:print(数据获取超时跳过本次处理)第五步生成时间戳文件名defgenerate_timestamp_filename(prefixreport,extxlsx):生成带时间戳的文件名防止覆盖timestampdatetime.now().strftime(%Y%m%d_%H%M%S)returnf{prefix}_{timestamp}.{ext}# report_20240626_143000.xlsx# 唯一的文件名 → 多次运行不会互相覆盖另外要注意strftime里的%f微秒非常有用高频率运行时避免同名冲突。有什么坑坑1时区——datetime.now()不一定是北京时间如果你的服务器时区设置不对datetime.now()返回的可能不是北京时间。凌晨2点触发的任务可能下午才跑。解决方法TEMU店群如何管理运营fromdatetimeimporttimezone,timedelta# 明确使用北京时间beijing_tztimezone(timedelta(hours8))beijing_nowdatetime.now(beijing_tz)坑2月份加减的天数陷阱timedelta(days30)不等于「一个月后」。1月31日 30天 3月2日但你可能期望是2月28日。fromdateutil.relativedeltaimportrelativedelta# pip install python-dateutil# ✅ 正确的月份加减next_monthdatetime(2024,1,31)relativedelta(months1)print(next_month)# 2024-02-29 —— 自动处理月末three_months_agodatetime.now()-relativedelta(months3)坑3strftime不支持中文# ❌ 不能直接在strftime里写中文# now.strftime(%Y年%m月%d日) # 这个可以因为中文在格式字符串里# now.strftime(星期%A) # 这个不行%A输出的是英文星期几# ✅ 用字典映射WEEKDAY_CN{0:周一,1:周二,2:周三,3:周四,4:周五,5:周六,6:周日}weekday_cnWEEKDAY_CN[datetime.now().weekday()]坑4定时任务的累积效应如果定时任务执行时间超过了间隔时间比如每5分钟运行一次但单次执行要8分钟任务会堆积。解决方法在执行前检查是否有上一次任务还在跑。总结RPA的时间处理远不止「定时运行」四个字。核心技能timedelta日期加减、relativedelta月份处理、工作日计算、自然语言日期解析、超时控制。把这些封装成工具函数随用随取别每次从零写。