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

前端 未结 4 1381
不知归路
不知归路 2020-12-31 23:17

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

相关标签:
4条回答
  • 2020-12-31 23:49

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

    0 讨论(0)
  • 2021-01-01 00:00

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

    0 讨论(0)
  • 2021-01-01 00:05

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

    0 讨论(0)
  • 2021-01-01 00:12

    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.

    0 讨论(0)
提交回复
热议问题