UNPKG

@heinlein-video/rrule

Version:

rrule fork. Includes the src/ folder for typescript sourceMaps

232 lines (197 loc) 5.17 kB
import { RRule } from './rrule' import { sort, timeToUntilString } from './dateutil' import { includes } from './helpers' import IterResult from './iterresult' import { iterSet } from './iterset' import { QueryMethodTypes, IterResultType } from './types' import { rrulestr } from './rrulestr' import { optionsToString } from './optionstostring' function createGetterSetter<T>(fieldName: string) { return (field?: T) => { if (field !== undefined) { this[`_${fieldName}`] = field } if (this[`_${fieldName}`] !== undefined) { return this[`_${fieldName}`] } for (let i = 0; i < this._rrule.length; i++) { const field: T = this._rrule[i].origOptions[fieldName] if (field) { return field } } } } export class RRuleSet extends RRule { public readonly _rrule: RRule[] public readonly _rdate: Date[] public readonly _exrule: RRule[] public readonly _exdate: Date[] private _dtstart?: Date | null | undefined private _tzid?: string /** * * @param {Boolean?} noCache * The same stratagy as RRule on cache, default to false * @constructor */ constructor(noCache = false) { super({}, noCache) this._rrule = [] this._rdate = [] this._exrule = [] this._exdate = [] } dtstart = createGetterSetter.apply(this, ['dtstart']) tzid = createGetterSetter.apply(this, ['tzid']) _iter<M extends QueryMethodTypes>( iterResult: IterResult<M> ): IterResultType<M> { return iterSet( iterResult, this._rrule, this._exrule, this._rdate, this._exdate, this.tzid() ) } /** * Adds an RRule to the set * * @param {RRule} */ rrule(rrule: RRule) { _addRule(rrule, this._rrule) } /** * Adds an EXRULE to the set * * @param {RRule} */ exrule(rrule: RRule) { _addRule(rrule, this._exrule) } /** * Adds an RDate to the set * * @param {Date} */ rdate(date: Date) { _addDate(date, this._rdate) } /** * Adds an EXDATE to the set * * @param {Date} */ exdate(date: Date) { _addDate(date, this._exdate) } /** * Get list of included rrules in this recurrence set. * * @return List of rrules */ rrules() { return this._rrule.map((e) => rrulestr(e.toString())) } /** * Get list of excluded rrules in this recurrence set. * * @return List of exrules */ exrules() { return this._exrule.map((e) => rrulestr(e.toString())) } /** * Get list of included datetimes in this recurrence set. * * @return List of rdates */ rdates() { return this._rdate.map((e) => new Date(e.getTime())) } /** * Get list of included datetimes in this recurrence set. * * @return List of exdates */ exdates() { return this._exdate.map((e) => new Date(e.getTime())) } valueOf() { let result: string[] = [] if (!this._rrule.length && this._dtstart) { result = result.concat(optionsToString({ dtstart: this._dtstart })) } this._rrule.forEach(function (rrule) { result = result.concat(rrule.toString().split('\n')) }) this._exrule.forEach(function (exrule) { result = result.concat( exrule .toString() .split('\n') .map((line) => line.replace(/^RRULE:/, 'EXRULE:')) .filter((line) => !/^DTSTART/.test(line)) ) }) if (this._rdate.length) { result.push(rdatesToString('RDATE', this._rdate, this.tzid())) } if (this._exdate.length) { result.push(rdatesToString('EXDATE', this._exdate, this.tzid())) } return result } /** * to generate recurrence field such as: * DTSTART:19970902T010000Z * RRULE:FREQ=YEARLY;COUNT=2;BYDAY=TU * RRULE:FREQ=YEARLY;COUNT=1;BYDAY=TH */ toString() { return this.valueOf().join('\n') } /** * Create a new RRuleSet Object completely base on current instance */ clone(): RRuleSet { const rrs = new RRuleSet(!!this._cache) this._rrule.forEach((rule) => rrs.rrule(rule.clone())) this._exrule.forEach((rule) => rrs.exrule(rule.clone())) this._rdate.forEach((date) => rrs.rdate(new Date(date.getTime()))) this._exdate.forEach((date) => rrs.exdate(new Date(date.getTime()))) return rrs } } function _addRule(rrule: RRule, collection: RRule[]) { if (!(rrule instanceof RRule)) { throw new TypeError(String(rrule) + ' is not RRule instance') } if (!includes(collection.map(String), String(rrule))) { collection.push(rrule) } } function _addDate(date: Date, collection: Date[]) { if (!(date instanceof Date)) { throw new TypeError(String(date) + ' is not Date instance') } if (!includes(collection.map(Number), Number(date))) { collection.push(date) sort(collection) } } function rdatesToString( param: string, rdates: Date[], tzid: string | undefined ) { const isUTC = !tzid || tzid.toUpperCase() === 'UTC' const header = isUTC ? `${param}:` : `${param};TZID=${tzid}:` const dateString = rdates .map((rdate) => timeToUntilString(rdate.valueOf(), isUTC)) .join(',') return `${header}${dateString}` }