0
votes

I'm trying to create an array of times with RxJS operators using Moment.js objects. I think the generate() operator would be well suited, but it's returning the same time over and over, instead of the incremented time. What am I doing wrong?

According to the docs,

https://rxjs-dev.firebaseapp.com/api/index/function/generate

I should be able to use generate(startingValue, condition, increment) to create an observable which I can then pipe or subscribe to, but I can't get this to work.


times(): void {
        const startTime: Moment = START.clone(); //2019-01-01T16:00:00.000
        const endTime: Moment = END;             //2019-01-01T21:00:00.000
        generate(startTime, time => time <= endTime, time => time.add(15, 'minutes')).pipe(
           toArray()
        ).subscribe(console.log);
}

// returns: [2019-01-01T16:00:00.000, 2019-01-01T16:00:00.000...] 20 times
// desired: [2019-01-01T16:00:00.000, 2019-01-01T16:15:00.000, 2019-01-01T16:30:00.000... ]

I'm just getting an array of 20 moment objects, all with the same time value.

2

2 Answers

0
votes

I have not used generate() but it is possible that the problem is in the fact that the moment object is mutable so that momentObject.add(...) changes the momentObject. See here: https://momentjs.com/guides/#/lib-concepts/mutability/

You could try: generate(startTime, time => time <= endTime, time => time.clone().add(15, 'minutes'))

0
votes

Why do you need RxJs to create an array? Why not just use Array.from? RxJs creates streams, not arrays.

const createDateRange = (start, end, intervalQuantity, intervalType) => {
  const duration = moment.duration(end.diff(start));
  const interval = moment.duration(intervalQuantity, intervalType);
  return Array.from(
    { length: (duration.asHours() / interval.asHours()) + 1 },
    (_, i) => start.clone().add(moment.duration(intervalQuantity * i, intervalType))
  );
};

console.log(
  createDateRange(
    moment('2019-01-01T16:00:00.000'),
    moment('2019-01-01T21:00:00.000'),
    15,
    'minutes'
  )
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

If you then want an observable you could wrap the array with of to emit the whole array or from to emit the values one at a time.