cron_utils.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import re
  2. from app import schemas
  3. from datetime import datetime
  4. from datetime import timedelta
  5. from datetime import timezone
  6. import croniter
  7. from configs.settings import config
  8. hour_min = config.get('CRON_CONFIG', 'hour_min')
  9. hour_max = config.get('CRON_CONFIG', 'hour_max')
  10. enable = config.get('CRON_CONFIG', 'enable')
  11. def joint_cron_expression(item: schemas.CronExpression):
  12. cron = ""
  13. if item.cron_select_type == 0:
  14. if item.minute is not None:
  15. cron += '0/'+str(item.minute) + ' *'
  16. elif item.hour is not None:
  17. cron += '0 4-22/'+str(item.hour)
  18. else: cron += '*'
  19. cron += ' * * *'
  20. elif item.cron_select_type == 1:
  21. if item.minute is not None:
  22. cron += str(item.minute)
  23. else: cron += '*'
  24. cron += ' '
  25. if item.hour is not None:
  26. cron += str(item.hour)
  27. else: cron += '*'
  28. cron += ' * * *'
  29. elif item.cron_select_type == 2:
  30. if item.minute is not None:
  31. cron += str(item.minute)
  32. else: cron += '*'
  33. cron += ' '
  34. if item.hour is not None:
  35. cron += str(item.hour)
  36. else: cron += '*'
  37. if item.week is not None:
  38. cron += ' ? * '
  39. cron += str(item.week)
  40. else: cron += ' * * *'
  41. elif item.cron_select_type == 3:
  42. if item.minute is not None:
  43. cron += str(item.minute)
  44. else: cron += '*'
  45. cron += ' '
  46. if item.hour is not None:
  47. cron += str(item.hour)
  48. else: cron += '*'
  49. cron += ' '
  50. if item.day is not None:
  51. cron += str(item.day)
  52. else: cron += '*'
  53. cron += ' '
  54. if item.month is not None:
  55. cron += '1/'+str(item.month)
  56. else: cron += '*'
  57. if item.day is not None:
  58. cron += ' ?'
  59. else: cron += ' *'
  60. else:
  61. cron = item.cron_expression
  62. check_cron_expression(cron)
  63. if enable == '1': check_cron_hour(cron)
  64. return cron
  65. # 不允许隔小时、分钟
  66. enable_section_reg_list = [
  67. "^(([0-9]|[0-5][0-9]))$",
  68. "^(([0-9]|[1][0-9]|2[0-3]))$",
  69. "^((([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])|(\\*)|(\\?))$",
  70. "^((([1-9]|[1][0-2])(\\,|\\-|\\/){1}([1-9]|[1][0-2]))|([1-9]|[1][0-2])|(\\*))$",
  71. "^((([1-7])(\\,|\\-|\\/){1}([1-7]))|([1-7])|(\\*)|(\\?))$"
  72. ]
  73. # 允许隔小时分钟
  74. no_section_reg_list = [
  75. "^((([0-9]|[1-5][0-9])(\\,|\\-|\\/){1}([1-9]|[1-5][0-9]))|([0-9]|[0-5][0-9])|(\\*))$",
  76. "^((([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])|(\\*))$",
  77. "^((([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])|(\\*)|(\\?))$",
  78. "^((([1-9]|[1][0-2])(\\,|\\-|\\/){1}([1-9]|[1][0-2]))|([1-9]|[1][0-2])|(\\*))$",
  79. "^((([1-7])(\\,|\\-|\\/){1}([1-7]))|([1-7])|(\\*)|(\\?))$"
  80. ]
  81. def check_cron_expression(cron_expression):
  82. cron_list = cron_expression.split(' ')
  83. unit_list = ['minute', 'hour', 'day', 'month', 'week']
  84. reg_list = no_section_reg_list if enable == '0' else enable_section_reg_list
  85. for cron, unit, reg in zip(cron_list, unit_list, reg_list):
  86. match_obj = re.match(reg, cron)
  87. if match_obj is None:
  88. raise Exception(f'在{unit}的位置上,数据校验错误')
  89. def parsing_cron_expression(cron_expression):
  90. cron_list = cron_expression.split(' ')
  91. unit_list = ['minute', 'hour', 'day', 'month', 'week']
  92. cron_dict = {}
  93. for cron, unit in zip(cron_list, unit_list):
  94. if not bool(re.match('^((\\*)|(\\?))$',cron)):
  95. cron_dict.update({unit: cron.replace('0/','').replace('1/','')})
  96. return cron_dict
  97. def check_cron_hour(cron_expression):
  98. cron_list = cron_expression.split(' ')
  99. unit_list = ['minute', 'hour', 'day', 'month', 'week']
  100. for cron, unit in zip(cron_list, unit_list):
  101. if unit == 'hour':
  102. if int(cron) < int(hour_min) or int(cron) > int(hour_max)-1:
  103. raise Exception(f'执行时间必须在每日{hour_min}~{hour_max}时之间')
  104. def run_get_next_time(cron_expression):
  105. SHA_TZ = timezone(timedelta(hours=8),name='Asia/Shanghai',)
  106. utc_now = datetime.utcnow().replace(tzinfo=timezone.utc)
  107. now = utc_now.astimezone(SHA_TZ)
  108. cron_str = cron_expression.replace('?','*')
  109. cron = croniter.croniter(cron_str, now)
  110. execute_list = []
  111. for i in range(0, 5):
  112. next_time = cron.get_next(datetime).strftime("%Y-%m-%d %H:%M")
  113. execute_list.append(next_time)
  114. return execute_list