0

I currently have this code:

public static String getTimeAgo(OffsetDateTime dateArg) {
    Instant instantNow = Instant.now();
    Instant instantThen = dateArg.toInstant();
    Duration comparedDuration = Duration.between(instantThen, instantNow);

    LocalDate localDate = dateArg.toLocalDate();
    LocalDate localDateToday = LocalDate.now(ZoneId.systemDefault());
    Period comparedPeriod = Period.between(localDate, localDateToday);

    ZonedDateTime zdt1 = ZonedDateTime.ofInstant(instantThen, ZoneId.systemDefault());
    ZonedDateTime zdt2 = ZonedDateTime.ofInstant(instantNow, ZoneId.systemDefault());
    Calendar calendarFetched = GregorianCalendar.from(zdt1);
    Calendar calendarNow = GregorianCalendar.from(zdt2);

    Instant d1i = Instant.ofEpochMilli(calendarFetched.getTimeInMillis());
    Instant d2i = Instant.ofEpochMilli(calendarNow.getTimeInMillis());

    LocalDateTime startDateWeek = LocalDateTime.ofInstant(d1i, ZoneId.systemDefault());
    LocalDateTime endDateWeek = LocalDateTime.ofInstant(d2i, ZoneId.systemDefault());

    long weeksCalc = ChronoUnit.WEEKS.between(startDateWeek, endDateWeek);


    String s = "";
    if(comparedPeriod.getYears() > 0) {
        s += comparedPeriod.getYears() + " year" + ((comparedPeriod.getYears() == 1) ? " " : "s ");
    }

    if(weeksCalc > 4){
        s += comparedPeriod.getMonths() + " month" + ((comparedPeriod.getMonths() == 1) ? " " : "s ");

    }
    else{
        s += weeksCalc + " weeks ";

    }

    if (comparedPeriod.getDays() > 0){
        s += comparedPeriod.getDays() + " day" + ((comparedPeriod.getDays() == 1) ? " " : "s ");
    }

    if (comparedDuration.toHoursPart() > 0) {
        s += comparedDuration.toHoursPart() + " hour" + ((comparedDuration.toHoursPart() == 1) ? " " : "s ");
    }
    else{
        if(comparedDuration.toMinutesPart() > 0){
            s += comparedDuration.toMinutesPart() + " minute" + ((comparedDuration.toMinutesPart() == 1) ? " " : "s ");
        }

        else s += comparedDuration.toSecondsPart() + " seconds "; // lol lets just end it here...
    }

    return s + "ago";
}

The goal is to display "time ago" based off from given OffsetDateTime argument. This is to show the year, month, weeks, days, hours, minutes, all the way down to seconds, if said time units were not at 0. But I am having trouble calculating the month as the result always come back as 0, while having an "s" indicating that it is not truly 0.

For example, running System.out.println(Utils.getTimeAgo(OffsetDateTime.parse("2020-12-13T15:54:43.971273200-05:00"))) displays 1 year 0 months 1 hour ago as its output...

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
uriri
  • 25
  • 5
  • 3
    You should drop `Calendar` immediately. You are already using the newer Java Date and Time API available in `java.time`. – MC Emperor Dec 13 '21 at 22:18

1 Answers1

2

If you think on it, you’ll realize that rarely does it make sense to represent a span of time as a combination of years-months-days-hours-minutes-seconds.

That is why java.time splits out the scales into two separate classes:

  • Period years-months-days
  • Duration hours-minutes-seconds

org.threeten.extra.PeriodDuration

If you insist on combing the two scales, I suggest adding the ThreeTen-Extra library to your project. This provides the PeriodDuration class.

OffsetDateTime odtThen = … ;
OffsetDateTime odtNow = OffsetDateTime.now( odtThen.getOffset() ) ;
PeriodDuration pd = PeriodDuration.between( odtThen, odtNow ) ;

Interrogate to obtain each part. One way to do that is to loop on the list returned from PeriodDuration#getUnits.


As commented, stop using Calendar class. Along with Date & SimpleDateFormat, these terrible date-time classes were entirely supplanted by the java.time classes defined in JSR 310.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154