I'm trying to create a simple api for dealing with intervals of hours. (I'm aware of joda time, and I'm not trying to reinvent it. This is rather an exercise).
What I would like to achieve is this:
(1)
assert(from("20:30").to("20:50") == Interval("20:30", "20:50") )
//same thing, but without implicit defs
assert(from(Time(20, 30)).to(Time(20, 50)) == Interval(Time(20, 30), Time(20, 50)))
(2)
assert(from("20:30").forMinutes(10) == from("20:30").to("20:40"))
I have managed to implement (1), like this: (ignoring toString, Ordered trait, a.s.o)
case class Time(hour: Int, minute: Int)
case class Interval(start: Time, end: Time)
object Interval {
case class HalfInterval(half: Time => Interval) {
def to(time: Time): Interval = half(time)
def forMinutes(minutes: Int): Interval = ???
}
def from(start: Time): HalfInterval = HalfInterval(Interval(start, _))
}
object Time {
def apply(hourMinute: String): Time = {
val tries = hourMinute.split(":").map(s => Try(s.toInt))
tries match {
case Array(Success(hour), Success(minute)) => Time(hour, minute)
case _ => throw new IllegalArgumentException
}
}
implicit def stringToTime(hourMinute: String) = Time(hourMinute)
}
However, I don't know how to implement (2) (that is: Interval.forMinutes).
def forMinutes(minutes: Int): Interval = {
val time = ?? // Based on what Time object could I construct a new Time object here?
half(time)
}
Can't seem to wrap my head around this.
Does this "HalfInterval" wrapper over Time => Interval
make sense at all?
I designed it empirically - just so that the from(..).to(..)
calls work as planned - rather than with some functional-conceptual model in mind.
Is there a better way to achieve this api?
Thanks