1717package eu .timepit .fs2cron
1818
1919import cats .effect .{Sync , Temporal }
20- import cats .syntax .all ._
20+ import cats .syntax .all .*
2121
2222import java .time .temporal .ChronoUnit
2323import java .time .{Instant , ZoneId , ZoneOffset , ZonedDateTime }
@@ -29,14 +29,20 @@ abstract class ZonedDateTimeScheduler[F[_], Schedule](zoneId: F[ZoneId])(implici
2929) extends Scheduler [F , Schedule ] {
3030 def next (from : ZonedDateTime , schedule : Schedule ): F [ZonedDateTime ]
3131
32- override def fromNowUntilNext (schedule : Schedule ): F [FiniteDuration ] =
33- now.flatMap { from =>
34- next(from, schedule).map { to =>
35- val durationInMillis = from.until(to, ChronoUnit .MILLIS )
36- FiniteDuration (durationInMillis, TimeUnit .MILLISECONDS )
37- }
32+ def durationUntilNext (from : ZonedDateTime , schedule : Schedule ): F [FiniteDuration ] =
33+ next(from, schedule).map { to =>
34+ val durationInMillis = from
35+ // Since `until` only returns complete units between `from` and `to`,
36+ // we truncate `from` to milliseconds, so that `durationInMillis` + `from`
37+ // is never before `to`. See https://github.com/fthomas/fs2-cron/issues/598.
38+ .truncatedTo(ChronoUnit .MILLIS )
39+ .until(to, ChronoUnit .MILLIS )
40+ FiniteDuration (durationInMillis, TimeUnit .MILLISECONDS )
3841 }
3942
43+ override def fromNowUntilNext (schedule : Schedule ): F [FiniteDuration ] =
44+ now.flatMap(from => durationUntilNext(from, schedule))
45+
4046 private val now : F [ZonedDateTime ] =
4147 (temporal.realTime, zoneId).mapN((d, z) => Instant .EPOCH .plusNanos(d.toNanos).atZone(z))
4248}
0 commit comments