I am looking for a Java class where I can specify a set of date rules, such as \"every 3rd sunday\" and \"the first occurrence of a monday every second month\". I want to be
My company has something very much like you want but it's for .NET so it probably won't do you any good.
You could have a look at Quartz which is designed for job scheduling.
I don't think there's any readily made iterators for joda-time or Java Calendar API for that matter, however with joda it's so easy that you should just go with it. For example after re-familiarizing myself with joda after a few months pause I made this in about 10 minutes:
public class InstantIterator implements Iterator<Instant>,
Iterable<Instant> {
private Instant current;
private final Instant original;
private Duration skip;
private List<Instant> skipThese;
public InstantIterator(Instant startFrom, Duration skip) {
this.current = original = startFrom;
this.skip = skip;
skipThese = new Vector<Instant>();
}
public boolean hasNext() {
return true;
}
public Instant next() {
Instant currentNext = current.toInstant();
current = current.plus(skip);
while (skipThese.contains(currentNext)) {
currentNext = current.toInstant();
current = current.plus(skip);
}
return currentNext;
}
public void remove() {
skipThese.add(current.toInstant());
}
public Iterator<Instant> iterator() {
return this;
}
public void rewind() {
current = original.toInstant();
}
public void resetRemoved() {
skipThese.clear();
}
public void resetIterator() {
rewind();
resetRemoved();
}
}
Joda Time is awesome :-)
Easy, with java.time.
For 3rd Thursday:
LocalDate.now().with( // Get today's date, then adjust.
TemporalAdjusters.dayOfWeekInMonth( 3 , DayOfWeek.THURSDAY ) // Define adjuster to move to third Thursday of same month.
) // Instantiates another `LocalDate` object (java.time uses immutable objects).
The troublesome old date-time classes bundled with the earliest versions of Java are now obsolete, supplanted by the java.time classes.
The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate ld = LocalDate.of( 2018 , Month.FEBRUARY , 17 ) ;
For any LocalDate
, you can adjust into the ordinal occurrence of a day-of-week within the same month (ex: third Thursday, 2nd Tuesday, etc.). Specify the day-of-week using DayOfWeek enum.
To make the adjustment, use a TemporalAdjuster implementations found in the TemporalAdjusters class.
TemporalAdjuster thirdThursdayAdjuster = TemporalAdjusters.dayOfWeekInMonth( 3 , DayOfWeek.THURSDAY ) ; // Third-Thursday.
Apply that adjuster to any LocalDate
, producing another LocalDate
object.
LocalDate thirdThursday = ld.with( thirdThursdayAdjuster ) ;
something like an infinite iterator out of it (.next() would return the next date matching
Simply move from one LocalDate
to another. You could call LocalDate::addMonths
. Or if dealing with a month at a time, use the YearMonth
class.
TemporalAdjuster thirdThursdayAdjuster = TemporalAdjusters.dayOfWeekInMonth( 3 , DayOfWeek.THURSDAY ) ; // Third-Thursday.
List<LocalDate> dozenThirdThursdays = new ArrayList<>( 12 ) ;
YearMonth start = YearMonth.of( 2018 , Month.MARCH ) ;
for( int i = 1 ; i <= 12 ; i ++ ) {
YearMonth ym = start.plusMonths( i ) ;
LocalDate firstOfMonth = ym.atDay( 1 ) ;
LocalDate thirdThursday = firstOfMonth.with( thirdThursdayAdjuster ) ;
dozenThirdThursdays.add( thirdThursday ) ;
}
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.