因为APScheduler的CronTrigger本身的DayOfMonthField就不能去匹配last-n这种表达式, 所以要改造他.先放上源码:
class DayOfMonthField(BaseField):
COMPILERS = BaseField.COMPILERS + [WeekdayPositionExpression, LastDayOfMonthExpression]
def get_max(self, dateval):
return monthrange(dateval.year, dateval.month)[1]
这里的BaseField.COMPILERS, WeekdayPositionExpression,LastDayOfMonthExpression都是用来匹配表达式, 然后获取值的.如LastDayOfMonthExpression:
class LastDayOfMonthExpression(AllExpression):
value_re = re.compile(r'last', re.IGNORECASE)
def __init__(self):
super(LastDayOfMonthExpression, self).__init__(None)
def get_next_value(self, date, field):
return monthrange(date.year, date.month)[1]
def __str__(self):
return 'last'
def __repr__(self):
return "%s()" % self.__class__.__name__
作用就是匹配last, 然后通过get_next_value获取到要执行的值.那我们要做的就是在正则表示式上进行改造:
from apscheduler.triggers.cron.expressions import AllExpression
class LastNDayOfMonthExpression(AllExpression):
value_re = re.compile(r'last(-\d+)?', re.IGNORECASE)
def __init__(self):
super(LastNDayOfMonthExpression, self).__init__(None)
def get_next_value(self, date, field):
_expr = self.value_re.match(field.exprs).group(1)
day = monthrange(date.year, date.month)[1]
if _expr:
day -= int(_expr[1:])
return day
def __str__(self):
return 'last-n'
def __repr__(self):
return "%s()" % self.__class__.__name__
然后将其替换掉LastDayOfMonthExpression就行了
import re
from calendar import monthrange
from apscheduler.triggers.cron import CronTrigger as _CronTrigger, DayOfMonthField as _DayOfMonthField, BaseField
from apscheduler.triggers.cron.expressions import AllExpression, WeekdayPositionExpression
class DayOfMonthField(_DayOfMonthField):
COMPILERS = BaseField.COMPILERS + [WeekdayPositionExpression, LastNDayOfMonthExpression]
def __init__(self, name, exprs, is_default=False):
self.exprs = exprs
super().__init__(name, exprs, is_default=is_default)
class CronTrigger(_CronTrigger):
_CronTrigger.FIELDS_MAP.update({'day': DayOfMonthField})
这样我们就完成成功改造了CronTrigger, 投入使用也是很简单
from apscheduler.schedulers.background import BackgroundScheduler as _BackgroundScheduler
from utils.scheduler import CronTrigger
class BackgroundScheduler(_BackgroundScheduler):
_trigger_classes = {'cron': CronTrigger}
最后我们在创建BackgroundScheduler调度器的时候就可以使用我们自己改造的了, 是不是很简单.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。