影刀RPA 时间日期的进阶操作时区、格式、计算作者林焱时间日期看起来简单实际用起来坑特别多时间戳和字符串互转搞不清、时区差异导致时间对不上、工作日计算忘了考虑节假日、文件名里的日期格式不统一。这篇文章把RPA里常见的时间日期操作整理成速查手册。一、什么情况用什么场景推荐方法说明获取当前时间datetime.now()最常用格式化时间显示strftime()自定义格式解析时间字符串strptime()字符串转时间对象时间戳转日期datetime.fromtimestamp()Unix时间戳转换日期加减timedelta前后N天计算工作日计算chinesecalendar考虑法定节假日文件名带日期strftime(“%Y%m%d”)20260615格式计算耗时两个时间相减性能监控时区转换pytz / zoneinfo跨时区场景二、怎么做2.1 获取当前时间店群矩阵自动化突破运营极限fromdatetimeimportdatetime,date,timedeltaimporttime# 当前日期时间nowdatetime.now()print(now)# 2026-07-01 18:35:18.123456# 当前日期不含时间todaydate.today()print(today)# 2026-07-01# 当前时间戳timestamptime.time()print(timestamp)# 1751364918.123456# 各部分单独获取print(f年:{now.year})# 2026print(f月:{now.month})# 7print(f日:{now.day})# 1print(f时:{now.hour})# 18print(f分:{now.minute})# 35print(f秒:{now.second})# 18print(f星期:{now.weekday()})# 0周一, 6周日2.2 格式化时间fromdatetimeimportdatetime nowdatetime.now()# 常用格式print(now.strftime(%Y-%m-%d))# 2026-07-01print(now.strftime(%Y/%m/%d))# 2026/07/01print(now.strftime(%Y%m%d))# 20260701适合文件名print(now.strftime(%H:%M:%S))# 18:35:18print(now.strftime(%Y-%m-%d %H:%M:%S))# 2026-07-01 18:35:18print(now.strftime(%Y年%m月%d日))# 2026年07月01日print(now.strftime(%Y%m%d_%H%M%S))# 20260701_183518适合文件名带时间# 格式化符号速查# %Y 年4位 %m 月01-12 %d 日01-31# %H 时24h %M 分00-59 %S 秒00-59# %y 年2位 %I 时12h %p AM/PM# %A 星期全名 %a 星期缩写 %B 月份全名 %b 月份缩写2.3 解析时间字符串fromdatetimeimportdatetime# 字符串 → 时间对象date_str2026-07-01 18:35:18dtdatetime.strptime(date_str,%Y-%m-%d %H:%M:%S)print(dt)# 2026-07-01 18:35:18# 只解析日期date_str2026/07/01dtdatetime.strptime(date_str,%Y/%m/%d)print(dt)# 2026-07-01 00:00:00# 解析各种格式formats[(2026-07-01,%Y-%m-%d),(2026/07/01,%Y/%m/%d),(01-07-2026,%d-%m-%Y),(20260701,%Y%m%d),(2026年7月1日,%Y年%m月%d日),]fordate_str,fmtinformats:try:dtdatetime.strptime(date_str,fmt)print(f{date_str} →{dt.strftime(%Y-%m-%d)})exceptValueErrorase:print(f{date_str} 解析失败:{e})2.4 时间戳转换fromdatetimeimportdatetimeimporttime# 当前时间戳timestamptime.time()print(f时间戳:{timestamp})# 1751364918.123# 时间戳 → 日期时间dtdatetime.fromtimestamp(timestamp)print(f日期时间:{dt})# 日期时间 → 时间戳timestampdt.timestamp()print(f时间戳:{timestamp})# 毫秒时间戳很多API用毫秒timestamp_msint(time.time()*1000)print(f毫秒时间戳:{timestamp_ms})# 毫秒时间戳 → 日期dtdatetime.fromtimestamp(timestamp_ms/1000)print(f日期:{dt})2.5 日期加减计算fromdatetimeimportdatetime,timedelta nowdatetime.now()# 加减天数tomorrownowtimedelta(days1)yesterdaynow-timedelta(days1)next_weeknowtimedelta(weeks1)print(f明天:{tomorrow.strftime(%Y-%m-%d)})print(f昨天:{yesterday.strftime(%Y-%m-%d)})print(f下周:{next_week.strftime(%Y-%m-%d)})# 加减小时/分钟one_hour_laternowtimedelta(hours1)thirty_min_agonow-timedelta(minutes30)# 计算两个日期的差date1datetime(2026,7,1)date2datetime(2026,7,15)diffdate2-date1print(f相差:{diff.days}天)# 14# 计算年龄birthdatetime(1990,6,15)age(datetime.now()-birth).days/365.25print(f年龄:{int(age)}岁)2.6 工作日计算fromdatetimeimportdatetime,timedeltadefadd_workdays(start_date,days):从指定日期开始加N个工作日currentstart_date added0whileaddeddays:currenttimedelta(days1)# 周一到周五是工作日ifcurrent.weekday()5:added1returncurrent# 3个工作日后是哪天startdatetime(2026,7,1)# 周三resultadd_workdays(start,3)print(f3个工作日后:{result.strftime(%Y-%m-%d)})# 2026-07-06周一# 考虑法定节假日需要chinesecalendar库defadd_workdays_with_holidays(start_date,days):加N个工作日考虑法定节假日try:fromchinese_calendarimportis_workdayexceptImportError:print(未安装chinesecalendar使用基础工作日计算)returnadd_workdays(start_date,days)currentstart_date added0whileaddeddays:currenttimedelta(days1)ifis_workday(current):added1returncurrent# 本月所有工作日defget_workdays_in_month(year,month):获取某月所有工作日try:fromchinese_calendarimportis_workdayexceptImportError:is_workdaylambdad:d.weekday()5workdays[]day1whileTrue:try:ddatetime(year,month,day)exceptValueError:breakifis_workday(d):workdays.append(d)day1returnworkdays# 使用workdaysget_workdays_in_month(2026,7)print(f2026年7月工作日:{len(workdays)}天)forwdinworkdays[:5]:print(f{wd.strftime(%Y-%m-%d %A)})2.7 计算耗时importtimefromdatetimeimportdatetimedefmeasure_time(func):计算函数执行耗时starttime.time()resultfunc()elapsedtime.time()-startifelapsed1:print(f耗时:{elapsed*1000:.0f}毫秒)elifelapsed60:print(f耗时:{elapsed:.2f}秒)else:minutesint(elapsed//60)secondselapsed%60print(f耗时:{minutes}分{seconds:.0f}秒)returnresult# 流程耗时统计classTimer:流程计时器def__init__(self):self.checkpoints[]defcheckpoint(self,name):记录检查点self.checkpoints.append({name:name,time:time.time()})defreport(self):输出耗时报告iflen(self.checkpoints)2:print(至少需要2个检查点)returnprint(\n 耗时报告 )foriinrange(1,len(self.checkpoints)):prevself.checkpoints[i-1]currself.checkpoints[i]elapsedcurr[time]-prev[time]print(f{prev[name]}→{curr[name]}:{elapsed:.2f}秒)totalself.checkpoints[-1][time]-self.checkpoints[0][time]print(f总耗时:{total:.2f}秒)# 使用示例# timer Timer()# timer.checkpoint(开始)# # ... 执行操作A ...# timer.checkpoint(操作A完成)# # ... 执行操作B ...# timer.checkpoint(操作B完成)# # ... 执行操作C ...# timer.checkpoint(操作C完成)# timer.report()2.8 生成带日期的文件名fromdatetimeimportdatetimeimportosdefgenerate_dated_filename(prefix,extension,dtNone):生成带日期的文件名ifdtisNone:dtdatetime.now()date_strdt.strftime(%Y%m%d)time_strdt.strftime(%H%M%S)filenamef{prefix}_{date_str}_{time_str}.{extension}returnfilename# 使用示例print(generate_dated_filename(日报,xlsx))# 日报_20260701_183518.xlsxprint(generate_dated_filename(采集结果,csv))# 采集结果_20260701_183518.csvprint(generate_dated_filename(截图,png))# 截图_20260701_183518.png# 按日期创建目录defcreate_dated_folder(base_dir,dtNone):按日期创建文件夹ifdtisNone:dtdatetime.now()folder_pathos.path.join(base_dir,dt.strftime(%Y),dt.strftime(%m),dt.strftime(%d))os.makedirs(folder_path,exist_okTrue)returnfolder_path# D:\data\2026\07\01# folder create_dated_folder(rD:\data)三、有什么坑坑1strftime的中文格式化问题fromdatetimeimportdatetime nowdatetime.now()# Windows上可能报错# now.strftime(%Y年%m月%d日) # 可能在某些系统上报UnicodeEncodeError[video(video-WO398Gmi-1784395101298)(type-csdn)(url-https://live.csdn.net/v/embed/524992)(image-https://v-blog.csdnimg.cn/asset/b59aed2f01d4fe8583467562aaf4dcfd/cover/Cover0.jpg)(title-temu店群自动化报活动案例)]# 解决先格式化再拼接date_strf{now.year}年{now.month:02d}月{now.day:02d}日print(date_str)# 2026年07月01日坑2月份和天数不补零fromdatetimeimportdatetime nowdatetime(2026,7,1)# 默认不补零print(f{now.year}-{now.month}-{now.day})# 2026-7-1# 补零print(f{now.year}-{now.month:02d}-{now.day:02d})# 2026-07-01# strftime自动补零print(now.strftime(%Y-%m-%d))# 2026-07-01坑3跨月计算日期出错fromdatetimeimportdatetime,timedelta# 1月31日加1个月 ≠ 2月31日datedatetime(2026,1,31)# 错误做法# wrong date.replace(month2) # ValueError: day is out of range# 正确做法用calendar库importcalendardefadd_months(source_date,months):加N个月monthsource_date.month-1months yearsource_date.yearmonth//12monthmonth%121daymin(source_date.day,calendar.monthrange(year,month)[1])returnsource_date.replace(yearyear,monthmonth,dayday)resultadd_months(datetime(2026,1,31),1)print(result)# 2026-02-28自动处理月末坑4时区问题服务器时区和本地不一致导致时间对不上fromdatetimeimportdatetime,timezone,timedelta# UTC时间utc_nowdatetime.now(timezone.utc)print(fUTC:{utc_now})# 北京时间UTC8beijing_tztimezone(timedelta(hours8))beijing_nowdatetime.now(beijing_tz)print(f北京:{beijing_now})# UTC转北京时间utc_timedatetime(2026,7,1,10,0,0,tzinfotimezone.utc)beijing_timeutc_time.astimezone(beijing_tz)print(fUTC 10:00 → 北京{beijing_time.strftime(%H:%M)})# 18:00坑5时间比较的类型不一致fromdatetimeimportdatetimeimporttime# 时间戳和日期对象不能直接比较timestamptime.time()dtdatetime.now()# 错误# if timestamp dt: # TypeError# 正确统一类型iftimestampdt.timestamp():print(时间戳更大)# 字符串日期比较只对相同格式有效d12026-07-01d22026-07-15print(d1d2)# True字符串比较YYYY-MM-DD格式可行# 但不同格式不行d32026-7-1print(d1d3)# False字符串比较位数不同结果错误# 安全做法都转为datetime对象比较fromdatetimeimportdatetime d1_dtdatetime.strptime(d1,%Y-%m-%d)d3_dtdatetime.strptime(d3,%Y-%m-%d)# 注意格式匹配print(d1_dtd3_dt)# True总结时间日期操作的核心要点格式化统一用strftime——文件名用%Y%m%d显示用%Y-%m-%d解析用strptime——注意格式要和字符串匹配工作日计算用chinesecalendar——基础方法不考虑节假日跨月计算要处理月末——用calendar.monthrange获取天数时区用timezonetimedelta——服务器和本地时区可能不同耗时统计用time.time()——比datetime更精确
影刀RPA 时间日期的进阶操作:时区、格式、计算
影刀RPA 时间日期的进阶操作时区、格式、计算作者林焱时间日期看起来简单实际用起来坑特别多时间戳和字符串互转搞不清、时区差异导致时间对不上、工作日计算忘了考虑节假日、文件名里的日期格式不统一。这篇文章把RPA里常见的时间日期操作整理成速查手册。一、什么情况用什么场景推荐方法说明获取当前时间datetime.now()最常用格式化时间显示strftime()自定义格式解析时间字符串strptime()字符串转时间对象时间戳转日期datetime.fromtimestamp()Unix时间戳转换日期加减timedelta前后N天计算工作日计算chinesecalendar考虑法定节假日文件名带日期strftime(“%Y%m%d”)20260615格式计算耗时两个时间相减性能监控时区转换pytz / zoneinfo跨时区场景二、怎么做2.1 获取当前时间店群矩阵自动化突破运营极限fromdatetimeimportdatetime,date,timedeltaimporttime# 当前日期时间nowdatetime.now()print(now)# 2026-07-01 18:35:18.123456# 当前日期不含时间todaydate.today()print(today)# 2026-07-01# 当前时间戳timestamptime.time()print(timestamp)# 1751364918.123456# 各部分单独获取print(f年:{now.year})# 2026print(f月:{now.month})# 7print(f日:{now.day})# 1print(f时:{now.hour})# 18print(f分:{now.minute})# 35print(f秒:{now.second})# 18print(f星期:{now.weekday()})# 0周一, 6周日2.2 格式化时间fromdatetimeimportdatetime nowdatetime.now()# 常用格式print(now.strftime(%Y-%m-%d))# 2026-07-01print(now.strftime(%Y/%m/%d))# 2026/07/01print(now.strftime(%Y%m%d))# 20260701适合文件名print(now.strftime(%H:%M:%S))# 18:35:18print(now.strftime(%Y-%m-%d %H:%M:%S))# 2026-07-01 18:35:18print(now.strftime(%Y年%m月%d日))# 2026年07月01日print(now.strftime(%Y%m%d_%H%M%S))# 20260701_183518适合文件名带时间# 格式化符号速查# %Y 年4位 %m 月01-12 %d 日01-31# %H 时24h %M 分00-59 %S 秒00-59# %y 年2位 %I 时12h %p AM/PM# %A 星期全名 %a 星期缩写 %B 月份全名 %b 月份缩写2.3 解析时间字符串fromdatetimeimportdatetime# 字符串 → 时间对象date_str2026-07-01 18:35:18dtdatetime.strptime(date_str,%Y-%m-%d %H:%M:%S)print(dt)# 2026-07-01 18:35:18# 只解析日期date_str2026/07/01dtdatetime.strptime(date_str,%Y/%m/%d)print(dt)# 2026-07-01 00:00:00# 解析各种格式formats[(2026-07-01,%Y-%m-%d),(2026/07/01,%Y/%m/%d),(01-07-2026,%d-%m-%Y),(20260701,%Y%m%d),(2026年7月1日,%Y年%m月%d日),]fordate_str,fmtinformats:try:dtdatetime.strptime(date_str,fmt)print(f{date_str} →{dt.strftime(%Y-%m-%d)})exceptValueErrorase:print(f{date_str} 解析失败:{e})2.4 时间戳转换fromdatetimeimportdatetimeimporttime# 当前时间戳timestamptime.time()print(f时间戳:{timestamp})# 1751364918.123# 时间戳 → 日期时间dtdatetime.fromtimestamp(timestamp)print(f日期时间:{dt})# 日期时间 → 时间戳timestampdt.timestamp()print(f时间戳:{timestamp})# 毫秒时间戳很多API用毫秒timestamp_msint(time.time()*1000)print(f毫秒时间戳:{timestamp_ms})# 毫秒时间戳 → 日期dtdatetime.fromtimestamp(timestamp_ms/1000)print(f日期:{dt})2.5 日期加减计算fromdatetimeimportdatetime,timedelta nowdatetime.now()# 加减天数tomorrownowtimedelta(days1)yesterdaynow-timedelta(days1)next_weeknowtimedelta(weeks1)print(f明天:{tomorrow.strftime(%Y-%m-%d)})print(f昨天:{yesterday.strftime(%Y-%m-%d)})print(f下周:{next_week.strftime(%Y-%m-%d)})# 加减小时/分钟one_hour_laternowtimedelta(hours1)thirty_min_agonow-timedelta(minutes30)# 计算两个日期的差date1datetime(2026,7,1)date2datetime(2026,7,15)diffdate2-date1print(f相差:{diff.days}天)# 14# 计算年龄birthdatetime(1990,6,15)age(datetime.now()-birth).days/365.25print(f年龄:{int(age)}岁)2.6 工作日计算fromdatetimeimportdatetime,timedeltadefadd_workdays(start_date,days):从指定日期开始加N个工作日currentstart_date added0whileaddeddays:currenttimedelta(days1)# 周一到周五是工作日ifcurrent.weekday()5:added1returncurrent# 3个工作日后是哪天startdatetime(2026,7,1)# 周三resultadd_workdays(start,3)print(f3个工作日后:{result.strftime(%Y-%m-%d)})# 2026-07-06周一# 考虑法定节假日需要chinesecalendar库defadd_workdays_with_holidays(start_date,days):加N个工作日考虑法定节假日try:fromchinese_calendarimportis_workdayexceptImportError:print(未安装chinesecalendar使用基础工作日计算)returnadd_workdays(start_date,days)currentstart_date added0whileaddeddays:currenttimedelta(days1)ifis_workday(current):added1returncurrent# 本月所有工作日defget_workdays_in_month(year,month):获取某月所有工作日try:fromchinese_calendarimportis_workdayexceptImportError:is_workdaylambdad:d.weekday()5workdays[]day1whileTrue:try:ddatetime(year,month,day)exceptValueError:breakifis_workday(d):workdays.append(d)day1returnworkdays# 使用workdaysget_workdays_in_month(2026,7)print(f2026年7月工作日:{len(workdays)}天)forwdinworkdays[:5]:print(f{wd.strftime(%Y-%m-%d %A)})2.7 计算耗时importtimefromdatetimeimportdatetimedefmeasure_time(func):计算函数执行耗时starttime.time()resultfunc()elapsedtime.time()-startifelapsed1:print(f耗时:{elapsed*1000:.0f}毫秒)elifelapsed60:print(f耗时:{elapsed:.2f}秒)else:minutesint(elapsed//60)secondselapsed%60print(f耗时:{minutes}分{seconds:.0f}秒)returnresult# 流程耗时统计classTimer:流程计时器def__init__(self):self.checkpoints[]defcheckpoint(self,name):记录检查点self.checkpoints.append({name:name,time:time.time()})defreport(self):输出耗时报告iflen(self.checkpoints)2:print(至少需要2个检查点)returnprint(\n 耗时报告 )foriinrange(1,len(self.checkpoints)):prevself.checkpoints[i-1]currself.checkpoints[i]elapsedcurr[time]-prev[time]print(f{prev[name]}→{curr[name]}:{elapsed:.2f}秒)totalself.checkpoints[-1][time]-self.checkpoints[0][time]print(f总耗时:{total:.2f}秒)# 使用示例# timer Timer()# timer.checkpoint(开始)# # ... 执行操作A ...# timer.checkpoint(操作A完成)# # ... 执行操作B ...# timer.checkpoint(操作B完成)# # ... 执行操作C ...# timer.checkpoint(操作C完成)# timer.report()2.8 生成带日期的文件名fromdatetimeimportdatetimeimportosdefgenerate_dated_filename(prefix,extension,dtNone):生成带日期的文件名ifdtisNone:dtdatetime.now()date_strdt.strftime(%Y%m%d)time_strdt.strftime(%H%M%S)filenamef{prefix}_{date_str}_{time_str}.{extension}returnfilename# 使用示例print(generate_dated_filename(日报,xlsx))# 日报_20260701_183518.xlsxprint(generate_dated_filename(采集结果,csv))# 采集结果_20260701_183518.csvprint(generate_dated_filename(截图,png))# 截图_20260701_183518.png# 按日期创建目录defcreate_dated_folder(base_dir,dtNone):按日期创建文件夹ifdtisNone:dtdatetime.now()folder_pathos.path.join(base_dir,dt.strftime(%Y),dt.strftime(%m),dt.strftime(%d))os.makedirs(folder_path,exist_okTrue)returnfolder_path# D:\data\2026\07\01# folder create_dated_folder(rD:\data)三、有什么坑坑1strftime的中文格式化问题fromdatetimeimportdatetime nowdatetime.now()# Windows上可能报错# now.strftime(%Y年%m月%d日) # 可能在某些系统上报UnicodeEncodeError[video(video-WO398Gmi-1784395101298)(type-csdn)(url-https://live.csdn.net/v/embed/524992)(image-https://v-blog.csdnimg.cn/asset/b59aed2f01d4fe8583467562aaf4dcfd/cover/Cover0.jpg)(title-temu店群自动化报活动案例)]# 解决先格式化再拼接date_strf{now.year}年{now.month:02d}月{now.day:02d}日print(date_str)# 2026年07月01日坑2月份和天数不补零fromdatetimeimportdatetime nowdatetime(2026,7,1)# 默认不补零print(f{now.year}-{now.month}-{now.day})# 2026-7-1# 补零print(f{now.year}-{now.month:02d}-{now.day:02d})# 2026-07-01# strftime自动补零print(now.strftime(%Y-%m-%d))# 2026-07-01坑3跨月计算日期出错fromdatetimeimportdatetime,timedelta# 1月31日加1个月 ≠ 2月31日datedatetime(2026,1,31)# 错误做法# wrong date.replace(month2) # ValueError: day is out of range# 正确做法用calendar库importcalendardefadd_months(source_date,months):加N个月monthsource_date.month-1months yearsource_date.yearmonth//12monthmonth%121daymin(source_date.day,calendar.monthrange(year,month)[1])returnsource_date.replace(yearyear,monthmonth,dayday)resultadd_months(datetime(2026,1,31),1)print(result)# 2026-02-28自动处理月末坑4时区问题服务器时区和本地不一致导致时间对不上fromdatetimeimportdatetime,timezone,timedelta# UTC时间utc_nowdatetime.now(timezone.utc)print(fUTC:{utc_now})# 北京时间UTC8beijing_tztimezone(timedelta(hours8))beijing_nowdatetime.now(beijing_tz)print(f北京:{beijing_now})# UTC转北京时间utc_timedatetime(2026,7,1,10,0,0,tzinfotimezone.utc)beijing_timeutc_time.astimezone(beijing_tz)print(fUTC 10:00 → 北京{beijing_time.strftime(%H:%M)})# 18:00坑5时间比较的类型不一致fromdatetimeimportdatetimeimporttime# 时间戳和日期对象不能直接比较timestamptime.time()dtdatetime.now()# 错误# if timestamp dt: # TypeError# 正确统一类型iftimestampdt.timestamp():print(时间戳更大)# 字符串日期比较只对相同格式有效d12026-07-01d22026-07-15print(d1d2)# True字符串比较YYYY-MM-DD格式可行# 但不同格式不行d32026-7-1print(d1d3)# False字符串比较位数不同结果错误# 安全做法都转为datetime对象比较fromdatetimeimportdatetime d1_dtdatetime.strptime(d1,%Y-%m-%d)d3_dtdatetime.strptime(d3,%Y-%m-%d)# 注意格式匹配print(d1_dtd3_dt)# True总结时间日期操作的核心要点格式化统一用strftime——文件名用%Y%m%d显示用%Y-%m-%d解析用strptime——注意格式要和字符串匹配工作日计算用chinesecalendar——基础方法不考虑节假日跨月计算要处理月末——用calendar.monthrange获取天数时区用timezonetimedelta——服务器和本地时区可能不同耗时统计用time.time()——比datetime更精确