Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make weeksOfMonthByDay match weeks from the end of the month too #53

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 48 additions & 23 deletions moment-recur.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"daysOfMonth": "date",
"daysOfWeek": "day",
"weeksOfMonth": "monthWeek",
"weeksOfMonthByDay": "monthWeekByDay",
"weeksOfMonthByDay": "monthWeeksByDay",
"weeksOfYear": "week",
"monthsOfYear": "month"
};
Expand All @@ -85,7 +85,7 @@
"daysOfMonth" : { low: 1, high: 31 },
"daysOfWeek" : { low: 0, high: 6 },
"weeksOfMonth" : { low: 0, high: 4 },
"weeksOfMonthByDay" : { low: 0, high: 4 },
"weeksOfMonthByDay" : { low: -5, high: 4 },
"weeksOfYear" : { low: 0, high: 52 },
"monthsOfYear" : { low: 0, high: 11 }
};
Expand Down Expand Up @@ -150,20 +150,28 @@
var unitType = unitTypes[measure];

// Get the unit based on the required measure of the date
var unit = date[unitType]();
var units = date[unitType]();

// If the unit is in our list, return true, else return false
if (list[unit]) {
return true;
if (units.constructor !== Array) {
units = [ units ];
}

// match on end of month days
if (unitType === 'date' && unit == date.add(1, 'months').date(0).format('D') && unit < 31) {
while (unit <= 31) {
if (list[unit]) {
return true;
for (var i = 0; i < units.length; i++) {
var unit = units[i];

// If the unit is in our list, return true, else return false
if (list[unit]) {
return true;
}

// match on end of month days
if (unitType === 'date' && unit == date.add(1, 'months').date(0).format('D') && unit < 31) {
while (unit <= 31) {
if (list[unit]) {
return true;
}
unit++;
}
unit++;
}
}

Expand Down Expand Up @@ -706,29 +714,46 @@
return day0.diff(week0, "weeks");
};

// Plugin for calculating the last week of the month of a date
moment.fn.lastMonthWeek = function() {
// Last day of the last week of the month (may be first week of next month)
var weekL = this.clone().endOf("month").endOf("week");

// Last day of week
var dayL = this.clone().endOf("week");

return dayL.diff(weekL, "weeks");
};

// Plugin for calculating the occurrence of the day of the week in the month.
// Similar to `moment().monthWeek()`, the return value is zero-indexed.
// A return value of 2 means the date is the 3rd occurence of that day
// of the week in the month.
moment.fn.monthWeekByDay = function(date) {
var day, week0, day0, diff;
var diff = this.monthWeek();

// date obj
day = this.clone();
if (this.clone().subtract(diff, "weeks").month() === this.month()) {
return diff;
}

// First day of the first week of the month
week0 = this.clone().startOf("month").startOf("week");
return diff - 1;
};

// First day of week
day0 = this.clone().startOf("week");
// Plugin for calculating the last occurrence of the day of the week in the month.
// A return value of -3 means the date is the 3rd occurence of that day
// of the week from the end of the month.
moment.fn.lastMonthWeekByDay = function() {
var diff = this.lastMonthWeek();

diff = day0.diff(week0, "weeks");
if (this.clone().subtract(diff, "weeks").month() === this.month()) {
return diff - 1;
}

if (day.subtract(diff, "weeks").month() === this.clone().month()) {
return diff;
}
};

return diff - 1;
moment.fn.monthWeeksByDay = function() {
return [ this.monthWeekByDay(), this.lastMonthWeekByDay() ];
};

// Plugin for removing all time information from a given date
Expand Down
13 changes: 13 additions & 0 deletions tests/spec/jasmine-event-recur.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,19 @@ describe("weeksOfMonthByDay()", function() {
expect(recurrence.matches(moment(startDate).date(31))).toBe(true);
});

it("can recur on the last and 3rd last Sundays of the month", function() {
var recurrence;
recurrence = moment.recur()
.every(["Sunday"]).daysOfWeek()
.every([-1, -3]).weeksOfMonthByDay();
expect(recurrence.matches(moment(startDate))).toBe(false);
expect(recurrence.matches(moment(startDate).date(6))).toBe(false);
expect(recurrence.matches(moment(startDate).date(8))).toBe(false);
expect(recurrence.matches(moment(startDate).date(13))).toBe(true);
expect(recurrence.matches(moment(startDate).date(20))).toBe(false);
expect(recurrence.matches(moment(startDate).date(27))).toBe(true);
});

it("will throw an error if used without daysOfWeek()", function() {
var recurrence, caught = { message: false };
try {
Expand Down