问题
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 to convert this string into a double of total seconds with milliseconds to get a progression percent.
I already looked into SimpleDateFormatter, but I'm having some issue understanding how it works or how I'm supposed to use it.
I've tried this:
val timeString = "00:01:08.83"
val df = SimpleDateFormat("HH:mm:ss.SS")
df.parse(timeString)?.seconds!!.toFloat() // Returns 8.00, I want to have 68.83 for this example string
So is there a simple/efficient way of doing this ?
回答1:
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
回答2:
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
回答3:
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)
来源:https://stackoverflow.com/questions/58670865/parsing-a-duration-string-in-kotlin