moment-recur2

moment-recur2 is a recurring date plugin for momentjs. This plugin handles dates only time information is discarded.
It is a fork of the original moment-recur2 with a focus on ISO6801 compliance.
Example
const interval = moment("2014-01-01").recur().every(2).days()
interval.matches("2014-01-03")
const calendar = moment.recur().every(10).dayOfMonth()
calendar.matches("2014-05-10")
Getting Started
moment-recur2 can be included in your project a few different ways.
node.js
moment-recur2 can be installed with npm
and required into a script.
npm install moment-recur2
const moment = require('moment')
require('moment-recur2')
Creating a Recurring Date
You can create a recurrence from an instance of moment or from the constructor a few different ways.
From an instance:
let recurrence
recurrence = moment().recur()
recurrence = moment().recur(start, end)
recurrence = moment(start).recur(end)
recurrence = moment().recur({
start: "2014-01-01",
end: "2015-01-01"
})
From the constructor:
let recurrence
recurrence = moment.recur()
recurrence = moment.recur(start, end)
recurrence = moment.recur({
start: "2014-01-01",
end: "2015-01-01"
})
Creating Rules
moment-recur2 uses rules to define when a date should recur. You can then generate future or past recurrences based on these rules, or see if a specific date matches the rules. Rules can also be overridden or removed.
The every() Function
The every()
function allows you to set the units and, optionally, the measurement type of the recurring date. It returns the recur object to allow chaining.
let myDate, recurrence
myDate = moment("2014-01-01")
recurrence = myDate.recur().every(1, "days")
recurrence = myDate.recur().every(1).day()
recurrence = myDate.recur().every([3, 5]).days()
recurrence = myDate.recur().every(["Monday", "wed"]).daysOfWeek()
recurrence = myDate.recur().every(["Jan", "february"], "monthsOfYear")
every()
will override the last "every" if a measurement was not provided. The following line will create a recurrence for every 5 days.
recurrence = myDate.recur().every(1).every(5).days()
If you need to specify multiple units, pass an array to every()
.
You may also pass the units directly to the interval functions (listed below) instead of using every()
.
const recurrence = moment.recur().monthOfYear("January")
Length Intervals
moment-recur2 supports intervals for days, weeks, months, and years. Measurements may be singular or plural (ex: day()
vs days()
). Length Intervals must have a start date defined.
Supported length intervals include:
- day / days
- week / weeks
- month / months
- year / years
Examples
let myDate, interval
myDate = moment("2014-01-01")
interval = myDate.recur().every(1).day()
interval = myDate.recur().every(2).weeks()
interval = myDate.recur().every(3).months()
interval = myDate.recur().every(1).years()
interval = myDate.recur().every([3, 5]).days()
interval = myDate.recur().every(3).days().every(2).months()
Calendar Intervals
Calendar Intervals do not depend on a start date. They define a unit of another unit. For instance, a day of a month, or a month of a year. Measurements may be singular or plural (ex: dayOfMonth()
vs daysOfMonth()
).
Supported calendar intervals include:
- dayOfWeek / daysOfWeek
- dayOfMonth / daysOfMonth
- weekOfMonth / weeksOfMonth
- weekOfYear / weeksOfYear
- monthOfYear / monthsOfYear
Examples
let cal
cal = moment.recur().every(["Sunday", 1]).daysOfWeek()
cal = moment.recur().every([1, 10]).daysOfMonth()
cal = moment.recur().every([1, 3]).weeksOfMonth()
cal = moment.recur().every(20).weekOfYear()
cal = moment.recur().every("January").monthsOfYear()
const valentines = moment.recur().every(14).daysOfMonth()
.every("February").monthsOfYear()
cal = moment.recur().every("Thursday").daysOfWeek()
.every([0, 2]).weeksOfMonthByDay()
Using the Rules
Matching
The matches()
function will test a date to check if all of the recurrence rules match. It returns true
if the date matches, false
otherwise.
let interval = moment("2014-01-01").recur().every(2).days()
interval.matches("2014-01-02")
interval.matches("2014-01-03")
You may also see if a date matches before the start date or after the end date by passing true
as the second argument to matches()
.
let interval = moment("2014-01-01").recur().every(2).days()
interval.matches("2013-12-30")
interval.matches("2013-12-30", true)
Exceptions
To prevent a date from matching that would normally match, use the except()
function.
let recurrence = moment("2014-01-01").recur().every(1).day().except("2014-01-02")
recurrence.matches("2014-01-02")
Overriding and Forgetting
If a rule is created with the same measurement of a previous rule, it will override the previous rule. Rules can also be removed from a recurrence.
let recurrence = moment("2014-01-01").recur().every(1).day().except("2014-01-03")
recurrence.every(2).days()
recurrence.forget("2014-01-03")
recurrence.forget("days")
Generating Dates
It is also possible to generate dates from the rules. These functions require a starting date.
let recurrence, nextDates
recurrence = moment("2014-01-01").recur().every(2).days()
nextDates = recurrence.next(3)
nextDates = recurrence.next(3, "L")
nextDates = recurrence.previous(3, "L")
If your recurrence does not have a start date set, or if it does but you want to start at a different date, use the fromDate()
method first.
let recurrence = moment("2014-01-01").recur().every(2).days()
recurrence.fromDate("2014-02-05")
nextDates = recurrence.next(3, "YYYY-MM-DD")
With both a start date and an end date set, you can generate all dates within that range that match the pattern (including the start/end dates).
let recurrence = moment().recur("2014-01-01", "2014-01-07").every(2).days()
allDates = recurrence.all("YYYY-MM-DD")
Important Note: These functions may be very inefficient/slow. They work by attempting to match every date from the start of a range until the desired number of dates have been generated. So if you attempt to get 10 dates for a rule that matches once a year, it will run the match function for ~3650 days.
Options and Other Methods
moment-recur2 provides a few methods for getting/setting options, as well as two utility methods. It also creates two additional momentjs functions.
Options
Options can be set when creating a recurrence or using the getter/setter methods listed below.
Set options upon creation. Note that the units for rules are converted to objects, so it is not recommended to set rules this way. They can be set in the options so that they can be imported.
moment().recur({
start: "2014-01-01",
end: "2014-12-31",
rules: [
{ units: { 2: true }, measure: "days" }
],
excepted: ["2014-01-05"]
})
Get/Set the Start Date
recurrence.startDate()
recurrence.startDate("2014-01-01")
Get/Set the End Date
recurrence.endDate()
recurrence.endDate("2014-01-01")
Get/Set a temporary "From Date" for use with generating dates
recurrence.fromDate()
recurrence.fromDate("2014-01-01")
Utility Methods
Use repeats()
to check if a recurrence has rules set.
recurrence.repeats()
Use save()
to export all options, rules, and exceptions as an object. This can be used to store recurrences in a database.
Note: This does not export the "From Date" which is considered a temporary option.
recurrence.save()
momentjs Functions
The monthWeek()
method can be used to determine the week of the month a date is in.
moment("2014-01-01").monthWeek()
The dateOnly()
method can be used to remove any time information from a moment.
moment("2014-01-01 09:30:26").dateOnly()
License
UNLICENSE - see UNLICENSE file and unlicense.org for details.
See also the AUTHORS file.