All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.playtika.testcontainer.common.utils.DateUtils Maven / Gradle / Ivy

The newest version!
package com.playtika.testcontainer.common.utils;


import org.springframework.util.StringUtils;

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;

/**
 * Convert ISO timestamps to human-readable relative times
 */
public class DateUtils {

    /**
     * @param isoFormattedDate ISO timestamp {@code "2021-12-31T23:59:59.123456789+18:00"}
     * @return Combine original timestamp at local time zone truncated to seconds and human-readable relative time: {@code "2021-12-31T07:59:59+02:00 (1 year 2 months ago)"}
     * @see #toTimeAgo(String)
     */
    public static String toDateAndTimeAgo(String isoFormattedDate) {
        Object instantOrString = parseToInstantOrString(isoFormattedDate);
        if (!(instantOrString instanceof Instant)) {
            return (String) instantOrString;
        }
        Instant instant = ((Instant) instantOrString);
        OffsetDateTime offsetDateTime = ((Instant) instantOrString).atZone(ZoneId.systemDefault()).toOffsetDateTime();
        return offsetDateTime + " (" + toTimeAgo(instant.toEpochMilli()) + ")";
    }

    /**
     * @param isoFormattedDate ISO timestamp {@code "2021-12-31T23:59:59.123456789+18:00"}
     * @return human-readable relative time: {@code "1 year 2 months ago"}
     * @see #toTimeAgo(long)
     */
    public static String toTimeAgo(String isoFormattedDate) {
        Object instantOrString = parseToInstantOrString(isoFormattedDate);
        return instantOrString instanceof Instant ? toTimeAgo(((Instant) instantOrString)
            .toEpochMilli()) : (String) instantOrString;
    }

    /**
     * @param isoFormattedDate ISO timestamp {@code "2021-12-31T23:59:59.123456789+18:00"}
     * @return 
    *
  • Successfully parsed Instant object at UTC time zone truncated to seconds, i.e. {@code "2021-12-31T05:59:59Z"}
  • *
  • {@code null} if isoFormattedDate is {@code null}
  • *
  • {@code ""} empty string if isoFormattedDate is blank
  • *
  • String containing the DateTimeParseException error message if isoFormattedDate is invalid
  • *
* @see DateTimeFormatter#parse(CharSequence) * @see Instant#from(TemporalAccessor) */ static Object parseToInstantOrString(String isoFormattedDate) { if (isoFormattedDate == null) { return null; } if (!StringUtils.hasText(isoFormattedDate)) { return ""; } try { return Instant.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(isoFormattedDate)) .with(ChronoField.NANO_OF_SECOND, 0); } catch (DateTimeParseException e) { return e.getMessage(); } } /** *

Thresholds are 60 seconds, 50 minutes, 20 hours, 3 weeks, 10 months.
* Everything else is rounded (1.5 becomes 2).
* Surplus months except 1 are not rounded (1 year 2 months ago).
* 1 month are 30.42 days. *

    *
  • {@literal <}= 89 seconds: a minute ago
  • *
  • {@literal <}= 50 minutes: 50 minutes ago
  • *
  • {@literal <}= 89 minutes: an hour ago
  • *
  • {@literal <}= 20 hours: 20 hours ago
  • *
  • {@literal <}= 35 hours: yesterday
  • *
  • {@literal <}= 5 days: 5 days ago
  • *
  • {@literal <}= 10 days: a week ago
  • *
  • {@literal <}= 24 days: 3 weeks ago
  • *
  • {@literal <}= 45 days: a month ago
  • *
  • {@literal <}= 10 months: 10 months ago
  • *
  • {@literal <}= 13 months: a year ago
  • *
  • == 14 months: 1 year 2 months ago
  • *
  • == 23 months: 1 year 11 months ago
  • *
*
     *  0 sec = a minute ago
     * 89 sec = a minute ago
     * 90 sec = 2 minutes ago
     * 50 min = 50 minutes ago
     * 51 min = an hour ago
     * 89 min = an hour ago
     * 90 min = 2 hours ago
     * 20 hrs = 20 hours ago
     * 21 hrs = yesterday
     * 35 hrs = yesterday
     * 36 hrs = 2 days ago
     *  5 day = 5 days ago
     *  6 day = a week ago
     * 10 day = a week ago
     * 11 day = 2 weeks ago
     * 17 day = 2 weeks ago
     * 18 day = 3 weeks ago
     * 24 day = 3 weeks ago
     * 25 day = a month ago
     * 45 day = a month ago
     * 46 day = 2 months ago
     * 10 mon = 10 months ago
     * 11 mon = a year ago
     * 13 mon = a year ago
     * 14 mon = 1 year 2 months ago
     * 23 mon = 1 year 11 months ago
     * 25 mon = 2 years ago
     * 26 mon = 2 years 2 months ago
     * 
*

* * @param epochMillis Unix time in milliseconds (since 1970-01-01) * @return human readable relative time: {@code "1 year 2 months ago"} */ public static String toTimeAgo(long epochMillis) { long seconds = Instant.now().toEpochMilli() / 1000 - (epochMillis / 1000); long minutes = Math.round(seconds / 60.0); if (minutes <= 50) { return minutes <= 1 ? "a minute ago" : minutes + " minutes ago"; } long hours = Math.round(seconds / 3600.0); if (hours <= 20) { return hours == 1 ? "an hour ago" : hours + " hours ago"; } long days = Math.round(seconds / 86400.0); if (days <= 5) { return days <= 1 ? "yesterday" : days + " days ago"; } long weeks = Math.round(seconds / 604800.0); if (weeks <= 3) { return weeks <= 1 ? "a week ago" : weeks + " weeks ago"; } long months = Math.round(seconds / 2628288.0); // 30.42 days per month if (months <= 10) { return months <= 1 ? "a month ago" : months + " months ago"; } long years = months / 12; // 11 -> 0, 23 -> 1 months = months % 12; return months <= 1 || years == 0 ? ((years <= 1 ? "a year" : years + " years") + " ago") : years + ((years <= 1 ? " year " : " years ") + months + " months ago"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy