Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java/Kotlin/Android - format time (hh:mm:ss) and remove unnecessary zeros from the beginning

My application displays time left in such format hh:mm:ss, for example, 01:05:45 what stands for one hour 5 minutes and 45 seconds.

When hours or minutes are zero I would like not to display them. Currently, if 45 seconds are remaining my timer will show '00:00:45'. The expected result is just '45'.

I need some kind of Java/Kotlin/Android method to produce the following outputs:

  • 1 hour 13 minutes and 10 seconds ==> 01:13:10
  • 0 hours 13 minutes and 10 seconds ==> 13:10
  • 3 hours 0 minutes and 16 seconds ==> 03:00:16
  • 0 hour 0 minutes and 5 seconds ==> 5

Currently I use such string as a formatter:

<string name="time_default_formatter" translatable="false">%02d:%02d:%02d</string>

I tried to manually replace string "00:" with "" but it fails when it comes to a 3rd example. Also, I think standard formatting should provide something like that but I keep failing to find it.

Edit: I can do it in code. The thing is I am looking for an elegant solution.

like image 832
Michał Powłoka Avatar asked Mar 07 '19 16:03

Michał Powłoka


2 Answers

String resources are meant for displaying actual text in a way that is easily localizable. They aren't meant for formatting dates and times; that's what DateUtils is for.

This class contains various date-related utilities for creating text for things like elapsed time and date ranges, strings for days of the week and months, and AM/PM text etc.

Which comes with a convenient formatElapsedTime() method that formats a duration as you would expect.

Formats an elapsed time in the form "MM:SS" or "H:MM:SS"…

Unfortunately the last format you mentioned (which only displays seconds) is fairly uncommon, therefore unsupported by DateUtils. Though this can be easily remedied with the following function.

fun formatDuration(seconds: Long): String = if (seconds < 60) {
    seconds.toString()
} else {
    DateUtils.formatElapsedTime(seconds)
}
like image 115
Bryan Avatar answered Oct 12 '22 09:10

Bryan


So far I haven't found any elegant in my opinion solution and I do it like that.

I have three formatting strings, one for each situation:

<string name="time_hours_minutes_seconds_formatter" translatable="false">%02d:%02d:%02d</string>
<string name="time_minutes_seconds_formatter" translatable="false">%02d:%02d</string>
<string name="time_seconds_formatter" translatable="false">%02d</string>

Then, manually I format it using function (in Kotlin):

    private fun formatTime(millis: Long): String {
    val hours = TimeUnit.MILLISECONDS.toHours(millis) % 24
    val minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % 60
    val seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % 60

    return when {
        hours == 0L && minutes == 0L -> String.format(
            resources.getString(R.string.time_seconds_formatter), seconds
        )

        hours == 0L && minutes > 0L -> String.format(
            resources.getString(R.string.time_minutes_seconds_formatter), minutes, seconds
        )

        else -> resources.getString(R.string.time_hours_minutes_seconds_formatter, hours, minutes, seconds)
    }
}
like image 41
Michał Powłoka Avatar answered Oct 12 '22 10:10

Michał Powłoka