Разбор строки продолжительности в Kotlin - PullRequest
2 голосов
/ 02 ноября 2019

Я работаю над приложением для Android, и мне нужно проанализировать строку продолжительности этого вида "00: 00: 00.000" (например: "00: 00: 38.47" или "00: 03: 27.11").

Моя конечная цель - преобразовать эту строку в удвоенную долю секунды с миллисекундами, чтобы получить процент прогресса.

Я уже изучал SimpleDateFormatter, но у меня возникли некоторые проблемы с пониманием, как это работаетили как я должен это использовать.

Я пробовал это:

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

Так есть ли простой / эффективный способ сделать это?

Ответы [ 3 ]

3 голосов
/ 02 ноября 2019
  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)

Выход:

68
68830000000
68.83
1 голос
/ 03 ноября 2019

java.time.Duration

Как показано в связанных вопросах, есть несколько способов сделать это. Боюсь, что не существует одного объективно лучшего способа.

Скорее всего, вы должны использовать Duration из java.time, современного API даты и времени Java, для своей продолжительности.

К сожалению, нет способа проанализировать вашу строку непосредственно в Duration. Я предпочитаю модифицировать вашу строку в формате ISO 8601 , формате, который класс Duration знает, как анализировать. Я верю, что вы переведете мой Java-код в еще более красивый код Kotlin.

    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);

Вывод этого фрагмента:

PT1M8.83S

Регулярное выражение мощно, но трудно читать. Круглые скобки обозначают группы, которые я хочу сохранить в измененной строке;Я называю их $1 и т. Д. В строке замены. (?:\\.\\d+) - это группа без захвата , которую мне не нужно использовать при замене. ? после группы без захвата говорит, что его там не должно быть (поэтому выражение также совпадает только с 00:01:08).

Для процента снова есть некоторые опции. Duration объекты могут быть непосредственно умножены на 100, а Java 9 делится друг на друга. Предполагая, что вы еще не работаете на Java 9, я бы, вероятно, сделал расчет на основе миллисекунд или наносекунд (а не секунд с дробью). Например:

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

68830

Однако, чтобы ответить на ваш вопрос, вот как я бы преобразовал в секунды в float:

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

68,83

0 голосов
/ 02 ноября 2019

Используемый вами метод getSeconds() возвращает только секунды анализируемого времени, а также он устарел. Если вы не можете использовать LocalTime.parse() в своем приложении для Android, поскольку оно требует API-уровень 26 , то разбейте временную строку и проанализируйте ее, умножив каждую часть на соответствующий коэффициент:

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)

напечатает:

68.83

Вы также можете создать функцию расширения:

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
}

и использовать ее:

val timeString = "00:01:08.83"
val seconds = timeString.toSeconds()
println(seconds)
...