static Generator byWeekNoGenerator(
            int[] weekNos, final Weekday wkst, final DateValue dtStart) {
        final int[] uWeekNos = Util.uniquify(weekNos);

        return new Generator() {
            int year = dtStart.year();
            int month = dtStart.month();
            /** number of weeks in the last year seen */
            int weeksInYear;
            /** dates generated anew for each month seen */
            int[] dates;
            /** index into dates */
            int i = 0;

            /**
             * day of the year of the start of week 1 of the current year.
             * Since week 1 may start on the previous year, this may be negative.
             */
            int doyOfStartOfWeek1;

            {
                checkYear();
                checkMonth();
            }

            void checkYear() {
                // if the first day of jan is wkst, then there are 7.
                // if the first day of jan is wkst + 1, then there are 6
                // if the first day of jan is wkst + 6, then there is 1
                Weekday dowJan1 = Weekday.firstDayOfWeekInMonth(year, 1);
                int nDaysInFirstWeek =
                        7 - ((7 + dowJan1.javaDayNum - wkst.javaDayNum) % 7);
                // number of days not in any week
                int nOrphanedDays = 0;
                // according to RFC 2445
                //     Week number one of the calendar year is the first week which
                //     contains at least four (4) days in that calendar year.
                if (nDaysInFirstWeek < 4) {
                    nOrphanedDays = nDaysInFirstWeek;
                    nDaysInFirstWeek = 7;
                }

                // calculate the day of year (possibly negative) of the start of the
                // first week in the year.  This day must be of wkst.
                doyOfStartOfWeek1 = nDaysInFirstWeek - 7 + nOrphanedDays;

                weeksInYear = (TimeUtils.yearLength(year) - nOrphanedDays + 6) / 7;
            }

            void checkMonth() {
                // the day of the year of the 1st day in the month
                int doyOfMonth1 = TimeUtils.dayOfYear(year, month, 1);
                // the week of the year of the 1st day of the month.  approximate.
                int weekOfMonth = ((doyOfMonth1 - doyOfStartOfWeek1) / 7) + 1;
                // number of days in the month
                int nDays = TimeUtils.monthLength(year, month);

                // generate the dates in the month
                IntSet udates = new IntSet();
                for (int j = 0; j < uWeekNos.length; j++) {
                    int weekNo = uWeekNos[j];
                    if (weekNo < 0) {
                        weekNo += weeksInYear + 1;
                    }
                    if (weekNo >= weekOfMonth - 1 && weekNo <= weekOfMonth + 6) {
                        for (int d = 0; d < 7; ++d) {
                            int date =
                                    ((weekNo - 1) * 7 + d + doyOfStartOfWeek1 - doyOfMonth1) + 1;
                            if (date >= 1 && date <= nDays) {
                                udates.add(date);
                            }
                        }
                    }
                }
                dates = udates.toIntArray();
            }

            @Override
            boolean generate(DTBuilder builder) {

                // this is a bit odd, since we're generating days within the given
                // weeks of the year within the month/year from builder
                if (year != builder.year || month != builder.month) {
                    if (year != builder.year) {
                        year = builder.year;
                        checkYear();
                    }
                    month = builder.month;
                    checkMonth();

                    i = 0;
                }

                if (i >= dates.length) {
                    return false;
                }
                builder.day = dates[i++];
                return true;
            }

            @Override
            public String toString() {
                return "byWeekNoGenerator";
            }
        };
    }
static Generator byWeekNoGenerator ( int [ ] weekNos , final Weekday wkst , final DateValue dtStart ) { final int [ ] uWeekNos = Util . uniquify ( weekNos ) ; return new Generator ( ) { int year = dtStart . year ( ) ; int month = dtStart . month ( ) ; int weeksInYear ; int [ ] dates ; int i = 0 ; int doyOfStartOfWeek1 ; { checkYear ( ) ; checkMonth ( ) ; } void checkYear ( ) { Weekday dowJan1 = Weekday . firstDayOfWeekInMonth ( year , 1 ) ; int nDaysInFirstWeek = 7 - ( ( 7 + dowJan1 . javaDayNum - wkst . javaDayNum ) % 7 ) ; int nOrphanedDays = 0 ; if ( nDaysInFirstWeek < 4 ) { nOrphanedDays = nDaysInFirstWeek ; nDaysInFirstWeek = 7 ; } doyOfStartOfWeek1 = nDaysInFirstWeek - 7 + nOrphanedDays ; weeksInYear = ( TimeUtils . yearLength ( year ) - nOrphanedDays + 6 ) / 7 ; } void checkMonth ( ) { int doyOfMonth1 = TimeUtils . dayOfYear ( year , month , 1 ) ; int weekOfMonth = ( ( doyOfMonth1 - doyOfStartOfWeek1 ) / 7 ) + 1 ; int nDays = TimeUtils . monthLength ( year , month ) ; IntSet udates = new IntSet ( ) ; for ( int j = 0 ; j < uWeekNos . length ; j ++ ) { int weekNo = uWeekNos [ j ] ; if ( weekNo < 0 ) { weekNo += weeksInYear + 1 ; } if ( weekNo >= weekOfMonth - 1 && weekNo <= weekOfMonth + 6 ) { for ( int d = 0 ; d < 7 ; ++ d ) { int date = ( ( weekNo - 1 ) * 7 + d + doyOfStartOfWeek1 - doyOfMonth1 ) + 1 ; if ( date >= 1 && date <= nDays ) { udates . add ( date ) ; } } } } dates = udates . toIntArray ( ) ; } @ Override boolean generate ( DTBuilder builder ) { if ( year != builder . year || month != builder . month ) { if ( year != builder . year ) { year = builder . year ; checkYear ( ) ; } month = builder . month ; checkMonth ( ) ; i = 0 ; } if ( i >= dates . length ) { return false ; } builder . day = dates [ i ++ ] ; return true ; } @ Override public String toString ( ) { return "byWeekNoGenerator" ; } } ; }
constructs a generator that yields each day in the current month that falls
in one of the given weeks of the year.
@param weekNos (elements in [-53,53] != 0) week numbers
@param wkst (in RRULE_WDAY_*) day of the week that the week starts on.
@param dtStart non null