lib/rrule.js
function byday(rules, dt, after) {
    if(!rules || !rules.length) return dt;

    // Generate a list of candiDATES. (HA!)
    var candidates = rules.map(function(rule) {
        // Align on the correct day of the week...
        var days = rule[1]-wkday(dt);
        if(days < 0) days += 7;
        var newdt = add_d(new Date(dt), days);

        if(rule[0] > 0) {
            var wk = 0 | ((d(newdt) - 1) / 7) + 1;
            if(wk > rule[0]) return null;

            add_d(newdt, (rule[0] - wk) * 7);
        }
        else if(rule[0] < 0) {
            // Find all the matching days in the month...
            var dt2 = new Date(newdt);
            var days = [];
            while(m(dt2) === m(newdt)) {
                days.push(d(dt2));
                add_d(dt2, 7);
            }

            // Then grab the nth from the end...
            set_d(newdt, days.reverse()[(-rule[0])-1]);
        }

        // Ignore if it's a past date...
        if (newdt.valueOf() <= after.valueOf()) return null;

        return newdt;
    });

    // Select the date occurring next...
    var newdt = sort_dates(candidates).shift();
    return newdt || dt;
}
function byday(rules, dt, after) {
    if(!rules || !rules.length) return dt;

    // Generate a list of candiDATES. (HA!)
    var candidates = rules.map(function(rule) {
        // Align on the correct day of the week...
        var days = rule[1]-wkday(dt);
        if(days < 0) days += 7;
        var newdt = add_d(new Date(dt), days);

        if(rule[0] > 0) {
            var wk = 0 | ((d(newdt) - 1) / 7) + 1;
            if(wk > rule[0]) return null;

            add_d(newdt, (rule[0] - wk) * 7);
        }
        else if(rule[0] < 0) {
            // Find all the matching days in the month...
            var dt2 = new Date(newdt);
            var days = [];
            while(m(dt2) === m(newdt)) {
                days.push(d(dt2));
                add_d(dt2, 7);
            }

            // Then grab the nth from the end...
            set_d(newdt, days.reverse()[(-rule[0])-1]);
        }

        // Ignore if it's a past date...
        if (newdt.valueOf() <= after.valueOf()) return null;

        return newdt;
    });

    // Select the date occurring next...
    var newdt = sort_dates(candidates).shift();
    return newdt || dt;
}
function byday ( rules , dt , after ) { if ( ! rules || ! rules . length ) return dt ; // Generate a list of candiDATES. (HA!) var candidates = rules . map ( function ( rule ) { // Align on the correct day of the week... var days = rule [ 1 ] - wkday ( dt ) ; if ( days < 0 ) days += 7 ; var newdt = add_d ( new Date ( dt ) , days ) ; if ( rule [ 0 ] > 0 ) { var wk = 0 | ( ( d ( newdt ) - 1 ) / 7 ) + 1 ; if ( wk > rule [ 0 ] ) return null ; add_d ( newdt , ( rule [ 0 ] - wk ) * 7 ) ; } else if ( rule [ 0 ] < 0 ) { // Find all the matching days in the month... var dt2 = new Date ( newdt ) ; var days = [ ] ; while ( m ( dt2 ) === m ( newdt ) ) { days . push ( d ( dt2 ) ) ; add_d ( dt2 , 7 ) ; } // Then grab the nth from the end... set_d ( newdt , days . reverse ( ) [ ( - rule [ 0 ] ) - 1 ] ) ; } // Ignore if it's a past date... if ( newdt . valueOf ( ) <= after . valueOf ( ) ) return null ; return newdt ; } ) ; // Select the date occurring next... var newdt = sort_dates ( candidates ) . shift ( ) ; return newdt || dt ; }
Advance to the next day that satisfies the byday rule...
Advance to the next day that satisfies the byday rule ...