Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

287
Views
Kotlin conditional formatting string

I have three variables :

val months: Long
val days: Long
val hours: Long

and I want to return something like this :

3 months, 2 days and 5 hours

Now this would simply translate to as :

val str = "$months months, $days days and $hours hours"

And if my months had to be 0 and days as 1 and hours as 0 then it will come like '0 months, 1 days and 0 hours'

But what I am looking for is "1 days" instead. How can I get it done?

I can definitely use some sort of conditional StringBuilder to get this done, but is there something better and elegant?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

How does this look to you?

fun formatTime(months: Long, days: Long, hours: Long): String =
  listOf(
    months to "months",
    days to "days",
    hours to "hours"
  )
  .filter { (length,_) -> length > 0L }
  // You can add an optional map predicate to make singular and plurals
  .map { (amount, label) -> amount to if(abs(amount)==1L) label.replace("s", "") else label }
  .joinToString(separator=", ") { (length, label) -> "$length $label" }
  .addressLastItem()

fun String.addressLastItem() =
  if(this.count { it == ','} >= 1) 
    // Dirty hack to get it working quickly
    this.reversed().replaceFirst(" ,", " dna ").reversed() 
  else 
    this

You can see it working over here

over 4 years ago · Santiago Trujillo Report

0

Another variant without replacing, counting or reversing the list:

fun formatTime(months: Long, days: Long, hours: Long): String {
  val list = listOfNotNull(
    months.formatOrNull("month", "months"),
    days.formatOrNull("day", "days"),
    hours.formatOrNull("hour", "hours"),
  )
  return if (list.isEmpty()) "all values <= 0"
  else
    listOfNotNull(
      list.take(list.lastIndex).joinToString().takeIf(String::isNotEmpty),
      list.lastOrNull()
    ).joinToString(" and ")
}

fun Long.formatOrNull(singular: String, plural: String = "${singular}s") = when {
  this == 1L -> "$this $singular"
  this > 1L -> "$this $plural"
  else -> null
}

It also has a fallback if all values are <= 0... you could also just use an empty string or whatever you prefer.

If you do not like that there are intermediate lists created to concatenate the string, you may also just use something as follows instead in the else path:

list.iterator().run {
  buildString {
    while (hasNext()) {
      val part = next()
      if (length > 0)
        if (hasNext())
          append(", ")
        else
          append(" and ")
      append(part)
    }
  }
}
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!