import re from app import schemas from datetime import datetime from datetime import timedelta from datetime import timezone import croniter from configs.settings import config hour_min = config.get('CRON_CONFIG', 'hour_min') hour_max = config.get('CRON_CONFIG', 'hour_max') enable = config.get('CRON_CONFIG', 'enable') def joint_cron_expression(item: schemas.CronExpression): cron = "" if item.cron_select_type == 0: if item.minute is not None: cron += '0/'+str(item.minute) + ' *' elif item.hour is not None: cron += '0 4-22/'+str(item.hour) else: cron += '*' cron += ' * * *' elif item.cron_select_type == 1: if item.minute is not None: cron += str(item.minute) else: cron += '*' cron += ' ' if item.hour is not None: cron += str(item.hour) else: cron += '*' cron += ' * * *' elif item.cron_select_type == 2: if item.minute is not None: cron += str(item.minute) else: cron += '*' cron += ' ' if item.hour is not None: cron += str(item.hour) else: cron += '*' if item.week is not None: cron += ' ? * ' cron += str(item.week) else: cron += ' * * *' elif item.cron_select_type == 3: if item.minute is not None: cron += str(item.minute) else: cron += '*' cron += ' ' if item.hour is not None: cron += str(item.hour) else: cron += '*' cron += ' ' if item.day is not None: cron += str(item.day) else: cron += '*' cron += ' ' if item.month is not None: cron += '1/'+str(item.month) else: cron += '*' if item.day is not None: cron += ' ?' else: cron += ' *' else: cron = item.cron_expression check_cron_expression(cron) if enable == '1': check_cron_hour(cron) return cron # 不允许隔小时、分钟 enable_section_reg_list = [ "^(([0-9]|[0-5][0-9]))$", "^(([0-9]|[1][0-9]|2[0-3]))$", "^((([1-9]|[1-2][0-9]|3[01])(\\,|\\-|\\/){1}([1-9]|[1-2][0-9]|3[01]))|([1-9]|[1-2][0-9]|3[01])|(\\*)|(\\?))$", "^((([1-9]|[1][0-2])(\\,|\\-|\\/){1}([1-9]|[1][0-2]))|([1-9]|[1][0-2])|(\\*))$", "^((([1-7])(\\,|\\-|\\/){1}([1-7]))|([1-7])|(\\*)|(\\?))$" ] # 允许隔小时分钟 no_section_reg_list = [ "^((([0-9]|[1-5][0-9])(\\,|\\-|\\/){1}([1-9]|[1-5][0-9]))|([0-9]|[0-5][0-9])|(\\*))$", "^((([0-9]|[1][0-9]|2[0-3])(\\,|\\-|\\/){1}([1-9]|[1][0-9]|2[0-3]))|([0-9]|[1][0-9]|2[0-3])|(\\*))$", "^((([1-9]|[1-2][0-9]|3[01])(\\,|\\-|\\/){1}([1-9]|[1-2][0-9]|3[01]))|([1-9]|[1-2][0-9]|3[01])|(\\*)|(\\?))$", "^((([1-9]|[1][0-2])(\\,|\\-|\\/){1}([1-9]|[1][0-2]))|([1-9]|[1][0-2])|(\\*))$", "^((([1-7])(\\,|\\-|\\/){1}([1-7]))|([1-7])|(\\*)|(\\?))$" ] def check_cron_expression(cron_expression): cron_list = cron_expression.split(' ') unit_list = ['minute', 'hour', 'day', 'month', 'week'] reg_list = no_section_reg_list if enable == '0' else enable_section_reg_list for cron, unit, reg in zip(cron_list, unit_list, reg_list): match_obj = re.match(reg, cron) if match_obj is None: raise Exception(f'在{unit}的位置上,数据校验错误') def parsing_cron_expression(cron_expression): cron_list = cron_expression.split(' ') unit_list = ['minute', 'hour', 'day', 'month', 'week'] cron_dict = {} for cron, unit in zip(cron_list, unit_list): if not bool(re.match('^((\\*)|(\\?))$',cron)): cron_dict.update({unit: cron.replace('0/','').replace('1/','')}) return cron_dict def check_cron_hour(cron_expression): cron_list = cron_expression.split(' ') unit_list = ['minute', 'hour', 'day', 'month', 'week'] for cron, unit in zip(cron_list, unit_list): if unit == 'hour': if int(cron) < int(hour_min) or int(cron) > int(hour_max)-1: raise Exception(f'执行时间必须在每日{hour_min}~{hour_max}时之间') def run_get_next_time(cron_expression): SHA_TZ = timezone(timedelta(hours=8),name='Asia/Shanghai',) utc_now = datetime.utcnow().replace(tzinfo=timezone.utc) now = utc_now.astimezone(SHA_TZ) cron_str = cron_expression.replace('?','*') cron = croniter.croniter(cron_str, now) execute_list = [] for i in range(0, 5): next_time = cron.get_next(datetime).strftime("%Y-%m-%d %H:%M") execute_list.append(next_time) return execute_list