Parsing a Duration String in Kotlin

后端 未结 3 1857
终归单人心
终归单人心 2021-01-06 10:06

I\'m working on a Android application and I need to parse a duration string of this form \"00:00:00.000\" (Ex: \"00:00:38.47\" or \"00:03:27.11\").

My final goal is

相关标签:
3条回答
  • 2021-01-06 10:17
      val time = LocalTime.parse("00:01:08.83", DateTimeFormatter.ofPattern("HH:mm:ss.SS"))
    
      println(time.toSecondOfDay())
      println(time.toNanoOfDay())
      println(time.toNanoOfDay().toFloat() / 1_000_000_000)
    

    Output:

    68
    68830000000
    68.83
    
    0 讨论(0)
  • 2021-01-06 10:23

    The method getSeconds() that you use returns only the seconds of the parsed time and also it is deprecated.
    If you can't use LocalTime.parse() in your Android app because it requires API level 26, then split the time string and parse it by multiplying each part with the appropriate factor:

    val timeString = "00:01:08.83"
    val factors = arrayOf(3600.0, 60.0, 1.0, 0.01)
    var value = 0.0
    timeString.replace(".", ":").split(":").forEachIndexed { i, s -> value += factors[i] * s.toDouble() }
    println(value)
    

    will print:

    68.83
    

    You could also create an extension function:

    fun String.toSeconds(): Double {
        val factors = arrayOf(3600.0, 60.0, 1.0, 0.01)
        var value = 0.0
        this.replace(".", ":").split(":").forEachIndexed { i, s -> value += factors[i] * s.toDouble() }
        return value
    }
    

    and use it:

    val timeString = "00:01:08.83"
    val seconds = timeString.toSeconds()
    println(seconds)
    
    0 讨论(0)
  • 2021-01-06 10:28

    java.time.Duration

    As shown in the linked questions there are several ways to do this. I am afraid that there isn’t one objectively best way.

    You should most probably use a Duration from java.time, the modern Java date and time API, for your duration.

    Unfortunately there isn’t a way to parse your string directly into a Duration. My preference is for modifying your string into ISO 8601 format, the format that the Duration class knows how to parse. I trust you to translate my Java code into even more beautiful Kotlin code.

        String timeString = "00:01:08.83";
        String isoDurationString = timeString
                .replaceFirst("(\\d+):(\\d{2}):(\\d{2}(?:\\.\\d+)?)", "PT$1H$2M$3S");
        Duration dur = Duration.parse(isoDurationString);
        System.out.println(dur);
    

    Output from this snippet is:

    PT1M8.83S

    The regular expression is powerful but hard to read. The round brackets denote groups that I want to keep in the modified string; I refer to them as $1 etc. in the replacement string. (?:\\.\\d+) is a non-capturing group, one that I don’t need to use in the replacement. The ? after the non-capturing group says that it needs not be there (so the expression matches just 00:01:08 as well).

    For a percentage there are some options again. Duration objects can be directly multiplied by 100 and since Java 9 divided by each other. Assuming that you are not yet on Java 9, I would probably make the calculation based on milliseconds or nanoseconds (rather than seconds with a fraction). For example:

        long totalMilliseconds = dur.toMillis();
        System.out.println(totalMilliseconds);
    

    68830

    However to answer your question here’s how I would convert to seconds in a float:

        float totalSeconds = ((float) dur.toNanos()) / TimeUnit.SECONDS.toNanos(1);
        System.out.println(totalSeconds);
    

    68.83

    0 讨论(0)
提交回复
热议问题