0

This is how I call getTimeBetween function:

getTimeBetween(ZonedDateTime.now().minusHours(4).minusMinutes(1).minusSeconds(40), ZonedDateTime.now());

And I expect this output:

4 hours, 1 minute, 40 seconds ago

This is my getTimeBetween function:

private String getTimeBetween(ZonedDateTime zonedDateTime1, ZonedDateTime zonedDateTime2) {
    Duration timeDifference = Duration.between(zonedDateTime1, zonedDateTime2);
    if (timeDifference.getSeconds() == 0) return "now";
    String timeDifferenceAsPrettyString = "";
    Boolean putComma = false;
    if (timeDifference.toDays() > 0) {
        if (timeDifference.toDays() == 1) timeDifferenceAsPrettyString += timeDifference.toDays() + " day";
        else timeDifferenceAsPrettyString += timeDifference.toDays() + " days";
        putComma = true;
    }
    if (timeDifference.toHours() > 0) {
        if (putComma) timeDifferenceAsPrettyString += ", ";
        if (timeDifference.toHours() == 1) timeDifferenceAsPrettyString += timeDifference.toHours() + " hour";
        else timeDifferenceAsPrettyString += timeDifference.toHours() % 24 + " hours";
        putComma = true;
    }
    if (timeDifference.toMinutes() > 0) {
        if (putComma) timeDifferenceAsPrettyString += ", ";
        if (timeDifference.toMinutes() == 1) timeDifferenceAsPrettyString += timeDifference.toMinutes() + " minute";
        else timeDifferenceAsPrettyString += timeDifference.toMinutes() % 60 + " minutes";
        putComma = true;
    }
    if (timeDifference.getSeconds() > 0) {
        if (putComma) timeDifferenceAsPrettyString += ", ";
        if (timeDifference.getSeconds() == 1) timeDifferenceAsPrettyString += timeDifference.getSeconds() + " second";
        else timeDifferenceAsPrettyString += timeDifference.getSeconds() % 60 + " seconds";
    }
    timeDifferenceAsPrettyString += " ago";
    return timeDifferenceAsPrettyString;
}

This function works as expected but is it really necessary to do it like this? Perhaps there is a better way to achieve this?

I'm using Java 8.

Defozo
  • 2,946
  • 6
  • 32
  • 51
  • Better ways: 1) Use `StringBuilder`. 2) Refactor common code to helper method, i.e. the four `if` statements. – Andreas Jan 03 '17 at 15:45

1 Answers1

1

How about this?

static String getTimeBetween(ZonedDateTime from, ZonedDateTime to) {
    StringBuilder builder = new StringBuilder();
    long epochA = from.toEpochSecond(), epochB = to.toEpochSecond();
    long secs = Math.abs(epochB - epochA);
    if (secs == 0) return "now";
    Map<String, Integer> units = new LinkedHashMap<>();
    units.put("day", 86400);
    units.put("hour", 3600);
    units.put("minute", 60);
    units.put("second", 1);
    boolean separator = false;
    for (Map.Entry<String, Integer> unit : units.entrySet()) {
        if (secs >= unit.getValue()) {
            long count = secs / unit.getValue();
            if (separator) builder.append(", ");
            builder.append(count).append(' ').append(unit.getKey());
            if (count != 1) builder.append('s');
            secs %= unit.getValue();
            separator = true;
        }
    }
    return builder.append(epochA > epochB ? " ago" : " in the future").toString();
}

You could probably store the LinkedHashMap instead of instantiating it every method call, but this should work.

Salem
  • 13,516
  • 4
  • 51
  • 70
  • Thank you for your answer. It's very helpful. BTW I think " ago" and " in the future" should be swapped. – Defozo Jan 03 '17 at 22:54
  • @Defozo That was intended - if the `from` date is before the `to` date the `to` date must be in the future. I guess you could swap the parameters :P – Salem Jan 04 '17 at 08:45