import { DateAdapter } from '../date-adapter'; import { DateTime } from '../date-time'; import { IOccurrenceGenerator, IRunArgs } from '../interfaces'; import { IOperatorConfig, Operator, OperatorFnOutput } from './interface'; import { IterableWrapper, selectNextIterable, streamPastEnd, streamPastSkipToDate, } from './utilities'; const ADD_OPERATOR_ID = Symbol.for('2898c208-e9a8-41a2-8627-2bc993ab376f'); /** * An operator function which accepts a spread of occurrence generators * and adds their occurrences to the output. * * @param streams a spread of occurrence generators */ export function add( ...streams: IOccurrenceGenerator[] ): OperatorFnOutput { return (options: IOperatorConfig) => new AddOperator(streams, options); } export class AddOperator extends Operator { static isAddOperator(object: unknown): object is AddOperator { return !!(super.isOperator(object) && (object as any)[ADD_OPERATOR_ID]); } protected readonly [ADD_OPERATOR_ID] = true; /** Not actually used but necessary for IRunnable interface */ set(_: 'timezone', value: string | null) { return new AddOperator(this._streams.map(stream => stream.set('timezone', value)), { ...this.config, base: this.config.base && this.config.base.set('timezone', value), timezone: value, }); } /** @internal */ *_run(args: IRunArgs = {}): IterableIterator { const streams = this._streams.map(input => new IterableWrapper(input._run(args))); if (this.config.base) { streams.push(new IterableWrapper(this.config.base._run(args))); } if (streams.length === 0) return; let stream = selectNextIterable(streams, args); if (streamPastEnd(stream, args)) return; while (!stream.done) { const yieldArgs = yield this.normalizeRunOutput(stream.value); stream.picked(); stream = selectNextIterable(streams, args); if (yieldArgs && yieldArgs.skipToDate) { while ( !streamPastEnd(stream, args) && !streamPastSkipToDate(stream, yieldArgs.skipToDate, args) ) { stream.picked(); stream = selectNextIterable(streams, args); } } if (streamPastEnd(stream, args)) return; } } protected calculateIsInfinite() { return ( (this.config.base && this.config.base.isInfinite) || this._streams.some(stream => stream.isInfinite) ); } protected calculateHasDuration() { const streamsDuration = this._streams.every(stream => stream.hasDuration); if (!this.config.base) return streamsDuration; return this.config.base.hasDuration && streamsDuration; } }