简体   繁体   中英

Pretty print java.time.Duration to something like “2 days”

The following:

java.time.Duration.ofDays(30).toString

produces this output:

PT720H

Is there a simple way to pretty print this, for example, as "30 days".

Likewise, for something like "P2DT3H4M", I'd like to output this as "2 days, 3 hours and 4 minutes".

I'm aware of the answer here "pretty print" duration in java , but not sure if I can use/convert Java's Duration to Joda's Duration to be able to use this?

You can do java.time.Duration.ofDays(30).toDays() to receive the amount of days in the Duration, or java.time.Duration.ofDays(30).getSeconds() for seconds.

If you'd like to format it differently, use String.format(), so something like this:

        Duration dur = Duration.parse("P2DT3H4M5.6S");
        Long s = dur.getSeconds();
        String formatted = String.format("%d days, %02d hours, %02d minutes", s / 3600, (s % 3600) / 60, (s % 60));

Here's the doc: https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html

I ended up using this (extended from this answer https://stackoverflow.com/a/49628638/5300930 ).

I'm sure that there should be a simpler way to do this using the Java/Scala libraries? Note, my input will always be a java.time.Duration, I can use the Joda libraries, but they must be able to start with a java.time.Duration as input.

  /** Encodes a [[java.time.Duration]] into a more readable format.
    *
    * @example
    * encodeDuration(Duration.ofDays(30).plusHours(3))  // returns "30 days, 3 hours"
    * encodeDuration(Duration.ofDays(1))                // returns "1 day"
    * encodeDuration(Duration.parse("PT720H"))          // returns "30 days"
    * encodeDuration(Duration.parse("PT12000H10S"))     // returns "1 year, 4 months, 15 days, 10 seconds"
    */
implicit val encodeDuration: Encoder[java.time.Duration] = (duration: Duration) => {
    val oneMinute = 60
    val twoMinutes = oneMinute * 2
    val oneHour = oneMinute * 60
    val twoHours = oneHour * 2
    val oneDay = oneHour * 24
    val twoDays = oneDay * 2
    val oneMonth = oneDay * 30
    val twoMonths = oneMonth * 2
    val oneYear = oneDay * 365
    val twoYears = oneYear * 2

    // scalastyle:off cyclomatic.complexity
    def encodeDuration(result: List[String], seconds: Long): List[String] = {

      seconds match {
        case seconds if seconds <= 0                                 =>
          List.empty[String]
        case seconds if seconds == 1                                 =>
          result ::: List(s"${seconds} second")
        case seconds if seconds < oneMinute                          =>
          result ::: List(s"${seconds} seconds")
        case seconds if seconds >= oneMinute && seconds < twoMinutes =>
          List(s"${seconds / oneMinute} minute") ::: encodeDuration(result, seconds % oneMinute)
        case seconds if seconds >= oneMinute && seconds < oneHour =>
          List(s"${seconds / oneMinute} minutes") ::: encodeDuration(result, seconds % oneMinute)
        case seconds if seconds >= oneHour && seconds < twoHours     =>
          List(s"${seconds / oneHour} hour") ::: encodeDuration(result, seconds % oneHour)
        case seconds if seconds >= twoHours && seconds < oneDay      =>
          List(s"${seconds / oneHour} hours") ::: encodeDuration(result, seconds % oneHour)
        case seconds if seconds >= oneDay && seconds < twoDays       =>
          List(s"${seconds / oneDay} day") ::: encodeDuration(result, seconds % oneDay)
        case seconds if seconds >= twoDays && seconds < oneMonth     =>
          List(s"${seconds / oneDay} days") ::: encodeDuration(result, seconds % oneDay)
        case seconds if seconds >= oneMonth && seconds < twoMonths   =>
          List(s"${seconds / oneMonth} month") ::: encodeDuration(result, seconds % oneMonth)
        case seconds if seconds >= twoMonths && seconds < oneYear    =>
          List(s"${seconds / oneMonth} months") ::: encodeDuration(result, seconds % oneMonth)
        case seconds if seconds >= oneYear && seconds < twoYears     =>
          List(s"${seconds / oneYear} year") ::: encodeDuration(result, seconds % oneYear)
        case seconds if seconds >= twoYears                          =>
          List(s"${seconds / oneYear} years") ::: encodeDuration(result, seconds % oneYear)
      }
    }
    // scalastyle:on cyclomatic.complexity

    Encoder.encodeString(encodeDuration(List.empty[String], duration.getSeconds).mkString(", "))
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM