1
1
/*
2
- * Copyright 2002-2021 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.
29
29
30
30
/**
31
31
* Extension of {@link CronField} for
32
- * <a href="https://www.quartz-scheduler.org>Quartz</a> -specific fields.
32
+ * <a href="https://www.quartz-scheduler.org" >Quartz</a>-specific fields.
33
33
* Created using the {@code parse*} methods, uses a {@link TemporalAdjuster}
34
34
* internally.
35
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
+ *
36
42
* @author Arjen Poutsma
37
43
* @since 5.3
38
44
*/
@@ -60,8 +66,9 @@ private QuartzCronField(Type type, Type rollForwardType, TemporalAdjuster adjust
60
66
this .rollForwardType = rollForwardType ;
61
67
}
62
68
69
+
63
70
/**
64
- * 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.
65
72
*/
66
73
public static boolean isQuartzDaysOfMonthField (String value ) {
67
74
return value .contains ("L" ) || value .contains ("W" );
@@ -78,14 +85,14 @@ public static QuartzCronField parseDaysOfMonth(String value) {
78
85
if (idx != 0 ) {
79
86
throw new IllegalArgumentException ("Unrecognized characters before 'L' in '" + value + "'" );
80
87
}
81
- else if (value .length () == 2 && value .charAt (1 ) == 'W' ) { // "LW"
88
+ else if (value .length () == 2 && value .charAt (1 ) == 'W' ) { // "LW"
82
89
adjuster = lastWeekdayOfMonth ();
83
90
}
84
91
else {
85
- if (value .length () == 1 ) { // "L"
92
+ if (value .length () == 1 ) { // "L"
86
93
adjuster = lastDayOfMonth ();
87
94
}
88
- else { // "L-[0-9]+"
95
+ else { // "L-[0-9]+"
89
96
int offset = Integer .parseInt (value .substring (idx + 1 ));
90
97
if (offset >= 0 ) {
91
98
throw new IllegalArgumentException ("Offset '" + offset + " should be < 0 '" + value + "'" );
@@ -103,7 +110,7 @@ else if (value.length() == 2 && value.charAt(1) == 'W') { // "LW"
103
110
else if (idx != value .length () - 1 ) {
104
111
throw new IllegalArgumentException ("Unrecognized characters after 'W' in '" + value + "'" );
105
112
}
106
- else { // "[0-9]+W"
113
+ else { // "[0-9]+W"
107
114
int dayOfMonth = Integer .parseInt (value .substring (0 , idx ));
108
115
dayOfMonth = Type .DAY_OF_MONTH .checkValidValue (dayOfMonth );
109
116
TemporalAdjuster adjuster = weekdayNearestTo (dayOfMonth );
@@ -114,15 +121,16 @@ else if (idx != value.length() - 1) {
114
121
}
115
122
116
123
/**
117
- * Returns whether the given value is a Quartz day-of-week field.
124
+ * Determine whether the given value is a Quartz day-of-week field.
118
125
*/
119
126
public static boolean isQuartzDaysOfWeekField (String value ) {
120
127
return value .contains ("L" ) || value .contains ("#" );
121
128
}
122
129
123
130
/**
124
- * Parse the given value into a days of week {@code QuartzCronField}, the sixth entry of a cron expression.
125
- * Expects a "L" or "#" in the given value.
131
+ * Parse the given value into a days of week {@code QuartzCronField},
132
+ * the sixth entry of a cron expression.
133
+ * <p>Expects a "L" or "#" in the given value.
126
134
*/
127
135
public static QuartzCronField parseDaysOfWeek (String value ) {
128
136
int idx = value .lastIndexOf ('L' );
@@ -135,7 +143,7 @@ public static QuartzCronField parseDaysOfWeek(String value) {
135
143
if (idx == 0 ) {
136
144
throw new IllegalArgumentException ("No day-of-week before 'L' in '" + value + "'" );
137
145
}
138
- else { // "[0-7]L"
146
+ else { // "[0-7]L"
139
147
DayOfWeek dayOfWeek = parseDayOfWeek (value .substring (0 , idx ));
140
148
adjuster = lastInMonth (dayOfWeek );
141
149
}
@@ -157,7 +165,6 @@ else if (idx == value.length() - 1) {
157
165
throw new IllegalArgumentException ("Ordinal '" + ordinal + "' in '" + value +
158
166
"' must be positive number " );
159
167
}
160
-
161
168
TemporalAdjuster adjuster = dayOfWeekInMonth (ordinal , dayOfWeek );
162
169
return new QuartzCronField (Type .DAY_OF_WEEK , Type .DAY_OF_MONTH , adjuster , value );
163
170
}
@@ -167,14 +174,13 @@ else if (idx == value.length() - 1) {
167
174
private static DayOfWeek parseDayOfWeek (String value ) {
168
175
int dayOfWeek = Integer .parseInt (value );
169
176
if (dayOfWeek == 0 ) {
170
- dayOfWeek = 7 ; // cron is 0 based; java.time 1 based
177
+ dayOfWeek = 7 ; // cron is 0 based; java.time 1 based
171
178
}
172
179
try {
173
180
return DayOfWeek .of (dayOfWeek );
174
181
}
175
182
catch (DateTimeException ex ) {
176
- String msg = ex .getMessage () + " '" + value + "'" ;
177
- throw new IllegalArgumentException (msg , ex );
183
+ throw new IllegalArgumentException (ex .getMessage () + " '" + value + "'" , ex );
178
184
}
179
185
}
180
186
@@ -213,10 +219,10 @@ private static TemporalAdjuster lastWeekdayOfMonth() {
213
219
Temporal lastDom = adjuster .adjustInto (temporal );
214
220
Temporal result ;
215
221
int dow = lastDom .get (ChronoField .DAY_OF_WEEK );
216
- if (dow == 6 ) { // Saturday
222
+ if (dow == 6 ) { // Saturday
217
223
result = lastDom .minus (1 , ChronoUnit .DAYS );
218
224
}
219
- else if (dow == 7 ) { // Sunday
225
+ else if (dow == 7 ) { // Sunday
220
226
result = lastDom .minus (2 , ChronoUnit .DAYS );
221
227
}
222
228
else {
@@ -227,7 +233,7 @@ else if (dow == 7) { // Sunday
227
233
}
228
234
229
235
/**
230
- * Return a temporal adjuster that finds the nth-to-last day of the month.
236
+ * Returns a temporal adjuster that finds the nth-to-last day of the month.
231
237
* @param offset the negative offset, i.e. -3 means third-to-last
232
238
* @return a nth-to-last day-of-month adjuster
233
239
*/
@@ -241,7 +247,7 @@ private static TemporalAdjuster lastDayWithOffset(int offset) {
241
247
}
242
248
243
249
/**
244
- * Return a temporal adjuster that finds the weekday nearest to the given
250
+ * Returns a temporal adjuster that finds the weekday nearest to the given
245
251
* day-of-month. If {@code dayOfMonth} falls on a Saturday, the date is
246
252
* moved back to Friday; if it falls on a Sunday (or if {@code dayOfMonth}
247
253
* is 1 and it falls on a Saturday), it is moved forward to Monday.
@@ -253,10 +259,10 @@ private static TemporalAdjuster weekdayNearestTo(int dayOfMonth) {
253
259
int current = Type .DAY_OF_MONTH .get (temporal );
254
260
DayOfWeek dayOfWeek = DayOfWeek .from (temporal );
255
261
256
- if ((current == dayOfMonth && isWeekday (dayOfWeek )) || // dayOfMonth is a weekday
257
- (dayOfWeek == DayOfWeek .FRIDAY && current == dayOfMonth - 1 ) || // dayOfMonth is a Saturday, so Friday before
258
- (dayOfWeek == DayOfWeek .MONDAY && current == dayOfMonth + 1 ) || // dayOfMonth is a Sunday, so Monday after
259
- (dayOfWeek == DayOfWeek .MONDAY && dayOfMonth == 1 && current == 3 )) { // dayOfMonth is Saturday 1st, so Monday 3rd
262
+ if ((current == dayOfMonth && isWeekday (dayOfWeek )) || // dayOfMonth is a weekday
263
+ (dayOfWeek == DayOfWeek .FRIDAY && current == dayOfMonth - 1 ) || // dayOfMonth is a Saturday, so Friday before
264
+ (dayOfWeek == DayOfWeek .MONDAY && current == dayOfMonth + 1 ) || // dayOfMonth is a Sunday, so Monday after
265
+ (dayOfWeek == DayOfWeek .MONDAY && dayOfMonth == 1 && current == 3 )) { // dayOfMonth is Saturday 1st, so Monday 3rd
260
266
return temporal ;
261
267
}
262
268
int count = 0 ;
@@ -292,7 +298,7 @@ private static boolean isWeekday(DayOfWeek dayOfWeek) {
292
298
}
293
299
294
300
/**
295
- * Return a temporal adjuster that finds the last of the given doy -of-week
301
+ * Returns a temporal adjuster that finds the last of the given day -of-week
296
302
* in a month.
297
303
*/
298
304
private static TemporalAdjuster lastInMonth (DayOfWeek dayOfWeek ) {
@@ -329,6 +335,7 @@ private static Temporal rollbackToMidnight(Temporal current, Temporal result) {
329
335
}
330
336
}
331
337
338
+
332
339
@ Override
333
340
public <T extends Temporal & Comparable <? super T >> T nextOrSame (T temporal ) {
334
341
T result = adjust (temporal );
@@ -345,7 +352,6 @@ public <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal) {
345
352
return result ;
346
353
}
347
354
348
-
349
355
@ Nullable
350
356
@ SuppressWarnings ("unchecked" )
351
357
private <T extends Temporal & Comparable <? super T >> T adjust (T temporal ) {
@@ -354,27 +360,25 @@ private <T extends Temporal & Comparable<? super T>> T adjust(T temporal) {
354
360
355
361
356
362
@ Override
357
- public int hashCode () {
358
- return this .value .hashCode ();
359
- }
360
-
361
- @ Override
362
- public boolean equals (Object o ) {
363
- if (this == o ) {
363
+ public boolean equals (@ Nullable Object other ) {
364
+ if (this == other ) {
364
365
return true ;
365
366
}
366
- if (!(o instanceof QuartzCronField )) {
367
+ if (!(other instanceof QuartzCronField )) {
367
368
return false ;
368
369
}
369
- QuartzCronField other = (QuartzCronField ) o ;
370
- return type () == other .type () &&
371
- this .value .equals (other .value );
370
+ QuartzCronField otherField = (QuartzCronField ) other ;
371
+ return (type () == otherField .type () && this .value .equals (otherField .value ));
372
+ }
373
+
374
+ @ Override
375
+ public int hashCode () {
376
+ return this .value .hashCode ();
372
377
}
373
378
374
379
@ Override
375
380
public String toString () {
376
381
return type () + " '" + this .value + "'" ;
377
-
378
382
}
379
383
380
384
}
0 commit comments