Android default method to get date and times properly for 1 day and 1 hour

264 Views Asked by At

I have written if-else conditions for displaying date and time when it comes to 1 day, 1 hour, etc. I want to know whether there are any functions that would do that without adding these conditions. I am posting my code here

if(days.toInt() == 0 && hours.toInt() > 1)
            {
                result = "$hours hours"
            }
            else if(hours.toInt() == 0 && days.toInt() > 1)
            {
                result = "$days days"
            }
            else if(days.toInt() == 1 && hours.toInt() > 1)
            {
                result = "$days day $hours hours"
            }
            else if(hours.toInt() == 1 && days.toInt() > 1)
            {
                result = "$days days $hours hour"
            }
            else if(days.toInt() == 1 && hours.toInt() == 0)
            {
                result = "$days day"
            }
            else if(days.toInt() == 0 && hours.toInt() == 1)
            {
                result = "$hours hour"
            }
            else if(days.toInt() == 1 && hours.toInt() == 1)
            {
                result = "$days day $hours hour"
            }
            else if(hours.toInt() == 0 && days.toInt() ==0)
            {
                result = ""
            }
            else if(hours.toInt() > 1 && days.toInt() > 1)
            {
                result = "$days days $hours hours"
            }
            return result
3

There are 3 best solutions below

2
On

You can use the ICU MessageFormat from android.icu.text.MessageFormat (not the one from java.text). The syntax of the format string is described in http://userguide.icu-project.org/formatparse/messages

MessageFormat.format(
        "{days,plural,=1{# day} other {# days}}{hours,plural,=0{} =1{ # hour} other { # hours}}", mapOf<String, Any?>(
            "days" to 2,
            "hours" to 0
        ))

There is also RelativeDateTimeFormatter which you might want to look at, but that gives a slightly different English string than in your example.

 RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance();
 fmt.format(1, Direction.NEXT, RelativeUnit.DAYS); // "in 1 day"
0
On

I don't know if there are such functions, but you can make your if - else cascade a lot simpler, for example by defining this function

private String my_formatter(int val, String strPlaceholder) {
    String ret = "";
    if ( val == 1 )
            result = "1 " + strPlaceholder;
        else
            result = val + " " + strPlaceholder + "s";
    return ret;
}

and then you can just do like this

result = "";
if(days.toInt() > 0) {
    result = result + my_formatter(days.toInt(), "day");
}
if(hours.toInt() > 0) {
    result = result + my_formatter(hours.toInt(), "hour");
}
0
On

java.time

I recommend you do it using the modern date-time API:

import java.time.Duration;
import java.time.LocalDateTime;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(getDateTimeDifference("2020-12-20T20:20:50", "2020-12-23T17:10:40"));

    }

    static String getDateTimeDifference(String strStartDateTime, String strEndDateTime) {
        LocalDateTime startDateTime = LocalDateTime.parse(strStartDateTime);
        LocalDateTime endDateTime = LocalDateTime.parse(strEndDateTime);
        Duration duration = Duration.between(startDateTime, endDateTime);

        // #################### Since Java-8 ####################
        String formattedDurationJava8 = String.format("%d days %d hours %d minutes %d seconds", duration.toDays(),
                duration.toHours() % 24, duration.toMinutes() % 60, duration.toSeconds() % 60);
        System.out.println(formattedDurationJava8);
        // ######################################################

        // #################### Since Java-9 ####################
        String formattedDurationJava9 = String.format("%d days %d hours %d minutes %d seconds", duration.toDaysPart(),
                duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart());
        System.out.println(formattedDurationJava9);
        // ######################################################

        // return formattedDurationJava8;
        return formattedDurationJava9;
    }
}

Output:

2 days 20 hours 49 minutes 50 seconds
2 days 20 hours 49 minutes 50 seconds
2 days 20 hours 49 minutes 50 seconds

Some important notes:

  1. java.time.Duration is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementation. With Java-9 some more convenient methods were introduced.
  2. The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API. For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
  3. Learn about the modern date-time API from Trail: Date Time.