-
Notifications
You must be signed in to change notification settings - Fork 0
/
time.scala
73 lines (60 loc) · 2.55 KB
/
time.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.Period
import java.time.ZoneId
import java.time.temporal.ChronoField
import scala.annotation.tailrec
import scala.concurrent.duration.*
import scala.concurrent.duration.TimeUnit
import PrettyDuration.PrettyPrintableDuration
import cats.effect.*
def waitTimeUntil(scheduledTime: LocalTime): IO[FiniteDuration] = IO.realTimeInstant.flatMap { instant =>
val zone = ZoneId.systemDefault()
val now = LocalDateTime.ofInstant(instant, zone)
val adjustedNow = LocalDateTime.of(now.toLocalDate(), scheduledTime)
val next = if now.isAfter(adjustedNow) then adjustedNow.plusDays(1) else adjustedNow
val nextMillis = next.atZone(zone).toInstant().toEpochMilli()
val wait = (nextMillis - instant.toEpochMilli()).millis
IO.println(s"now: $now") *>
IO.println(s"next: $next") *>
IO.println(s"wait: ${wait.pretty}") *>
IO.println("")
.as(wait)
}
object PrettyDuration {
val timeUnitList: List[TimeUnit] =
DAYS :: HOURS :: MINUTES :: SECONDS :: MILLISECONDS :: MICROSECONDS :: NANOSECONDS :: Nil
implicit class PrettyPrintableDuration(val duration: Duration) extends AnyVal {
@tailrec
private def prettyRec(
acc: List[FiniteDuration],
remUnits: List[TimeUnit],
rem: FiniteDuration,
isPast: Boolean
): String = {
remUnits match {
case h :: t =>
if rem > Duration(1, h) then {
val x = Duration(rem.toUnit(h).toLong, h)
prettyRec(x :: acc, t, rem - x, isPast)
} else {
prettyRec(acc, t, rem, isPast)
}
case Nil =>
acc.reverse.map(_.toString).mkString(" ") + (if isPast then " ago" else "")
}
}
def pretty: String = {
duration match {
case Duration.Zero => "now"
case f: FiniteDuration if f < Duration.Zero => prettyRec(Nil, timeUnitList, f * -1, isPast = true)
case f: FiniteDuration => prettyRec(Nil, timeUnitList, f, isPast = false)
case Duration.Inf => "infinite"
case Duration.MinusInf => "minus infinite"
case _ => "undefined"
}
}
}
}