如何在一周中的特定日期为每个第一/第二/第三/第四周创建定期工作?

时间:2018-08-08 09:19:43

标签: c# cron hangfire

我正在寻找一种表达方式,可以通过Hangfire在特定的星期几以及星期几创建有效的每月定期工作,

RecurringJob.AddOrUpdate有两种创建Cron expresison的方法(通过hangfire和字符串表达式本身来创建helper类)helper类包含Monthly表达式的方法,但问题是它仅具有日期和时间数的参数,以及我一直在寻找有效的表达方式,但发现以下主题:

Hangfire Cron expressions are not valid 我已经尝试找到一种有效的方法来创建表达目的的表达式,但是当我尝试使用http://cron.schlitt.info或{{3 }}可能由hangfire用于解析表达式):

1-7 first week
8-14 second week
15-21 third week
22-28 forth week
29-31 fifth week

1 个答案:

答案 0 :(得分:1)

根据我的理解,cron表达式不能包含星期数,请参阅下面的cron标准:

minute (0-59)
hour (0-23)
day of the month (1-31)
month of the year (1-12)
day of the week (0-6 with 0=Sunday)

话虽这么说,但不了解您的确切情况,这里有2种可能的解决方案:

解决方案1:

忽略周数并计算天数:

        RecurringJob.AddOrUpdate(() => Execute(), "0 6 1,2,3,4,5,6,7 * *");// Run every morning @ 6 if day between 1 and 7
        RecurringJob.AddOrUpdate(() => Execute(), "0 6 8,9,10,11,12,13,14 * *");// Run every morning @ 6 if day between 8 and 14
        RecurringJob.AddOrUpdate(() => Execute(), "0 6 15,16,17,18,19,20,21 * *");// Run every morning @ 6 if day between 15 and 21
        RecurringJob.AddOrUpdate(() => Execute(), "0 6 22,23,24,25,26,27,28 * *");// Run every morning @ 6 if day between 22 and 28
        RecurringJob.AddOrUpdate(() => Execute(), "0 6 29,30,31 * *");// Run every morning @ 6 if day between 29 and 31

解决方案2:

根据您的业务需求也可以解决问题的伪代码:

每天运行一次的主要作业(如果适用)将排队其他作业。

static void Main(string[] args)
    {
        RecurringJob.AddOrUpdate(() => Execute(), "0 6 * * *");// Run every morning @ 6
    }

    private static void Execute()
    {
        int currentWeekNumber = GetWeekNumberOfMonth(DateTime.Now);
        int dayNumber = (int)DateTime.Now.DayOfWeek;

        if ((currentWeekNumber == 1) && (dayNumber == (int)DayOfWeek.Wednesday))
            BackgroundJob.Enqueue(() => Console.WriteLine("Week 1 Job"));

        if ((currentWeekNumber == 2) && (dayNumber == (int)DayOfWeek.Monday))
            BackgroundJob.Enqueue(() => Console.WriteLine("Week 2 Job"));

        if ((currentWeekNumber == 3) && (dayNumber == (int)DayOfWeek.Thursday))
            BackgroundJob.Enqueue(() => Console.WriteLine("Week 3 Job"));

        if ((currentWeekNumber == 4) && (dayNumber == (int)DayOfWeek.Friday))
            BackgroundJob.Enqueue(() => Console.WriteLine("Week 4 Job"));
    }


    private static int GetWeekNumberOfMonth(DateTime date)
    {
        date = date.Date;
        DateTime firstMonthDay = new DateTime(date.Year, date.Month, 1);
        DateTime firstMonthMonday = firstMonthDay.AddDays((DayOfWeek.Monday + 7 - firstMonthDay.DayOfWeek) % 7);
        if (firstMonthMonday > date)
        {
            firstMonthDay = firstMonthDay.AddMonths(-1);
            firstMonthMonday = firstMonthDay.AddDays((DayOfWeek.Monday + 7 - firstMonthDay.DayOfWeek) % 7);
        }
        return (date - firstMonthMonday).Days / 7 + 1;
    }