Special cases we'll need to address: When Sunday is day #1 or day #2 of the month. By limiting Sundays to days in the range 3-9, we're safe. When Sunday is day #3 or greater, we can know for sure that there is a preceding Friday in current month.
Expression
0 0 16 3-9 3/3 SUN
Expression will fire at
Sun, Mar 7, 2021 at 04:00:00 pm
Sun, Jun 6, 2021 at 04:00:00 pm
Sun, Sep 5, 2021 at 04:00:00 pm
Sun, Dec 5, 2021 at 04:00:00 pm
Sun, Mar 6, 2022 at 04:00:00 pm
Expression may be tested like this:
var sundays = CronExpression.parse("0 0 16 3-9 3/3 SUN");
var nextDate = LocalDateTime.now();
var dateFormatter = DateTimeFormatter.ofPattern("EEE, MMM d, yyyy 'at' hh:mm:ss a");
for (var i = 0; i < 5; i++) {
nextDate = sundays.next(nextDate);
System.out.println(nextDate.format(dateFormatter));
}
We can verify that the special-case is working as depicted by having a look into June 2024
Sun, Jun 9, 2024 at 04:00:00 pm
From comment from OP
We can verify this case in May 2021. where saturday is first day of
month. So instead of 2nd May Sunday, we need 9th May Sunday. Which is
sunday after first Friday of month.
May 2021 is outside the quarterly schedule specified in question, but we can test this case by locking month to May and keep the rest of the expression unchanged like this:
0 0 16 3-9 5 SUN
Test code above will return Sun, May 9, 2021 at 04:00:00 pm
which is what OP is asking for.