1
1
/*
2
- * Copyright 2002-2023 the original author or authors.
2
+ * Copyright 2002-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
30
30
/**
31
31
* Extension of {@link CronField} for
32
32
* <a href="https://www.quartz-scheduler.org">Quartz</a>-specific fields.
33
- *
34
- * <p>Created using the {@code parse*} methods, uses a {@link TemporalAdjuster}
33
+ * Created using the {@code parse*} methods, uses a {@link TemporalAdjuster}
35
34
* internally.
36
35
*
36
+ * <p>Supports a Quartz day-of-month/week field with an L/# expression. Follows
37
+ * common cron conventions in every other respect, including 0-6 for SUN-SAT
38
+ * (plus 7 for SUN as well). Note that Quartz deviates from the day-of-week
39
+ * convention in cron through 1-7 for SUN-SAT whereas Spring strictly follows
40
+ * cron even in combination with the optional Quartz-specific L/# expressions.
41
+ *
37
42
* @author Arjen Poutsma
38
43
* @since 5.3
39
44
*/
@@ -61,8 +66,9 @@ private QuartzCronField(Type type, Type rollForwardType, TemporalAdjuster adjust
61
66
this .rollForwardType = rollForwardType ;
62
67
}
63
68
69
+
64
70
/**
65
- * Returns whether the given value is a Quartz day-of-month field.
71
+ * Determine whether the given value is a Quartz day-of-month field.
66
72
*/
67
73
public static boolean isQuartzDaysOfMonthField (String value ) {
68
74
return value .contains ("L" ) || value .contains ("W" );
@@ -80,14 +86,14 @@ public static QuartzCronField parseDaysOfMonth(String value) {
80
86
if (idx != 0 ) {
81
87
throw new IllegalArgumentException ("Unrecognized characters before 'L' in '" + value + "'" );
82
88
}
83
- else if (value .length () == 2 && value .charAt (1 ) == 'W' ) { // "LW"
89
+ else if (value .length () == 2 && value .charAt (1 ) == 'W' ) { // "LW"
84
90
adjuster = lastWeekdayOfMonth ();
85
91
}
86
92
else {
87
- if (value .length () == 1 ) { // "L"
93
+ if (value .length () == 1 ) { // "L"
88
94
adjuster = lastDayOfMonth ();
89
95
}
90
- else { // "L-[0-9]+"
96
+ else { // "L-[0-9]+"
91
97
int offset = Integer .parseInt (value , idx + 1 , value .length (), 10 );
92
98
if (offset >= 0 ) {
93
99
throw new IllegalArgumentException ("Offset '" + offset + " should be < 0 '" + value + "'" );
@@ -105,7 +111,7 @@ else if (value.length() == 2 && value.charAt(1) == 'W') { // "LW"
105
111
else if (idx != value .length () - 1 ) {
106
112
throw new IllegalArgumentException ("Unrecognized characters after 'W' in '" + value + "'" );
107
113
}
108
- else { // "[0-9]+W"
114
+ else { // "[0-9]+W"
109
115
int dayOfMonth = Integer .parseInt (value , 0 , idx , 10 );
110
116
dayOfMonth = Type .DAY_OF_MONTH .checkValidValue (dayOfMonth );
111
117
TemporalAdjuster adjuster = weekdayNearestTo (dayOfMonth );
@@ -116,7 +122,7 @@ else if (idx != value.length() - 1) {
116
122
}
117
123
118
124
/**
119
- * Returns whether the given value is a Quartz day-of-week field.
125
+ * Determine whether the given value is a Quartz day-of-week field.
120
126
*/
121
127
public static boolean isQuartzDaysOfWeekField (String value ) {
122
128
return value .contains ("L" ) || value .contains ("#" );
@@ -138,7 +144,7 @@ public static QuartzCronField parseDaysOfWeek(String value) {
138
144
if (idx == 0 ) {
139
145
throw new IllegalArgumentException ("No day-of-week before 'L' in '" + value + "'" );
140
146
}
141
- else { // "[0-7]L"
147
+ else { // "[0-7]L"
142
148
DayOfWeek dayOfWeek = parseDayOfWeek (value .substring (0 , idx ));
143
149
adjuster = lastInMonth (dayOfWeek );
144
150
}
@@ -160,7 +166,6 @@ else if (idx == value.length() - 1) {
160
166
throw new IllegalArgumentException ("Ordinal '" + ordinal + "' in '" + value +
161
167
"' must be positive number " );
162
168
}
163
-
164
169
TemporalAdjuster adjuster = dayOfWeekInMonth (ordinal , dayOfWeek );
165
170
return new QuartzCronField (Type .DAY_OF_WEEK , Type .DAY_OF_MONTH , adjuster , value );
166
171
}
@@ -170,14 +175,13 @@ else if (idx == value.length() - 1) {
170
175
private static DayOfWeek parseDayOfWeek (String value ) {
171
176
int dayOfWeek = Integer .parseInt (value );
172
177
if (dayOfWeek == 0 ) {
173
- dayOfWeek = 7 ; // cron is 0 based; java.time 1 based
178
+ dayOfWeek = 7 ; // cron is 0 based; java.time 1 based
174
179
}
175
180
try {
176
181
return DayOfWeek .of (dayOfWeek );
177
182
}
178
183
catch (DateTimeException ex ) {
179
- String msg = ex .getMessage () + " '" + value + "'" ;
180
- throw new IllegalArgumentException (msg , ex );
184
+ throw new IllegalArgumentException (ex .getMessage () + " '" + value + "'" , ex );
181
185
}
182
186
}
183
187
@@ -216,10 +220,10 @@ private static TemporalAdjuster lastWeekdayOfMonth() {
216
220
Temporal lastDom = adjuster .adjustInto (temporal );
217
221
Temporal result ;
218
222
int dow = lastDom .get (ChronoField .DAY_OF_WEEK );
219
- if (dow == 6 ) { // Saturday
223
+ if (dow == 6 ) { // Saturday
220
224
result = lastDom .minus (1 , ChronoUnit .DAYS );
221
225
}
222
- else if (dow == 7 ) { // Sunday
226
+ else if (dow == 7 ) { // Sunday
223
227
result = lastDom .minus (2 , ChronoUnit .DAYS );
224
228
}
225
229
else {
@@ -256,10 +260,10 @@ private static TemporalAdjuster weekdayNearestTo(int dayOfMonth) {
256
260
int current = Type .DAY_OF_MONTH .get (temporal );
257
261
DayOfWeek dayOfWeek = DayOfWeek .from (temporal );
258
262
259
- if ((current == dayOfMonth && isWeekday (dayOfWeek )) || // dayOfMonth is a weekday
260
- (dayOfWeek == DayOfWeek .FRIDAY && current == dayOfMonth - 1 ) || // dayOfMonth is a Saturday, so Friday before
261
- (dayOfWeek == DayOfWeek .MONDAY && current == dayOfMonth + 1 ) || // dayOfMonth is a Sunday, so Monday after
262
- (dayOfWeek == DayOfWeek .MONDAY && dayOfMonth == 1 && current == 3 )) { // dayOfMonth is Saturday 1st, so Monday 3rd
263
+ if ((current == dayOfMonth && isWeekday (dayOfWeek )) || // dayOfMonth is a weekday
264
+ (dayOfWeek == DayOfWeek .FRIDAY && current == dayOfMonth - 1 ) || // dayOfMonth is a Saturday, so Friday before
265
+ (dayOfWeek == DayOfWeek .MONDAY && current == dayOfMonth + 1 ) || // dayOfMonth is a Sunday, so Monday after
266
+ (dayOfWeek == DayOfWeek .MONDAY && dayOfMonth == 1 && current == 3 )) { // dayOfMonth is Saturday 1st, so Monday 3rd
263
267
return temporal ;
264
268
}
265
269
int count = 0 ;
@@ -357,26 +361,19 @@ private <T extends Temporal & Comparable<? super T>> T adjust(T temporal) {
357
361
358
362
359
363
@ Override
360
- public int hashCode () {
361
- return this .value .hashCode ();
364
+ public boolean equals (@ Nullable Object other ) {
365
+ return (this == other || (other instanceof QuartzCronField that &&
366
+ type () == that .type () && this .value .equals (that .value )));
362
367
}
363
368
364
369
@ Override
365
- public boolean equals (@ Nullable Object o ) {
366
- if (this == o ) {
367
- return true ;
368
- }
369
- if (!(o instanceof QuartzCronField other )) {
370
- return false ;
371
- }
372
- return type () == other .type () &&
373
- this .value .equals (other .value );
370
+ public int hashCode () {
371
+ return this .value .hashCode ();
374
372
}
375
373
376
374
@ Override
377
375
public String toString () {
378
376
return type () + " '" + this .value + "'" ;
379
-
380
377
}
381
378
382
379
}
0 commit comments