0

i'm looking for expression to create valid recurring monthly jobs via hangfire on specific week number as well day of week, according:

RecurringJob.AddOrUpdate there are two ways to create Cron expresison(helper class by hangfire and string expression by itself) helper class contains method for Monthly expression but problem is that it has only parameters for number of day and time, as well when i was looking for valid expression i've found the following topic:

Hangfire Cron expressions are not valid i've tried to find any of valid way to create expression for my purposes but all of the expression which i found with example range of days for specific week getting failed when i try to parse them with http://cron.schlitt.info or https://crontab.guru(they are probably used by hangfire to parse expressions):

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

1 Answers1

1

According to my understanding cron expressions cannot contain week numbers, see cron standards below:

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)

With that being said and without understanding your exact scenario here is 2 possible solutions:

Solution 1:

Ignoring the week number and working off the day number:

        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

Solution 2:

Pseudo code that will also solve the problem depending on your business requirements:

The main job that runs at 6 once a day that will en queue the other jobs if applicable.

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;
    }    
Pieter Alberts
  • 829
  • 1
  • 7
  • 23
  • not bad solutions as a workaround,but i believe there still might be solutions with valid expressions for my purposes since we could use day number to identify week and day of the week for specific week, maybe i'm not right , thanks anyways. – vtarbinskyi Aug 10 '18 at 11:32