UNPKG

@rschedule/rschedule

Version:

A typescript library for working with recurring dates and events.

85 lines (67 loc) 2.47 kB
import { InfiniteLoopError } from '../basic-utilities'; import { DateAdapter } from '../date-adapter'; import { DateTime } from '../date-time'; import { IOccurrenceGenerator } from '../interfaces'; import { IRunArgs } from '../interfaces/runnable'; import { DateInput } from '../utilities'; export class OccurrenceIterator< T extends typeof DateAdapter, G extends ReadonlyArray<IOccurrenceGenerator<T>> = ReadonlyArray<IOccurrenceGenerator<T>> > { private readonly iterator: IterableIterator<DateTime>; private readonly isInfinite: boolean; constructor(private iterable: IOccurrenceGenerator<T>, private args: IRunArgs) { this.iterator = iterable._run(args); this.isInfinite = iterable.isInfinite; } [Symbol.iterator] = () => this._run(); next(args?: { skipToDate?: DateInput<T> }) { return this._run(args).next(); } toArray() { if (this.args.end || this.args.take || !this.isInfinite) { return Array.from(this._run()); } throw new InfiniteLoopError( 'OccurrenceIterator#toArray() can only be called if the iterator ' + 'is not infinite, or you provide and `end` argument, or you provide ' + 'a `take` argument.', ); } private *_run(rawArgs?: { skipToDate?: DateInput<T> }) { let args = this.normalizeRunArgs(rawArgs); let date = this.iterator.next(args).value; while (date) { const yieldArgs = yield this.normalizeDateOutput(date); args = this.normalizeRunArgs(yieldArgs); date = this.iterator.next(args).value; } } private normalizeRunArgs(args?: { skipToDate?: DateInput<T> }) { return { skipToDate: this.normalizeDateInput(args && args.skipToDate), }; } private normalizeDateInput(date?: DateInput<T>) { if (!date) { return; } return DateAdapter.isInstance(date) ? date.set('timezone', this.iterable.timezone).toDateTime() : new this.iterable.dateAdapter(date).set('timezone', this.iterable.timezone).toDateTime(); } private normalizeDateOutput(date: DateTime): InstanceType<T> & { generators: G }; private normalizeDateOutput(date?: DateTime): undefined; private normalizeDateOutput(date?: DateTime) { if (!date) { return; } return this.iterable.dateAdapter.fromDateTime(date) as InstanceType<T>; } } export interface IOccurrencesArgs<T extends typeof DateAdapter> { start?: DateInput<T>; end?: DateInput<T>; take?: number; reverse?: boolean; }