cron_utils.py 5.2 KB

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