#/usr/bin/envpython
#-*-coding:utf-8-*-
"""
1.解析crontab配置文件中的五个数间参数(分时日月周),获取他们对应的取值范围
2.将时间戳与crontab配置中一行时间参数对比,判断该时间戳是否在配置设定的时间范围内
"""
#$Id$
importre,time,sys
fromCore.FDateTime.FDateTimeimportFDateTime
defget_struct_time(time_stamp_int):
"""
按整型时间戳获取格式化时间分时日月周
Args:
time_stamp_int为传入的值为时间戳(整形),如:1332888820
经过localtime转换后变成
time.struct_time(tm_year=2012,tm_mon=3,tm_mday=28,tm_hour=6,tm_min=53,tm_sec=40,tm_wday=2,tm_yday=88,tm_isdst=0)
Return:
list____返回分时日月周
"""
st_time=time.localtime(time_stamp_int)
return[st_time.tm_min,st_time.tm_hour,st_time.tm_mday,st_time.tm_mon,st_time.tm_wday]
defget_strptime(time_str,str_format):
"""从字符串获取整型时间戳
Args:
time_str字符串类型的时间戳如'31/Jul/2013:17:46:01'
str_format指定time_str的格式如'%d/%b/%Y:%H:%M:%S'
Return:
返回10位整型(int)时间戳,如1375146861
"""
returnint(time.mktime(time.strptime(time_str,str_format)))
defget_str_time(time_stamp,str_format='%Y%m%d%H%M'):
"""
获取时间戳,
Args:
time_stamp10位整型(int)时间戳,如1375146861
str_format指定返回格式,值类型为字符串str
Rturn:
返回格式默认为年月日时分,如2013年7月9日1时3分:201207090103
"""
returntime.strftime("%s"%str_format,time.localtime(time_stamp))
defmatch_cont(patten,cont):
"""
正则匹配(精确符合的匹配)
Args:
patten正则表达式
cont____匹配内容
Return:
TrueorFalse
"""
res=re.match(patten,cont)
ifres:
returnTrue
else:
returnFalse
defhandle_num(val,ranges=(0,100),res=list()):
"""处理纯数字"""
val=int(val)
ifval>=ranges[0]andval<=ranges[1]:
res.append(val)
returnres
defhandle_nlist(val,ranges=(0,100),res=list()):
"""处理数字列表如1,2,3,6"""
val_list=val.split(',')
fortmp_valinval_list:
tmp_val=int(tmp_val)
iftmp_val>=ranges[0]andtmp_val<=ranges[1]:
res.append(tmp_val)
returnres
defhandle_star(val,ranges=(0,100),res=list()):
"""处理星号"""
ifval=='*':
tmp_val=ranges[0]
whiletmp_val<=ranges[1]:
res.append(tmp_val)
tmp_val=tmp_val+1
returnres
defhandle_starnum(val,ranges=(0,100),res=list()):
"""星号/数字组合如*/3"""
tmp=val.split('/')
val_step=int(tmp[1])
ifval_step<1:
returnres
val_tmp=int(tmp[1])
whileval_tmp<=ranges[1]:
res.append(val_tmp)
val_tmp=val_tmp+val_step
returnres
defhandle_range(val,ranges=(0,100),res=list()):
"""处理区间如8-20"""
tmp=val.split('-')
range1=int(tmp[0])
range2=int(tmp[1])
tmp_val=range1
ifrange1<0:
returnres
whiletmp_val<=range2andtmp_val<=ranges[1]:
res.append(tmp_val)
tmp_val=tmp_val+1
returnres
defhandle_rangedv(val,ranges=(0,100),res=list()):
"""处理区间/步长组合如8-20/3"""
tmp=val.split('/')
range2=tmp[0].split('-')
val_start=int(range2[0])
val_end=int(range2[1])
val_step=int(tmp[1])
if(val_step<1)or(val_start<0):
returnres
val_tmp=val_start
whileval_tmp<=val_endandval_tmp<=ranges[1]:
res.append(val_tmp)
val_tmp=val_tmp+val_step
returnres
defparse_conf(conf,ranges=(0,100),res=list()):
"""解析crontab五个时间参数中的任意一个"""
#去除空格,再拆分
conf=conf.strip('').strip('')
conf_list=conf.split(',')
other_conf=[]
number_conf=[]
forconf_valinconf_list:
ifmatch_cont(PATTEN['number'],conf_val):
#记录拆分后的纯数字参数
number_conf.append(conf_val)
else:
#记录拆分后纯数字以外的参数,如通配符*,区间0-8,及0-8/3之类
other_conf.append(conf_val)
ifother_conf:
#处理纯数字外各种参数
forconf_valinother_conf:
forkey,ptninPATTEN.items():
ifmatch_cont(ptn,conf_val):
res=PATTEN_HANDLER[key](val=conf_val,ranges=ranges,res=res)
ifnumber_conf:
iflen(number_conf)>1orother_conf:
#纯数字多于1,或纯数字与其它参数共存,则数字作为时间列表
res=handle_nlist(val=','.join(number_conf),ranges=ranges,res=res)
else:
#只有一个纯数字存在,则数字为时间间隔
res=handle_num(val=number_conf[0],ranges=ranges,res=res)
returnres
defparse_crontab_time(conf_string):
"""
解析crontab时间配置参数
Args:
conf_string配置内容(共五个值:分时日月周)
取值范围分钟:0-59小时:1-23日期:1-31月份:1-12星期:0-6(0表示周日)
Return:
crontab_range list格式,分时日月周五个传入参数分别对应的取值范围
"""
time_limit =((0,59),(1,23),(1,31),(1,12),(0,6))
crontab_range=[]
clist=[]
conf_length=5
tmp_list=conf_string.split('')
forvalintmp_list:
iflen(clist)==conf_length:
break
ifval:
clist.append(val)
iflen(clist)!=conf_length:
return-1,'configerrorwhith[%s]'%conf_string
cindex=0
forconfinclist:
res_conf=[]
res_conf=parse_conf(conf,ranges=time_limit[cindex],res=res_conf)
ifnotres_conf:
return-1,'configerrorwhith[%s]'%conf_string
crontab_range.append(res_conf)
cindex=cindex+1
return0,crontab_range
deftime_match_crontab(crontab_time,time_struct):
"""
将时间戳与crontab配置中一行时间参数对比,判断该时间戳是否在配置设定的时间范围内
Args:
crontab_time____crontab配置中的五个时间(分时日月周)参数对应时间取值范围
time_struct____某个整型时间戳,如:1375027200对应的分时日月周
Return:
tuple状态码,状态描述
"""
cindex=0
forvalintime_struct:
ifvalnotincrontab_time[cindex]:
return0,False
cindex=cindex+1
return0,True
defclose_to_cron(crontab_time,time_struct):
"""coron的指定范围(crontab_time)中最接近指定时间time_struct的值"""
close_time=time_struct
cindex=0
forval_structintime_struct:
offset_min=val_struct
val_close=val_struct
forval_cronincrontab_time[cindex]:
offset_tmp=val_struct-val_cron
ifoffset_tmp>0andoffset_tmp<offset_min:
val_close=val_struct
offset_min=offset_tmp
close_time[cindex]=val_close
cindex=cindex+1
returnclose_time
defcron_time_list(
cron_time,
year_num=int(get_str_time(time.time(),"%Y")),
limit_start=get_str_time(time.time(),"%Y%m%d%H%M"),
limit_end=get_str_time(time.time()+86400,"%Y%m%d%H%M")
):
#print"\nfrom",limit_start,'to',limit_end
"""
获取crontab时间配置参数取值范围内的所有时间点的时间戳
Args:
cron_time符合crontab配置指定的所有时间点
year_num____指定在哪一年内获取
limit_start开始时间
Rturn:
List所有时间点组成的列表(年月日时分组成的时间,如2013年7月29日18时56分:201307291856)
"""
#按小时和分钟组装
hour_minute=[]
forminuteincron_time[0]:
minute=str(minute)
iflen(minute)<2:
minute='0%s'%minute
forhourincron_time[1]:
hour=str(hour)
iflen(hour)<2:
hour='0%s'%hour
hour_minute.append('%s%s'%(hour,minute))
#按天和小时组装
day_hm=[]
fordayincron_time[2]:
day=str(day)
iflen(day)<2:
day='0%s'%day
forhour_mntinhour_minute:
day_hm.append('%s%s'%(day,hour_mnt))
#按月和天组装
month_dhm=[]
#只有30天的月份
month_short=['02','04','06','09','11']
formonthincron_time[3]:
month=str(month)
iflen(month)<2:
month='0%s'%month
forday_hm_sinday_hm:
ifmonth=='02':
if(((notyear_num%4)and(year_num%100))or(notyear_num%400)):
#闰年2月份有29天
ifint(day_hm_s[:2])>29:
continue
else:
#其它2月份有28天
ifint(day_hm_s[:2])>28:
continue
ifmonthinmonth_short:
ifint(day_hm_s[:2])>30:
continue
month_dhm.append('%s%s'%(month,day_hm_s))
#按年和月组装
len_start=len(limit_start)
len_end=len(limit_end)
month_dhm_limit=[]
formonth_dhm_sinmonth_dhm:
time_ymdhm='%s%s'%(str(year_num),month_dhm_s)
#开始时间\结束时间以外的排除
if(int(time_ymdhm[:len_start])<int(limit_start))or\
(int(time_ymdhm[:len_end])>int(limit_end)):
continue
month_dhm_limit.append(time_ymdhm)
iflen(cron_time[4])<7:
#按不在每周指定时间的排除
month_dhm_week=[]
fortime_minuteinmonth_dhm_limit:
str_time=time.strptime(time_minute,'%Y%m%d%H%M%S')
ifstr_time.tm_wdayincron_time[4]:
month_dhm_week.append(time_minute)
returnmonth_dhm_week
returnmonth_dhm_limit
#crontab时间参数各种写法的正则匹配
PATTEN={
#纯数字
'number':'^[0-9]+$',
#数字列表,如1,2,3,6
'num_list':'^[0-9]+([,][0-9]+)+$',
#星号*
'star':'^\*$',
#星号/数字组合,如*/3
'star_num':'^\*\/[0-9]+$',
#区间如8-20
'range':'^[0-9]+[\-][0-9]+$',
#区间/步长组合如8-20/3
'range_div':'^[0-9]+[\-][0-9]+[\/][0-9]+$'
#区间/步长列表组合,如8-20/3,21,22,34
#'range_div_list':'^([0-9]+[\-][0-9]+[\/][0-9]+)([,][0-9]+)+$'
}
#各正则对应的处理方法
PATTEN_HANDLER={
'number':handle_num,
'num_list':handle_nlist,
'star':handle_star,
'star_num':handle_starnum,
'range':handle_range,
'range_div':handle_rangedv
}
defisdo(strs,tips=None):
"""
判断是否匹配成功!
"""
try:
tips=tips==Noneand"文件名称格式错误:job_月-周-天-时-分_文件名.txt"ortips
timer=strs.replace('@',"*").replace('%','/').split('_')[1]
month,week,day,hour,mins=timer.split('-')
conf_string=mins+""+hour+""+day+""+month+""+week
res,desc=parse_crontab_time(conf_string)
ifres==0:
cron_time=desc
else:
returnFalse
now=FDateTime.now()
now=FDateTime.datetostring(now,"%Y%m%d%H%M00")
time_stamp=FDateTime.strtotime(now,"%Y%m%d%H%M00")
#time_stamp=int(time.time())
#解析时间戳对应的分时日月周
time_struct=get_struct_time(time_stamp)
match_res=time_match_crontab(cron_time,time_struct)
returnmatch_res[1]
except:
printtips
returnFalse
defmain():
"""测试用实例"""
#crontab配置中一行时间参数
#conf_string='*/10****(cd/opt/pythonpm/devpapps;/usr/local/bin/python2.5data_test.py>>output_error.txt)'
conf_string='*/10****'
#时间戳
time_stamp=int(time.time())
#解析crontab时间配置参数分时日月周各个取值范围
res,desc=parse_crontab_time(conf_string)
ifres==0:
cron_time=desc
else:
printdesc
sys,exit(-1)
print"\nconfig:",conf_string
print"\nparseresult(rangeforcrontab):"
print"minute:",cron_time[0]
print"hour:",cron_time[1]
print"day:",cron_time[2]
print"month:",cron_time[3]
print"weekday:",cron_time[4]
#解析时间戳对应的分时日月周
time_struct=get_struct_time(time_stamp)
print"\nstructtime(minutehourdaymonthweek)for%d:"%\
time_stamp,time_struct
#将时间戳与crontab配置中一行时间参数对比,判断该时间戳是否在配置设定的时间范围内
match_res=time_match_crontab(cron_time,time_struct)
print"\nmatchingresult:",match_res
#crontab配置设定范围中最近接近时指定间戳的一组时间
most_close=close_to_cron(cron_time,time_struct)
print"\ninrangeofcrontabtimewhichismostcolsetostruct",most_close
time_list=cron_time_list(cron_time)
print"\n\n%dtimesneedtotart-up:\n"%len(time_list)
printtime_list[:10],'...'
if__name__=='__main__':
#请看使用实例
strs='job_@-@-@-@-@_test02.txt.sh'
printisdo(strs)
#main()0")