Skip to content

Instantly share code, notes, and snippets.

@P7h
Created May 12, 2017 11:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save P7h/2565c2379e4d32103441e12c8c905690 to your computer and use it in GitHub Desktop.
Save P7h/2565c2379e4d32103441e12c8c905690 to your computer and use it in GitHub Desktop.
DateTime difference between 2 timestamps. Granularity from centuries to nanos.
import java.time.LocalDateTime
import scala.annotation.tailrec
object Stopwatch {
def main(args: Array[String]): Unit = {
val from = LocalDateTime.of(2001, 9, 11, 8, 46, 40, 250)
val to = LocalDateTime.now()
println(s"Time diff is [approach#1]: ${elapsedTime(from, to)}")
println(s"Time diff is [approach#2]: ${elapsedTimeApproach2(from, to)}")
}
// Original approach based on my requirements.
// The granularity with this approach is from centuries to nanos.
def elapsedTime(from: LocalDateTime, to: LocalDateTime): String = {
import java.time.temporal.ChronoUnit
import java.time.temporal.ChronoUnit._
@tailrec
def elapsedTimeRec(fromRec: LocalDateTime, units: List[ChronoUnit], accum: String): String = {
units match {
case Nil => accum.trim
case head :: tail =>
val (fromRecalc, newAccum) = {
val diff = fromRec.until(to, head)
diff match {
// If the diff is 0, don't display this unit and label.
case 0 => (fromRec, "")
case _ => val label = {
val tempLabel = head.toString
// If the diff is 1, strip off 's' from the label; aesthetics.
if (diff == 1) {
tempLabel.substring(0, tempLabel.length - 1)
} else {
tempLabel
}
}
(fromRec.plus(diff, head), s"$diff $label ")
}
}
elapsedTimeRec(fromRecalc, tail, accum + newAccum)
}
}
val reqdUnits = List[ChronoUnit](
CENTURIES,
DECADES,
YEARS,
MONTHS,
WEEKS,
DAYS,
HOURS,
MINUTES,
SECONDS,
MILLIS,
MICROS,
NANOS)
elapsedTimeRec(from, reqdUnits, "")
}
// Approach#2 based on: https://gist.github.com/krishnanraman/0a17ef012c1cb28edf3e44214f5d4e83
// The granularity with this approach is only from days to seconds.
def elapsedTimeApproach2(from: LocalDateTime, to: LocalDateTime): String = {
import java.time.ZoneOffset
import java.util.concurrent.TimeUnit._
val units = List(
(DAYS, "Days"),
(HOURS, "Hours"),
(MINUTES, "Minutes"),
(SECONDS, "Seconds")
)
def humanReadable(timediff: Long): String = {
val init = ("", timediff)
units.foldLeft(init) { case (acc, next) =>
val (human, rest) = acc
val (unit, name) = next
val res = unit.convert(rest, MILLISECONDS)
val str = if (res > 0) human + " " + res + " " + name else human
val diff = rest - MILLISECONDS.convert(res, unit)
(str, diff)
}._1
}
val t1 = from.atZone(ZoneOffset.UTC).toInstant().toEpochMilli()
val t2 = to.atZone(ZoneOffset.UTC).toInstant().toEpochMilli()
humanReadable(t2 - t1).trim
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment