UNPKG

@heinlein-video/rrule

Version:

rrule fork. Includes the src/ folder for typescript sourceMaps

181 lines (150 loc) 4.62 kB
import { notEmpty, repeat, range, isPresent } from '../helpers' import { ParsedOptions, Frequency } from '../types' import { YearInfo, rebuildYear } from './yearinfo' import { rebuildMonth, MonthInfo } from './monthinfo' import { easter } from './easter' import { Time } from '../datetime' import { datetime, sort, toOrdinal } from '../dateutil' export type DaySet = [(number | null)[], number, number] export type GetDayset = () => DaySet // ============================================================================= // Iterinfo // ============================================================================= export default class Iterinfo { public yearinfo: YearInfo public monthinfo: MonthInfo public eastermask: number[] | null // eslint-disable-next-line no-empty-function constructor(private options: ParsedOptions) {} rebuild(year: number, month: number) { const options = this.options if (year !== this.lastyear) { this.yearinfo = rebuildYear(year, options) } if ( notEmpty(options.bynweekday) && (month !== this.lastmonth || year !== this.lastyear) ) { const { yearlen, mrange, wdaymask } = this.yearinfo this.monthinfo = rebuildMonth( year, month, yearlen, mrange, wdaymask, options ) } if (isPresent(options.byeaster)) { this.eastermask = easter(year, options.byeaster) } } get lastyear() { return this.monthinfo ? this.monthinfo.lastyear : null } get lastmonth() { return this.monthinfo ? this.monthinfo.lastmonth : null } get yearlen() { return this.yearinfo.yearlen } get yearordinal() { return this.yearinfo.yearordinal } get mrange() { return this.yearinfo.mrange } get wdaymask() { return this.yearinfo.wdaymask } get mmask() { return this.yearinfo.mmask } get wnomask() { return this.yearinfo.wnomask } get nwdaymask() { return this.monthinfo ? this.monthinfo.nwdaymask : [] } get nextyearlen() { return this.yearinfo.nextyearlen } get mdaymask() { return this.yearinfo.mdaymask } get nmdaymask() { return this.yearinfo.nmdaymask } ydayset() { return [range(this.yearlen), 0, this.yearlen] } mdayset(_: unknown, month: number) { const start = this.mrange[month - 1] const end = this.mrange[month] const set = repeat<number | null>(null, this.yearlen) for (let i = start; i < end; i++) set[i] = i return [set, start, end] } wdayset(year: number, month: number, day: number) { // We need to handle cross-year weeks here. const set = repeat<number | null>(null, this.yearlen + 7) let i = toOrdinal(datetime(year, month, day)) - this.yearordinal const start = i for (let j = 0; j < 7; j++) { set[i] = i ++i if (this.wdaymask[i] === this.options.wkst) break } return [set, start, i] } ddayset(year: number, month: number, day: number) { const set = repeat(null, this.yearlen) as (number | null)[] const i = toOrdinal(datetime(year, month, day)) - this.yearordinal set[i] = i return [set, i, i + 1] } htimeset(hour: number, _: number, second: number, millisecond: number) { let set: Time[] = [] this.options.byminute.forEach((minute) => { set = set.concat(this.mtimeset(hour, minute, second, millisecond)) }) sort(set) return set } mtimeset(hour: number, minute: number, _: number, millisecond: number) { const set = this.options.bysecond.map( (second) => new Time(hour, minute, second, millisecond) ) sort(set) return set } stimeset(hour: number, minute: number, second: number, millisecond: number) { return [new Time(hour, minute, second, millisecond)] } getdayset(freq: Frequency): (y: number, m: number, d: number) => DaySet { switch (freq) { case Frequency.YEARLY: return this.ydayset.bind(this) case Frequency.MONTHLY: return this.mdayset.bind(this) case Frequency.WEEKLY: return this.wdayset.bind(this) case Frequency.DAILY: return this.ddayset.bind(this) default: return this.ddayset.bind(this) } } gettimeset( freq: Frequency.HOURLY | Frequency.MINUTELY | Frequency.SECONDLY ): (h: number, m: number, s: number, ms: number) => Time[] { switch (freq) { case Frequency.HOURLY: return this.htimeset.bind(this) case Frequency.MINUTELY: return this.mtimeset.bind(this) case Frequency.SECONDLY: return this.stimeset.bind(this) } } }