Java date iterator factory, with rules specifying how to calculate the intervals

夙愿已清 提交于 2019-11-30 14:12:51

问题


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 able to get something like an infinite iterator out of it (.next() would return the next date matching the rules set).

I think I'd be able to build it myself - but calendars are a hassle, and it feels like something similar should exist already. I hate being the one to reinvent a crappier wheel.

Is anyone aware of something like this? I have been looking at JODA, and it seems to lay the groundwork for it, but does not appear to give the full functionality I want..


回答1:


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 :-)




回答2:


My company has something very much like you want but it's for .NET so it probably won't do you any good.




回答3:


You could have a look at Quartz which is designed for job scheduling.




回答4:


tl;dr

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).

java.time

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 ) ;
}

About java.time

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?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

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.



来源:https://stackoverflow.com/questions/847520/java-date-iterator-factory-with-rules-specifying-how-to-calculate-the-intervals

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!