import { DateAdapter } from '../date-adapter'; import { DateTime } from '../date-time'; import { IRunArgs } from '../interfaces'; import { IOperatorConfig, Operator, OperatorFnOutput } from './interface'; import { IterableWrapper, streamPastEnd, streamPastSkipToDate } from './utilities'; const UNIQUE_OPERATOR_ID = Symbol.for('cba869a4-13bf-407a-9648-18cc66261231'); /** * An operator function which deduplicates an occurrence stream. Occurrence * `duration` is currently ignored. */ export function unique(): OperatorFnOutput { return (options: IOperatorConfig) => new UniqueOperator([], options); } export class UniqueOperator extends Operator { static isUniqueOperator(object: unknown): object is UniqueOperator { return !!(super.isOperator(object) && (object as any)[UNIQUE_OPERATOR_ID]); } protected readonly [UNIQUE_OPERATOR_ID] = true; /** Not actually used but necessary for IRunnable interface */ set(_: 'timezone', value: string | null) { return new UniqueOperator([], { ...this.config, base: this.config.base && this.config.base.set('timezone', value), timezone: value, }); } /** @internal */ *_run(args: IRunArgs = {}): IterableIterator { if (!this.config.base) return; const stream = new IterableWrapper(this.config.base._run(args)); while (!stream.done) { const yieldArgs = yield this.normalizeRunOutput(stream.value); const lastValue = stream.value; stream.picked(); if (yieldArgs && yieldArgs.skipToDate) { while ( !streamPastEnd(stream, args) && !streamPastSkipToDate(stream, yieldArgs.skipToDate, args) ) { stream.picked(); } } while (!streamPastEnd(stream, args) && stream.value.isEqual(lastValue)) { stream.picked(); } } } protected calculateIsInfinite() { return !!(this.config.base && this.config.base.isInfinite); } protected calculateHasDuration() { return !!(this.config.base && this.config.base.hasDuration); } }