HangfireIO / Cronos

A fully-featured .NET library for working with Cron expressions. Built with time zones in mind and intuitively handles daylight saving time transitions
MIT License
1.01k stars 120 forks source link

Support for multiple day of week specifiers #41

Open darkeagle76 opened 3 years ago

darkeagle76 commented 3 years ago

Hi, I would like to ask if there is a plan to support multple day of week specifiers. For example this cron expression is currenlty not supported: 0 0 11 ? 8/2 SAT,SUN#3 It means: "At 11:00 AM, on the third Saturday and Sunday of the month, every 2 months, August through December" and allow to apply the "#" specifier to two days of week Saturday and Sunday. Thanks, regards, D

olegbsspb commented 2 years ago

To support extensions L and # in days of the week for range and list, I made a branch and changed only one function:

#if !NET40
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        private static unsafe long ParseDayOfWeek(ref char* pointer, ref CronExpressionFlag flags, ref byte nthWeekDay)
        {
            var field = CronField.DaysOfWeek;
            if (Accept(ref pointer, '*') || Accept(ref pointer, '?')) return ParseStar(field, ref pointer);

            var dayOfWeek = ParseValue(field, ref pointer);

#if false // Original
            if (AcceptCharacter(ref pointer, 'L')) return ParseLastWeekDay(dayOfWeek, ref flags);
            if (Accept(ref pointer, '#')) return ParseNthWeekDay(field, ref pointer, dayOfWeek, ref flags, out nthWeekDay);

            var bits = ParseRange(field, ref pointer, dayOfWeek, ref flags);
            if (Accept(ref pointer, ',')) bits |= ParseList(field, ref pointer, ref flags);

            return bits;
#else

            var bits = ParseRange(field, ref pointer, dayOfWeek, ref flags);
            if (Accept(ref pointer, ',')) bits |= ParseList(field, ref pointer, ref flags);

            if (AcceptCharacter(ref pointer, 'L'))
                ParseLastWeekDay(dayOfWeek, ref flags);
            else if (Accept(ref pointer, '#')) 
                ParseNthWeekDay(field, ref pointer, dayOfWeek, ref flags, out nthWeekDay);

            return bits;
#endif
        }

Generation works amazingly :) Examples: 0 10 1-5L 0 10 1-2,5-6#3