54 lines
1.5 KiB
Python
54 lines
1.5 KiB
Python
from dataclasses import dataclass
|
|
from datetime import timedelta
|
|
from typing import Callable, Generic, Optional, TypeVar
|
|
|
|
from reactivex import Observable, abc
|
|
from reactivex import operators as ops
|
|
from reactivex.scheduler import TimeoutScheduler
|
|
|
|
_T = TypeVar("_T")
|
|
|
|
|
|
@dataclass
|
|
class TimeInterval(Generic[_T]):
|
|
value: _T
|
|
interval: timedelta
|
|
|
|
|
|
def time_interval_(
|
|
scheduler: Optional[abc.SchedulerBase] = None,
|
|
) -> Callable[[Observable[_T]], Observable[TimeInterval[_T]]]:
|
|
def time_interval(source: Observable[_T]) -> Observable[TimeInterval[_T]]:
|
|
"""Records the time interval between consecutive values in an
|
|
observable sequence.
|
|
|
|
>>> res = time_interval(source)
|
|
|
|
Return:
|
|
An observable sequence with time interval information on
|
|
values.
|
|
"""
|
|
|
|
def subscribe(
|
|
observer: abc.ObserverBase[TimeInterval[_T]],
|
|
scheduler_: Optional[abc.SchedulerBase] = None,
|
|
) -> abc.DisposableBase:
|
|
_scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
|
|
last = _scheduler.now
|
|
|
|
def mapper(value: _T) -> TimeInterval[_T]:
|
|
nonlocal last
|
|
|
|
now = _scheduler.now
|
|
span = now - last
|
|
last = now
|
|
return TimeInterval(value=value, interval=span)
|
|
|
|
return source.pipe(ops.map(mapper)).subscribe(
|
|
observer, scheduler=_scheduler
|
|
)
|
|
|
|
return Observable(subscribe)
|
|
|
|
return time_interval
|