moment-recur-ts
Version:
A momentjs plugin for matching and generating recurring dates.
147 lines (127 loc) • 3.52 kB
text/typescript
import * as moment from 'moment'
import { Calendar } from './calendar'
import { Interval } from './interval'
export namespace Rule {
export type MeasureSingle =
'day'
| 'week'
| 'month'
| 'year'
| 'dayOfWeek'
| 'dayOfMonth'
| 'weekOfMonth'
| 'weekOfMonthByDay'
| 'weekOfYear'
| 'monthOfYear'
export type MeasurePlural =
'days'
| 'weeks'
| 'months'
| 'years'
| 'daysOfWeek'
| 'daysOfMonth'
| 'weeksOfMonth'
| 'weeksOfMonthByDay'
| 'weeksOfYear'
| 'monthsOfYear'
/**
* @internal
* @hidden
*/
export const MeasureSingleToPlural: {
[m: string]: MeasurePlural
} = {
day: 'days',
week: 'weeks',
month: 'months',
year: 'years',
dayOfWeek: 'daysOfWeek',
dayOfMonth: 'daysOfMonth',
weekOfMonth: 'weeksOfMonth',
weekOfMonthByDay: 'weeksOfMonthByDay',
weekOfYear: 'weeksOfYear',
monthOfYear: 'monthsOfYear'
}
export type UnitsInput = string | number | (string | number)[] | UnitsObject | undefined | null
/**
* @hidden
* @deprecated
*/
export interface UnitsObject {
[unit: string]: boolean
[unit: number]: boolean
}
export type MeasureInput = MeasureSingle | MeasurePlural | undefined | null
/**
* @internal
* @hidden
*/
export function factory (units: UnitsInput, measure: MeasureInput, start: moment.Moment | null): Rule {
const normMeasure = normalizeMeasure(measure)
switch (normMeasure) {
case 'days':
case 'weeks':
case 'months':
case 'years':
return new Interval(unitsToArray(units), normMeasure, start)
case 'daysOfWeek':
case 'daysOfMonth':
case 'weeksOfMonth':
case 'weeksOfMonthByDay':
case 'weeksOfYear':
case 'monthsOfYear':
return new Calendar(unitsToArray(units), normMeasure)
}
}
/**
* @internal
* @hidden
*/
function unitsToArray (units: UnitsInput): (string | number)[] {
if (units == null) {
throw new Error('Units not defined for recurrence rule.')
} else if (Array.isArray(units)) {
return units
} else if (typeof units === 'object') {
return Object.keys(units)
} else if (typeof units === 'number') {
return [units]
// tslint:disable-next-line:strict-type-predicates
} else if (typeof units === 'string') {
return [units]
} else {
throw new Error('Provide an array, object, string or number when passing units!')
}
}
/**
* Private function to pluralize measure names for use with dictionaries.
* @internal
* @hidden
*/
export function normalizeMeasure (measure: any): MeasurePlural {
if (typeof measure === 'string') {
if (MeasureSingleToPlural[measure]) {
return MeasureSingleToPlural[measure]
} else {
for (const key in MeasureSingleToPlural) {
if (MeasureSingleToPlural[key] === measure) return measure
}
}
}
throw new Error('Invalid Measure for recurrence: ' + measure)
}
}
/**
*
*/
export interface Rule {
readonly units: number[]
readonly measure: Rule.MeasurePlural
/**
* @internal
* @hidden
*/
match (date: moment.Moment): boolean
next (current: moment.Moment, limit?: moment.Moment): moment.Moment
previous (current: moment.Moment, limit?: moment.Moment): moment.Moment
}