Как посчитать «время назад» в Java?

127

В Ruby on Rails есть функция, которая позволяет вам взять любую дату и распечатать, "давно" она была.

Например:

8 minutes ago
8 hours ago
8 days ago
8 months ago
8 years ago

Есть ли простой способ сделать это на Java?

JTS
источник
1
См. Stackoverflow.com/questions/11/how-do-i-calculate-relative-time Это C #, но я уверен, что вы можете преобразовать его без особых проблем.
Брэндон,

Ответы:

177

Взгляните на библиотеку PrettyTime .

Использовать довольно просто:

import org.ocpsoft.prettytime.PrettyTime;

PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
// prints "moments ago"

Вы также можете передать локаль для интернационализированных сообщений:

PrettyTime p = new PrettyTime(new Locale("fr"));
System.out.println(p.format(new Date()));
// prints "à l'instant"

Как отмечено в комментариях, Android имеет эту функциональность, встроенную в android.text.format.DateUtilsкласс.

ataylor
источник
230
Если вы работаете над android, вы можете использовать это: android.text.format.DateUtils # getRelativeTimeSpanString ()
Somatik
Не могли бы вы добавить еще какое-то описание к своему ответу, ответ только по ссылке пока не подходит.
Ajay S,
@Somatik, если вам нужно получить это на платформе, отличной от Android, вы можете просмотреть этот класс на AOSP.
greg7gkb 05
@ataylor, как это использовать в Android ??
Hardik Parmar 02
getRelativeTimeSpanString не идеален для всех ситуаций, поэтому я создал свой собственный класс на основе множества примеров здесь. См. Мое решение ниже: stackoverflow.com/a/37042254/468360
Codeversed
67

Вы рассматривали перечисление TimeUnit ? Это может быть очень полезно для таких вещей

    try {
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        Date past = format.parse("01/10/2010");
        Date now = new Date();

        System.out.println(TimeUnit.MILLISECONDS.toMillis(now.getTime() - past.getTime()) + " milliseconds ago");
        System.out.println(TimeUnit.MILLISECONDS.toMinutes(now.getTime() - past.getTime()) + " minutes ago");
        System.out.println(TimeUnit.MILLISECONDS.toHours(now.getTime() - past.getTime()) + " hours ago");
        System.out.println(TimeUnit.MILLISECONDS.toDays(now.getTime() - past.getTime()) + " days ago");
    }
    catch (Exception j){
        j.printStackTrace();
    }
Бен Дж
источник
4
Я не думаю, что это полный ответ, поскольку единицы времени независимы. Например, время в миллисекундах - это всего лишь минуты * 60 * 1000. Вам нужно уменьшать с каждой единицы времени следующую большую единицу времени (после преобразования ее в меньшую единицу времени), чтобы иметь возможность использовать ее в «время назад». "строка.
Натив
@Benj - Это правильно? выше решение? потому что одно время указано в 12-часовом формате, а другое - в 24-часовом формате. Сообщите мне свой отзыв по моему запросу. Заранее благодарю.
Swift
это неверно, хотя ... каждая единица независима друг от друга, как уже упоминалось.
Джонатан Лалиберте
1
Android сделает это за вас. Если вы работаете над Android, вы можете использовать это: android.text.format.DateUtils.getRelativeTimeSpanString (миллисекунды)
Ваджид Али
50

Я беру ответы RealHowTo и Ben J и делаю свою версию:

public class TimeAgo {
public static final List<Long> times = Arrays.asList(
        TimeUnit.DAYS.toMillis(365),
        TimeUnit.DAYS.toMillis(30),
        TimeUnit.DAYS.toMillis(1),
        TimeUnit.HOURS.toMillis(1),
        TimeUnit.MINUTES.toMillis(1),
        TimeUnit.SECONDS.toMillis(1) );
public static final List<String> timesString = Arrays.asList("year","month","day","hour","minute","second");

public static String toDuration(long duration) {

    StringBuffer res = new StringBuffer();
    for(int i=0;i< TimeAgo.times.size(); i++) {
        Long current = TimeAgo.times.get(i);
        long temp = duration/current;
        if(temp>0) {
            res.append(temp).append(" ").append( TimeAgo.timesString.get(i) ).append(temp != 1 ? "s" : "").append(" ago");
            break;
        }
    }
    if("".equals(res.toString()))
        return "0 seconds ago";
    else
        return res.toString();
}
public static void main(String args[]) {
    System.out.println(toDuration(123));
    System.out.println(toDuration(1230));
    System.out.println(toDuration(12300));
    System.out.println(toDuration(123000));
    System.out.println(toDuration(1230000));
    System.out.println(toDuration(12300000));
    System.out.println(toDuration(123000000));
    System.out.println(toDuration(1230000000));
    System.out.println(toDuration(12300000000L));
    System.out.println(toDuration(123000000000L));
}}

который напечатает следующее

0 second ago
1 second ago
12 seconds ago
2 minutes ago
20 minutes ago
3 hours ago
1 day ago
14 days ago
4 months ago
3 years ago
Риккардо Касатта
источник
Очень круто. И действительно легко добавить другие единицы времени, такие как неделя (недели)
Петр
1
этот заслуживает большего количества голосов. Прежде всего, библиотека не нужна. Он по-прежнему чистый, элегантный и легко заменяется.
фанжж 06
небольшая опечатка: внутри кода вы ссылаетесь на статические свойства «Списки» вместо «TimeAgo». Lists.times.get (i) должно быть TimeAgo.get (i) ... и так далее
Диого Гомес,
2
Небольшое предложение: используйте .append(temp != 1 ? "s" : "")вместо, .append(temp > 1 ? "s" : "")потому что 0 также должен иметь sсуффикс
berkus
1
@ShajeelAfzal да, параметр длительности указывается в миллисекундах, но разница между временами не является абсолютной величиной. Вы получаете время, прошедшее с 1 января 1970 года, когда началась отметка времени unix
Риккардо Касатта,
42
  public class TimeUtils {

      public final static long ONE_SECOND = 1000;
      public final static long SECONDS = 60;

      public final static long ONE_MINUTE = ONE_SECOND * 60;
      public final static long MINUTES = 60;

      public final static long ONE_HOUR = ONE_MINUTE * 60;
      public final static long HOURS = 24;

      public final static long ONE_DAY = ONE_HOUR * 24;

      private TimeUtils() {
      }

      /**
       * converts time (in milliseconds) to human-readable format
       *  "<w> days, <x> hours, <y> minutes and (z) seconds"
       */
      public static String millisToLongDHMS(long duration) {
        StringBuffer res = new StringBuffer();
        long temp = 0;
        if (duration >= ONE_SECOND) {
          temp = duration / ONE_DAY;
          if (temp > 0) {
            duration -= temp * ONE_DAY;
            res.append(temp).append(" day").append(temp > 1 ? "s" : "")
               .append(duration >= ONE_MINUTE ? ", " : "");
          }

          temp = duration / ONE_HOUR;
          if (temp > 0) {
            duration -= temp * ONE_HOUR;
            res.append(temp).append(" hour").append(temp > 1 ? "s" : "")
               .append(duration >= ONE_MINUTE ? ", " : "");
          }

          temp = duration / ONE_MINUTE;
          if (temp > 0) {
            duration -= temp * ONE_MINUTE;
            res.append(temp).append(" minute").append(temp > 1 ? "s" : "");
          }

          if (!res.toString().equals("") && duration >= ONE_SECOND) {
            res.append(" and ");
          }

          temp = duration / ONE_SECOND;
          if (temp > 0) {
            res.append(temp).append(" second").append(temp > 1 ? "s" : "");
          }
          return res.toString();
        } else {
          return "0 second";
        }
      }


      public static void main(String args[]) {
        System.out.println(millisToLongDHMS(123));
        System.out.println(millisToLongDHMS((5 * ONE_SECOND) + 123));
        System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR));
        System.out.println(millisToLongDHMS(ONE_DAY + 2 * ONE_SECOND));
        System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR + (2 * ONE_MINUTE)));
        System.out.println(millisToLongDHMS((4 * ONE_DAY) + (3 * ONE_HOUR)
            + (2 * ONE_MINUTE) + ONE_SECOND));
        System.out.println(millisToLongDHMS((5 * ONE_DAY) + (4 * ONE_HOUR)
            + ONE_MINUTE + (23 * ONE_SECOND) + 123));
        System.out.println(millisToLongDHMS(42 * ONE_DAY));
        /*
          output :
                0 second
                5 seconds
                1 day, 1 hour
                1 day and 2 seconds
                1 day, 1 hour, 2 minutes
                4 days, 3 hours, 2 minutes and 1 second
                5 days, 4 hours, 1 minute and 23 seconds
                42 days
         */
    }
}

подробнее @ Форматировать продолжительность в миллисекундах в удобочитаемом формате

RealHowTo
источник
В итоге я использовал исправленную версию этого. Выложил для вас свои доработки.
Дэвид Блевинс
5
Дэвид Блевинс, другие примеры PrettyTime: stackoverflow.com/questions/3859288/… Большой -1 за изобретение колеса еще раз и не рекомендовать стороннюю библиотеку: -p
zakmck
9

Это основано на ответе RealHowTo, поэтому, если вам это нравится, подарите ему / ей тоже немного любви.

Эта очищенная версия позволяет вам указать диапазон времени, который может вас заинтересовать.

Он также обрабатывает часть «и» немного по-другому. Я часто замечаю, что при объединении строк с разделителем проще пропустить сложную логику и просто удалить последний разделитель, когда закончите.

import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

public class TimeUtils {

    /**
     * Converts time to a human readable format within the specified range
     *
     * @param duration the time in milliseconds to be converted
     * @param max      the highest time unit of interest
     * @param min      the lowest time unit of interest
     */
    public static String formatMillis(long duration, TimeUnit max, TimeUnit min) {
        StringBuilder res = new StringBuilder();

        TimeUnit current = max;

        while (duration > 0) {
            long temp = current.convert(duration, MILLISECONDS);

            if (temp > 0) {
                duration -= current.toMillis(temp);
                res.append(temp).append(" ").append(current.name().toLowerCase());
                if (temp < 2) res.deleteCharAt(res.length() - 1);
                res.append(", ");
            }

            if (current == min) break;

            current = TimeUnit.values()[current.ordinal() - 1];
        }

        // clean up our formatting....

        // we never got a hit, the time is lower than we care about
        if (res.lastIndexOf(", ") < 0) return "0 " + min.name().toLowerCase();

        // yank trailing  ", "
        res.deleteCharAt(res.length() - 2);

        //  convert last ", " to " and"
        int i = res.lastIndexOf(", ");
        if (i > 0) {
            res.deleteCharAt(i);
            res.insert(i, " and");
        }

        return res.toString();
    }
}

Небольшой код, чтобы дать ему вихрь:

import static java.util.concurrent.TimeUnit.*;

public class Main {

    public static void main(String args[]) {
        long[] durations = new long[]{
            123,
            SECONDS.toMillis(5) + 123,
            DAYS.toMillis(1) + HOURS.toMillis(1),
            DAYS.toMillis(1) + SECONDS.toMillis(2),
            DAYS.toMillis(1) + HOURS.toMillis(1) + MINUTES.toMillis(2),
            DAYS.toMillis(4) + HOURS.toMillis(3) + MINUTES.toMillis(2) + SECONDS.toMillis(1),
            DAYS.toMillis(5) + HOURS.toMillis(4) + MINUTES.toMillis(1) + SECONDS.toMillis(23) + 123,
            DAYS.toMillis(42)
        };

        for (long duration : durations) {
            System.out.println(TimeUtils.formatMillis(duration, DAYS, SECONDS));
        }

        System.out.println("\nAgain in only hours and minutes\n");

        for (long duration : durations) {
            System.out.println(TimeUtils.formatMillis(duration, HOURS, MINUTES));
        }
    }

}

Будет выведено следующее:

0 seconds
5 seconds 
1 day and 1 hour 
1 day and 2 seconds 
1 day, 1 hour and 2 minutes 
4 days, 3 hours, 2 minutes and 1 second 
5 days, 4 hours, 1 minute and 23 seconds 
42 days 

Again in only hours and minutes

0 minutes
0 minutes
25 hours 
24 hours 
25 hours and 2 minutes 
99 hours and 2 minutes 
124 hours and 1 minute 
1008 hours 

И на случай, если кому-то это понадобится, вот класс, который преобразует любую строку, подобную приведенной выше, обратно в миллисекунды . Это очень полезно для того, чтобы позволить людям указывать тайм-ауты для различных вещей в читаемом тексте.

Дэвид Блевинс
источник
9

есть простой способ сделать это:

допустим, вам нужно время 20 минут назад:

Long minutesAgo = new Long(20);
Date date = new Date();
Date dateIn_X_MinAgo = new Date (date.getTime() - minutesAgo*60*1000);

Это оно..

Мория
источник
1
В большинстве случаев вам нужен «умный» дисплей, т.е. вместо 5125 минут назад вы говорите x дней назад.
PhiLho
7

О встроенных решениях:

В Java нет встроенной поддержки форматирования относительного времени, также нет Java-8 и ее нового пакета. java.time . Если вам нужен только английский и ничего больше, тогда и только тогда может быть приемлемо собственное решение - см. Ответ @RealHowTo (хотя у него есть серьезный недостаток, заключающийся в том, что не учитывается часовой пояс для перевода мгновенных дельт в местное время единицы!). В любом случае, если вы хотите избежать домашних сложных обходных решений, особенно для других языков, вам понадобится внешняя библиотека.

В последнем случае рекомендую использовать свою библиотеку Time4J (или Time4A на Android). Он предлагает максимальную гибкость и максимальную мощность i18n . У класса net.time4j.PrettyTimeprintRelativeTime...(...) для этого есть семь методов . Пример использования тестовых часов в качестве источника времени:

TimeSource<?> clock = () -> PlainTimestamp.of(2015, 8, 1, 10, 24, 5).atUTC();
Moment moment = PlainTimestamp.of(2015, 8, 1, 17, 0).atUTC(); // our input
String durationInDays =
  PrettyTime.of(Locale.GERMAN).withReferenceClock(clock).printRelative(
    moment,
    Timezone.of(EUROPE.BERLIN),
    TimeUnit.DAYS); // controlling the precision
System.out.println(durationInDays); // heute (german word for today)

Другой пример использования в java.time.Instantкачестве ввода:

String relativeTime = 
  PrettyTime.of(Locale.ENGLISH)
    .printRelativeInStdTimezone(Moment.from(Instant.EPOCH));
System.out.println(relativeTime); // 45 years ago

Эта библиотека поддерживает в своей последней версии (v4.17) 80 языков, а также некоторые локали для конкретной страны (особенно для испанского, английского, арабского, французского). Данные i18n в основном основаны на последней версии CLDR v29 . Другими важными причинами, по которым следует использовать эту библиотеку, являются хорошая поддержка правил множественного числа (которые часто отличаются от английских в других регионах), сокращенный стиль формата (например, «1 секунду назад») и выразительные способы учета часовых поясов . Time4J знает даже о таких экзотических деталях, как дополнительные секунды при вычислении относительного времени (не очень важно, но формирует сообщение, относящееся к горизонту ожидания). Совместимость с Java-8существует благодаря легкодоступным методам преобразования для таких типов, как java.time.Instantили java.time.Period.

Есть ли недостатки? Только два.

  • Библиотека не маленькая (в том числе из-за большого хранилища i18n-данных).
  • API малоизвестен, поэтому знания и поддержка сообщества пока недоступны, в остальном прилагаемая документация является довольно подробной и всеобъемлющей.

(Компактные) альтернативы:

Если вы ищете решение меньшего размера и не нуждаетесь в таком большом количестве функций и готовы мириться с возможными проблемами качества, связанными с i18n-данными, тогда:

  • Я бы порекомендовал ocpsoft / PrettyTime (поддержка фактически 32 языков (скоро 34?), Подходящих для работы java.util.Dateтолько - см. Ответ @ataylor). Промышленный стандарт CLDR (от консорциума Unicode) с большим опытом сообщества, к сожалению, не является базой данных i18n, поэтому дальнейшие улучшения или улучшения данных могут занять некоторое время ...

  • Если вы используете Android, то вспомогательный класс android.text.format.DateUtils - это тонкая встроенная альтернатива (см. Другие комментарии и ответы здесь, с тем недостатком, что он не поддерживается годами и месяцами. И я уверен, что только мало кому нравится API-стиль этого вспомогательного класса.

  • Если вы поклонник Joda-Time, вы можете взглянуть на его класс PeriodFormat (поддержка 14 языков в версии v2.9.4, с другой стороны: Joda-Time, безусловно, тоже не компактный, поэтому я упоминаю его здесь только для полнота). Эта библиотека не является настоящим ответом, потому что относительное время вообще не поддерживается. Вам нужно будет как минимум добавить буквальное «назад» (и вручную удалить все нижние единицы из сгенерированных форматов списков - неудобно). В отличие от Time4J или Android-DateUtils, он не имеет специальной поддержки сокращений или автоматического переключения с относительного времени на представление абсолютного времени. Как и PrettyTime, он полностью зависит от неподтвержденного вклада частных членов Java-сообщества в его i18n-данные.

Мено Хохшильд
источник
5

Если вы ищете простые «Сегодня», «Вчера» или «x дней назад».

private String getDaysAgo(Date date){
    long days = (new Date().getTime() - date.getTime()) / 86400000;

    if(days == 0) return "Today";
    else if(days == 1) return "Yesterday";
    else return days + " days ago";
}
Думи Джей
источник
5

java.time

Использование фреймворка java.time, встроенного в Java 8 и новее.

LocalDateTime t1 = LocalDateTime.of(2015, 1, 1, 0, 0, 0);
LocalDateTime t2 = LocalDateTime.now();
Period period = Period.between(t1.toLocalDate(), t2.toLocalDate());
Duration duration = Duration.between(t1, t2);

System.out.println("First January 2015 is " + period.getYears() + " years ago");
System.out.println("First January 2015 is " + period.getMonths() + " months ago");
System.out.println("First January 2015 is " + period.getDays() + " days ago");
System.out.println("First January 2015 is " + duration.toHours() + " hours ago");
System.out.println("First January 2015 is " + duration.toMinutes() + " minutes ago");
habsq
источник
1
Эти Durationметоды сообщают всю продолжительность как общее количество часов и как общее количество минут. В Java 8 классу странным образом не хватало каких-либо методов для получения каждой части часа, минут и секунд. В Java 9 есть эти методы to…Part.
Basil
5

Основываясь на кучу ответов здесь, я создал следующее для своего варианта использования.

Пример использования:

String relativeDate = String.valueOf(
                TimeUtils.getRelativeTime( 1000L * myTimeInMillis() ));

import java.util.Arrays;
import java.util.List;

import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * Utilities for dealing with dates and times
 */
public class TimeUtils {

    public static final List<Long> times = Arrays.asList(
        DAYS.toMillis(365),
        DAYS.toMillis(30),
        DAYS.toMillis(7),
        DAYS.toMillis(1),
        HOURS.toMillis(1),
        MINUTES.toMillis(1),
        SECONDS.toMillis(1)
    );

    public static final List<String> timesString = Arrays.asList(
        "yr", "mo", "wk", "day", "hr", "min", "sec"
    );

    /**
     * Get relative time ago for date
     *
     * NOTE:
     *  if (duration > WEEK_IN_MILLIS) getRelativeTimeSpanString prints the date.
     *
     * ALT:
     *  return getRelativeTimeSpanString(date, now, SECOND_IN_MILLIS, FORMAT_ABBREV_RELATIVE);
     *
     * @param date String.valueOf(TimeUtils.getRelativeTime(1000L * Date/Time in Millis)
     * @return relative time
     */
    public static CharSequence getRelativeTime(final long date) {
        return toDuration( Math.abs(System.currentTimeMillis() - date) );
    }

    private static String toDuration(long duration) {
        StringBuilder sb = new StringBuilder();
        for(int i=0;i< times.size(); i++) {
            Long current = times.get(i);
            long temp = duration / current;
            if (temp > 0) {
                sb.append(temp)
                  .append(" ")
                  .append(timesString.get(i))
                  .append(temp > 1 ? "s" : "")
                  .append(" ago");
                break;
            }
        }
        return sb.toString().isEmpty() ? "now" : sb.toString();
    }
}
Codeversed
источник
Это очень полезно, большое спасибо.
Haya Akkad
4

Я создал простой порт Java timeago для подключаемого модуля jquery-timeago, который выполняет то, о чем вы просите.

TimeAgo time = new TimeAgo();
String minutes = time.timeAgo(System.currentTimeMillis() - (15*60*1000)); // returns "15 minutes ago"
Кевин Савики
источник
4

Если вы разрабатываете приложение для Android, оно предоставляет служебный класс DateUtils для всех таких требований. Взгляните на DateUtils # getRelativeTimeSpanString () служебный метод .

Из документации для

CharSequence getRelativeTimeSpanString (давно, давно, давно minResolution)

Возвращает строку, описывающую «время» как время относительно «сейчас». Промежутки времени в прошлом форматируются как «42 минуты назад». Промежутки времени в будущем форматируются как «Через 42 минуты».

Вы будете пролетая мимо , timestampкак время и , System.currentTimeMillis()как в настоящее время . minResolutionПозволяет определить минимальный TimeSpan сообщить.

Например, время, прошедшее через 3 секунды, будет отображаться как «0 минут назад», если для него установлено значение MINUTE_IN_MILLIS. Передайте одно из 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS и т. Д.

Рави Таплиял
источник
4

Вы можете использовать эту функцию для расчета времени назад

 private String timeAgo(long time_ago) {
        long cur_time = (Calendar.getInstance().getTimeInMillis()) / 1000;
        long time_elapsed = cur_time - time_ago;
        long seconds = time_elapsed;
        int minutes = Math.round(time_elapsed / 60);
        int hours = Math.round(time_elapsed / 3600);
        int days = Math.round(time_elapsed / 86400);
        int weeks = Math.round(time_elapsed / 604800);
        int months = Math.round(time_elapsed / 2600640);
        int years = Math.round(time_elapsed / 31207680);

        // Seconds
        if (seconds <= 60) {
            return "just now";
        }
        //Minutes
        else if (minutes <= 60) {
            if (minutes == 1) {
                return "one minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else if (hours <= 24) {
            if (hours == 1) {
                return "an hour ago";
            } else {
                return hours + " hrs ago";
            }
        }
        //Days
        else if (days <= 7) {
            if (days == 1) {
                return "yesterday";
            } else {
                return days + " days ago";
            }
        }
        //Weeks
        else if (weeks <= 4.3) {
            if (weeks == 1) {
                return "a week ago";
            } else {
                return weeks + " weeks ago";
            }
        }
        //Months
        else if (months <= 12) {
            if (months == 1) {
                return "a month ago";
            } else {
                return months + " months ago";
            }
        }
        //Years
        else {
            if (years == 1) {
                return "one year ago";
            } else {
                return years + " years ago";
            }
        }
    }

1) Здесь time_ago в микросекундах

Раджеш Тивари
источник
3

В пакете joda-time есть понятие периодов. . Вы можете выполнять арифметические операции с периодами и датами и временем.

Из документов :

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = new  Period().withDays(2).withHours(12);
  return datetimeRented.plus(rentalPeriod).isBeforeNow();
}
Пол Рубель
источник
2

Это лучший код с точки зрения производительности, он сокращает количество вычислений. Причина Минуты рассчитываются, только если количество секунд больше 60, а Часы рассчитываются, только если количество минут больше 60 и так далее ...

class timeAgo {

static String getTimeAgo(long time_ago) {
    time_ago=time_ago/1000;
    long cur_time = (Calendar.getInstance().getTimeInMillis())/1000 ;
    long time_elapsed = cur_time - time_ago;
    long seconds = time_elapsed;
   // Seconds
    if (seconds <= 60) {
        return "Just now";
    }
    //Minutes
    else{
        int minutes = Math.round(time_elapsed / 60);

        if (minutes <= 60) {
            if (minutes == 1) {
                return "a minute ago";
            } else {
                return minutes + " minutes ago";
            }
        }
        //Hours
        else {
            int hours = Math.round(time_elapsed / 3600);
            if (hours <= 24) {
                if (hours == 1) {
                    return "An hour ago";
                } else {
                    return hours + " hrs ago";
                }
            }
            //Days
            else {
                int days = Math.round(time_elapsed / 86400);
                if (days <= 7) {
                    if (days == 1) {
                        return "Yesterday";
                    } else {
                        return days + " days ago";
                    }
                }
                //Weeks
                else {
                    int weeks = Math.round(time_elapsed / 604800);
                    if (weeks <= 4.3) {
                        if (weeks == 1) {
                            return "A week ago";
                        } else {
                            return weeks + " weeks ago";
                        }
                    }
                    //Months
                    else {
                        int months = Math.round(time_elapsed / 2600640);
                        if (months <= 12) {
                            if (months == 1) {
                                return "A month ago";
                            } else {
                                return months + " months ago";
                            }
                        }
                        //Years
                        else {
                            int years = Math.round(time_elapsed / 31207680);
                            if (years == 1) {
                                return "One year ago";
                            } else {
                                return years + " years ago";
                            }
                        }
                    }
                }
            }
        }
    }

}

}
Асад Мирза
источник
1
Если вы работаете над android, вы можете использовать это: android.text.format.DateUtils.getRelativeTimeSpanString (миллисекунды)
Ваджид Али
2

java.time

В « Ответе Хабска » правильная идея, но неправильные методы.

Для промежутка времени, не привязанного к шкале времени в масштабе годы-месяцы-дни, используйте Period. Для дней, означающих 24-часовые отрезки времени, не связанные с календарем и часами-минутами-секундами, используйте Duration. Смешивание двух гамм редко имеет смысл.

Duration

Начните с получения текущего момента в формате UTC , используя Instantкласс.

Instant now = Instant.now();  // Capture the current moment as seen in UTC.
Instant then = now.minus( 8L , ChronoUnit.HOURS ).minus( 8L , ChronoUnit.MINUTES ).minus( 8L , ChronoUnit.SECONDS );
Duration d = Duration.between( then , now );

Создавайте текст для часов, минут и секунд.

// Generate text by calling `to…Part` methods.
String output = d.toHoursPart() + " hours ago\n" + d.toMinutesPart() + " minutes ago\n" + d.toSecondsPart() + " seconds ago";

Выгрузить в консоль.

System.out.println( "From: " + then + " to: " + now );
System.out.println( output );

От: 2019-06-04T11: 53: 55.714965Z до: 2019-06-04T20: 02: 03.714965Z

8 часов назад

8 минут назад

8 секунд назад

Period

Начните с получения текущей даты.

Часовой пояс имеет решающее значение при определении даты. В любой момент дата меняется в зависимости от зоны земного шара. Например, несколько минут после полуночи в Париже Франция - это новый день, в то время как в Монреаль-Квебеке все еще «вчера» .

Если часовой пояс не указан, JVM неявно применяет текущий часовой пояс по умолчанию. Это значение по умолчанию может измениться в любой момент. во время выполнения (!), Поэтому ваши результаты могут отличаться. Лучше явно указать желаемый / ожидаемый часовой пояс в качестве аргумента. Если критично, подтвердите зону у своего пользователя.

Укажите правильное время имя зоны в формате Continent/Region, например America/Montreal, Africa/Casablancaили Pacific/Auckland. Никогда не используйте аббревиатуру из 2-4 букв, например ESTили, ISTпоскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Воссоздайте дату восемь дней, месяцев и лет назад.

LocalDate then = today.minusYears( 8 ).minusMonths( 8 ).minusDays( 7 ); // Notice the 7 days, not 8, because of granularity of months. 

Рассчитайте прошедшее время.

Period p = Period.between( then , today );

Создайте цепочку из кусочков «давно назад».

String output = p.getDays() + " days ago\n" + p.getMonths() + " months ago\n" + p.getYears() + " years ago";

Выгрузить в консоль.

System.out.println( "From: " + then + " to: " + today );
System.out.println( output );

С: 27.09.2010 по: 04.06.2019

8 дней назад

8 месяцев назад

8 лет назад


Около java.time

Java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытеснять неприятные старые устаревшие классы даты и времени , такие как java.util.Date, Calendar, и SimpleDateFormat.

Чтобы узнать больше, см. Oracle Tutorial . И поищите в Stack Overflow множество примеров и объяснений. Спецификация - JSR 310 .

Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на классы java.time .

Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или новее. Нет необходимости в строках, нет необходимости в java.sql.*занятиях.

Где взять классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательной площадкой для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь , такие как Interval, YearWeek, YearQuarter, и более .

Василий Бурк
источник
Спасибо вам большое!
Ticherhaz 05
1

После долгих исследований я нашел это.

    public class GetTimeLapse {
    public static String getlongtoago(long createdAt) {
        DateFormat userDateFormat = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
        DateFormat dateFormatNeeded = new SimpleDateFormat("MM/dd/yyyy HH:MM:SS");
        Date date = null;
        date = new Date(createdAt);
        String crdate1 = dateFormatNeeded.format(date);

        // Date Calculation
        DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        crdate1 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(date);

        // get current date time with Calendar()
        Calendar cal = Calendar.getInstance();
        String currenttime = dateFormat.format(cal.getTime());

        Date CreatedAt = null;
        Date current = null;
        try {
            CreatedAt = dateFormat.parse(crdate1);
            current = dateFormat.parse(currenttime);
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Get msec from each, and subtract.
        long diff = current.getTime() - CreatedAt.getTime();
        long diffSeconds = diff / 1000;
        long diffMinutes = diff / (60 * 1000) % 60;
        long diffHours = diff / (60 * 60 * 1000) % 24;
        long diffDays = diff / (24 * 60 * 60 * 1000);

        String time = null;
        if (diffDays > 0) {
            if (diffDays == 1) {
                time = diffDays + "day ago ";
            } else {
                time = diffDays + "days ago ";
            }
        } else {
            if (diffHours > 0) {
                if (diffHours == 1) {
                    time = diffHours + "hr ago";
                } else {
                    time = diffHours + "hrs ago";
                }
            } else {
                if (diffMinutes > 0) {
                    if (diffMinutes == 1) {
                        time = diffMinutes + "min ago";
                    } else {
                        time = diffMinutes + "mins ago";
                    }
                } else {
                    if (diffSeconds > 0) {
                        time = diffSeconds + "secs ago";
                    }
                }

            }

        }
        return time;
    }
}
Хари Кришна Андхра-Прадеш
источник
1

Для Android Точно так же, как сказал Рави, но поскольку многие люди хотят просто скопировать и вставить , вот оно.

  try {
      SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
      Date dt = formatter.parse(date_from_server);
      CharSequence output = DateUtils.getRelativeTimeSpanString (dt.getTime());
      your_textview.setText(output.toString());
    } catch (Exception ex) {
      ex.printStackTrace();
      your_textview.setText("");
    }

Объяснение для людей, у которых больше времени

  1. Вы откуда-то получаете данные. Сначала вам нужно выяснить его формат.

Ex. Я получаю данные с сервера в формате Wed, 27 Jan 2016 09:32:35 GMT [это, вероятно, НЕ ваш случай]

это переведено на

SimpleDateFormat formatter = new SimpleDateFormat ("EEE, дд МММ гггг ЧЧ: мм: сс Z");

откуда я это знаю? Прочтите документацию здесь.

Затем, после того, как я его разбираю, я получаю свидание. эту дату я ввел в getRelativeTimeSpanString (без каких-либо дополнительных параметров я могу использовать по умолчанию минуты)

Вы получите исключение, если не определили правильную строку синтаксического анализа , что-то вроде: exception at the character 5 . Посмотрите на символ 5 и исправьте исходную строку синтаксического анализа. , Вы можете получить другое исключение. Повторяйте эти шаги, пока не получите правильную формулу.

OWADVL
источник
1
private const val SECOND_MILLIS = 1
private const val MINUTE_MILLIS = 60 * SECOND_MILLIS
private const val HOUR_MILLIS = 60 * MINUTE_MILLIS
private const val DAY_MILLIS = 24 * HOUR_MILLIS

object TimeAgo {

fun timeAgo(time: Int): String {

    val now = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())
    if (time > now || time <= 0) {
        return "in the future"
    }

    val diff = now - time
    return when {
        diff < MINUTE_MILLIS -> "Just now"
        diff < 2 * MINUTE_MILLIS -> "a minute ago"
        diff < 60 * MINUTE_MILLIS -> "${diff / MINUTE_MILLIS} minutes ago"
        diff < 2 * HOUR_MILLIS -> "an hour ago"
        diff < 24 * HOUR_MILLIS -> "${diff / HOUR_MILLIS} hours ago"
        diff < 48 * HOUR_MILLIS -> "yesterday"
        else -> "${diff / DAY_MILLIS} days ago"
    }
}

}

Вызов

val String = timeAgo (unixTimeStamp)

чтобы узнать время назад в Котлине

Дино Санни
источник
0

Вот моя реализация на Java этого

    public static String relativeDate(Date date){
    Date now=new Date();
    if(date.before(now)){
    int days_passed=(int) TimeUnit.MILLISECONDS.toDays(now.getTime() - date.getTime());
    if(days_passed>1)return days_passed+" days ago";
    else{
        int hours_passed=(int) TimeUnit.MILLISECONDS.toHours(now.getTime() - date.getTime());
        if(hours_passed>1)return days_passed+" hours ago";
        else{
            int minutes_passed=(int) TimeUnit.MILLISECONDS.toMinutes(now.getTime() - date.getTime());
            if(minutes_passed>1)return minutes_passed+" minutes ago";
            else{
                int seconds_passed=(int) TimeUnit.MILLISECONDS.toSeconds(now.getTime() - date.getTime());
                return seconds_passed +" seconds ago";
            }
        }
    }

    }
    else
    {
        return new SimpleDateFormat("HH:mm:ss MM/dd/yyyy").format(date).toString();
    }
  }
Джои Пинто
источник
0

меня устраивает

public class TimeDifference {
    int years;
    int months;
    int days;
    int hours;
    int minutes;
    int seconds;
    String differenceString;

    public TimeDifference(@NonNull Date curdate, @NonNull Date olddate) {

        float diff = curdate.getTime() - olddate.getTime();
        if (diff >= 0) {
            int yearDiff = Math.round((diff / (AppConstant.aLong * AppConstant.aFloat)) >= 1 ? (diff / (AppConstant.aLong * AppConstant.aFloat)) : 0);
            if (yearDiff > 0) {
                years = yearDiff;
                setDifferenceString(years + (years == 1 ? " year" : " years") + " ago");
            } else {
                int monthDiff = Math.round((diff / AppConstant.aFloat) >= 1 ? (diff / AppConstant.aFloat) : 0);
                if (monthDiff > 0) {
                    if (monthDiff > AppConstant.ELEVEN) {
                        monthDiff = AppConstant.ELEVEN;
                    }
                    months = monthDiff;
                    setDifferenceString(months + (months == 1 ? " month" : " months") + " ago");
                } else {
                    int dayDiff = Math.round((diff / (AppConstant.bFloat)) >= 1 ? (diff / (AppConstant.bFloat)) : 0);
                    if (dayDiff > 0) {
                        days = dayDiff;
                        if (days == AppConstant.THIRTY) {
                            days = AppConstant.TWENTYNINE;
                        }
                        setDifferenceString(days + (days == 1 ? " day" : " days") + " ago");
                    } else {
                        int hourDiff = Math.round((diff / (AppConstant.cFloat)) >= 1 ? (diff / (AppConstant.cFloat)) : 0);
                        if (hourDiff > 0) {
                            hours = hourDiff;
                            setDifferenceString(hours + (hours == 1 ? " hour" : " hours") + " ago");
                        } else {
                            int minuteDiff = Math.round((diff / (AppConstant.dFloat)) >= 1 ? (diff / (AppConstant.dFloat)) : 0);
                            if (minuteDiff > 0) {
                                minutes = minuteDiff;
                                setDifferenceString(minutes + (minutes == 1 ? " minute" : " minutes") + " ago");
                            } else {
                                int secondDiff = Math.round((diff / (AppConstant.eFloat)) >= 1 ? (diff / (AppConstant.eFloat)) : 0);
                                if (secondDiff > 0) {
                                    seconds = secondDiff;
                                } else {
                                    seconds = 1;
                                }
                                setDifferenceString(seconds + (seconds == 1 ? " second" : " seconds") + " ago");
                            }
                        }
                    }

                }
            }

        } else {
            setDifferenceString("Just now");
        }

    }

    public String getDifferenceString() {
        return differenceString;
    }

    public void setDifferenceString(String differenceString) {
        this.differenceString = differenceString;
    }

    public int getYears() {
        return years;
    }

    public void setYears(int years) {
        this.years = years;
    }

    public int getMonths() {
        return months;
    }

    public void setMonths(int months) {
        this.months = months;
    }

    public int getDays() {
        return days;
    }

    public void setDays(int days) {
        this.days = days;
    }

    public int getHours() {
        return hours;
    }

    public void setHours(int hours) {
        this.hours = hours;
    }

    public int getMinutes() {
        return minutes;
    }

    public void setMinutes(int minutes) {
        this.minutes = minutes;
    }

    public int getSeconds() {
        return seconds;
    }

    public void setSeconds(int seconds) {
        this.seconds = seconds;
    } }
Рахул
источник
0

Это самый простой сценарий. его легко импровизировать.
Результат: (XXX часов назад) или (XX дней назад / вчера / сегодня)

<span id='hourpost'></span>
,or
<span id='daypost'></span>

<script>
var postTime = new Date('2017/6/9 00:01'); 
var now = new Date();
var difference = now.getTime() - postTime.getTime();
var minutes = Math.round(difference/60000);
var hours = Math.round(minutes/60);
var days = Math.round(hours/24);

var result;
if (days < 1) {
result = "Today";
} else if (days < 2) {
result = "Yesterday";
} else {
result = days + " Days ago";
}

document.getElementById("hourpost").innerHTML = hours + "Hours Ago" ;
document.getElementById("daypost").innerHTML = result ;
</script>
Двипа Аранта
источник
0

для этого я сделал Just Now, seconds ago, min ago, hrs ago, days ago, weeks ago, months ago, years agoв этом примере, вы можете проанализировать дату, 2018-09-05T06:40:46.183Zтакую ​​или любую другую, как показано ниже

добавить значение ниже в string.xml

  <string name="lbl_justnow">Just Now</string>
    <string name="lbl_seconds_ago">seconds ago</string>
    <string name="lbl_min_ago">min ago</string>
    <string name="lbl_mins_ago">mins ago</string>
    <string name="lbl_hr_ago">hr ago</string>
    <string name="lbl_hrs_ago">hrs ago</string>
    <string name="lbl_day_ago">day ago</string>
    <string name="lbl_days_ago">days ago</string>
    <string name="lbl_lstweek_ago">last week</string>
    <string name="lbl_week_ago">weeks ago</string>
    <string name="lbl_onemonth_ago">1 month ago</string>
    <string name="lbl_month_ago">months ago</string>
    <string name="lbl_oneyear_ago" >last year</string>
    <string name="lbl_year_ago" >years ago</string>

код Java попробуйте ниже

  public String getFormatDate(String postTime1) {
        Calendar cal=Calendar.getInstance();
        Date now=cal.getTime();
        String disTime="";
        try {
            Date postTime;
            //2018-09-05T06:40:46.183Z
            postTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(postTime1);

            long diff=(now.getTime()-postTime.getTime()+18000)/1000;

            //for months
            Calendar calObj = Calendar.getInstance();
            calObj.setTime(postTime);
            int m=calObj.get(Calendar.MONTH);
            calObj.setTime(now);

            SimpleDateFormat monthFormatter = new SimpleDateFormat("MM"); // output month

            int mNow = Integer.parseInt(monthFormatter.format(postTime));

            diff = diff-19800;

            if(diff<15) { //below 15 sec

                disTime = getResources().getString(R.string.lbl_justnow);
            } else if(diff<60) {

                //below 1 min
                disTime= diff+" "+getResources().getString(R.string.lbl_seconds_ago);
            } else if(diff<3600) {//below 1 hr

                // convert min
                long temp=diff/60;

                if(temp==1) {
                    disTime= temp + " " +getResources().getString(R.string.lbl_min_ago);
                } else {
                    disTime = temp  + " " +getResources().getString(R.string.lbl_mins_ago);
                }
            } else if(diff<(24*3600)) {// below 1 day

                // convert hr
                long temp= diff/3600;
                System.out.println("hey temp3:"+temp);
                if(temp==1) {
                    disTime = temp  + " " +getResources().getString(R.string.lbl_hr_ago);
                } else {
                    disTime = temp + " " +getResources().getString(R.string.lbl_hrs_ago);
                }
            } else if(diff<(24*3600*7)) {// below week

                // convert days
                long temp=diff/(3600*24);
                if (temp==1) {
                    //  disTime = "\nyesterday";
                    disTime = temp + " " +getResources().getString(R.string.lbl_day_ago);
                } else {
                    disTime = temp + " " +getResources().getString(R.string.lbl_days_ago);
                }
            } else if(diff<((24*3600*28))) {// below month

                // convert week
                long temp=diff/(3600*24*7);
                if (temp <= 4) {

                    if (temp < 1) {
                        disTime = getResources().getString(R.string.lbl_lstweek_ago);
                    }else{
                        disTime = temp + " " + getResources().getString(R.string.lbl_week_ago);
                    }

                } else {
                    int diffMonth = mNow - m;
                    Log.e("count : ", String.valueOf(diffMonth));
                    disTime = diffMonth + " " + getResources().getString(R.string.lbl_month_ago);
                }
            }else if(diff<((24*3600*365))) {// below year

                // convert month
                long temp=diff/(3600*24*30);

                System.out.println("hey temp2:"+temp);
                if (temp <= 12) {

                    if (temp == 1) {
                        disTime = getResources().getString(R.string.lbl_onemonth_ago);
                    }else{
                        disTime = temp + " " + getResources().getString(R.string.lbl_month_ago);
                    }
                }

            }else if(diff>((24*3600*365))) { // above year

                // convert year
                long temp=diff/(3600*24*30*12);

                System.out.println("hey temp8:"+temp);

                if (temp == 1) {
                    disTime = getResources().getString(R.string.lbl_oneyear_ago);
                }else{
                    disTime = temp + " " + getResources().getString(R.string.lbl_year_ago);
                }
            }

        } catch(Exception e) {
            e.printStackTrace();
        }

        return disTime;
    }
OMIK
источник
Если вы работаете над Android, вы можете использовать это: android.text.format.DateUtils.getRelativeTimeSpanString (миллисекунды)
Ваджид Али
0

Вы можете использовать библиотеку Java RelativeDateTimeFormatter , она делает именно это:

RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance();
 fmt.format(1, Direction.NEXT, RelativeUnit.DAYS); // "in 1 day"
 fmt.format(3, Direction.NEXT, RelativeUnit.DAYS); // "in 3 days"
 fmt.format(3.2, Direction.LAST, RelativeUnit.YEARS); // "3.2 years ago"

 fmt.format(Direction.LAST, AbsoluteUnit.SUNDAY); // "last Sunday"
 fmt.format(Direction.THIS, AbsoluteUnit.SUNDAY); // "this Sunday"
 fmt.format(Direction.NEXT, AbsoluteUnit.SUNDAY); // "next Sunday"
 fmt.format(Direction.PLAIN, AbsoluteUnit.SUNDAY); // "Sunday"

 fmt.format(Direction.LAST, AbsoluteUnit.DAY); // "yesterday"
 fmt.format(Direction.THIS, AbsoluteUnit.DAY); // "today"
 fmt.format(Direction.NEXT, AbsoluteUnit.DAY); // "tomorrow"

 fmt.format(Direction.PLAIN, AbsoluteUnit.NOW); // "now"
mavesonzini
источник
1
Это библиотека Android, а не библиотека Java.
Madbreaks
0

Я использую Instant, Date и DateTimeUtils. Данные (дата), которые хранятся в базе данных в виде String, а затем конвертируются в Instant.

    /*
    This method is to display ago.
    Example: 3 minutes ago.
    I already implement the latest which is including the Instant.
    Convert from String to Instant and then parse to Date.
     */
    public String convertTimeToAgo(String dataDate) {
    //Initialize
    String conversionTime = null;
    String suffix = "Yang Lalu";
    Date pastTime;
    //Parse from String (which is stored as Instant.now().toString()
    //And then convert to become Date
    Instant instant = Instant.parse(dataDate);
    pastTime = DateTimeUtils.toDate(instant);

    //Today date
    Date nowTime = new Date();

    long dateDiff = nowTime.getTime() - pastTime.getTime();
    long second = TimeUnit.MILLISECONDS.toSeconds(dateDiff);
    long minute = TimeUnit.MILLISECONDS.toMinutes(dateDiff);
    long hour = TimeUnit.MILLISECONDS.toHours(dateDiff);
    long day = TimeUnit.MILLISECONDS.toDays(dateDiff);

    if (second < 60) {
        conversionTime = second + " Saat " + suffix;
    } else if (minute < 60) {
        conversionTime = minute + " Minit " + suffix;
    } else if (hour < 24) {
        conversionTime = hour + " Jam " + suffix;
    } else if (day >= 7) {
        if (day > 30) {
            conversionTime = (day / 30) + " Bulan " + suffix;
        } else if (day > 360) {
            conversionTime = (day / 360) + " Tahun " + suffix;
        } else {
            conversionTime = (day / 7) + " Minggu " + suffix;
        }
    } else if (day < 7) {
        conversionTime = day + " Hari " + suffix;
    }
    return conversionTime;
    }
Ticherhaz
источник
1
Вы используете ужасные старые классы времени и даты, которые несколько лет назад были вытеснены классами java.time .
Basil
@BasilBourque Я все еще не могу найти последний способ сделать это.
Ticherhaz
@BasilBourque Я добавил код, чтобы понять это. github.com/ticherhaz/tarikhmasa
Тихерхаз
0

Следующие решения созданы на чистой Java:

Вариант 1: без округления и только самый большой контейнер времени

Следующая функция будет отображать только самый большой контейнер времени, например, если истинное прошедшее время равно "1 month 14 days ago", эта функция будет только отображать "1 month ago". Эта функция также всегда будет округлять в меньшую сторону, поэтому время, эквивалентное, "50 days ago"будет отображаться как"1 month"

public String formatTimeAgo(long millis) {
        String[] ids = new String[]{"second","minute","hour","day","month","year"};

        long seconds = millis / 1000;
        long minutes = seconds / 60;
        long hours = minutes / 60;
        long days = hours / 24;
        long months = days / 30;
        long years = months / 12;

        ArrayList<Long> times = new ArrayList<>(Arrays.asList(years, months, days, hours, minutes, seconds));

        for(int i = 0; i < times.size(); i++) {
            if(times.get(i) != 0) {
                long value = times.get(i).intValue();

                return value + " " + ids[ids.length - 1 - i] + (value == 1 ? "" : "s") + " ago";
            }
        }

        return "0 seconds ago";
    }

Вариант 2: с округлением

Просто оберните контейнер времени, который вы хотите округлить, с помощью оператора Math.round (...), поэтому, если вы хотите округлить 50 daysдо 2 months, измените его long months = days / 30наlong months = Math.round(days / 30.0)

wdavies973
источник
1
Как показано в моем ответе, использовать Durationего to…Partметоды было бы намного проще .
Basil
0

Вот мой тестовый пример, надеюсь, он поможет:

    val currentCalendar = Calendar.getInstance()
    currentCalendar.set(2019, 6, 2, 5, 31, 0)

    val targetCalendar = Calendar.getInstance()
    targetCalendar.set(2019, 6, 2, 5, 30, 0)

    val diffTs = currentCalendar.timeInMillis - targetCalendar.timeInMillis
    val diffMins = TimeUnit.MILLISECONDS.toMinutes(diffTs)
    val diffHours = TimeUnit.MILLISECONDS.toHours(diffTs)
    val diffDays = TimeUnit.MILLISECONDS.toDays(diffTs)
    val diffWeeks = TimeUnit.MILLISECONDS.toDays(diffTs) / 7
    val diffMonths = TimeUnit.MILLISECONDS.toDays(diffTs) / 30
    val diffYears = TimeUnit.MILLISECONDS.toDays(diffTs) / 365

    val newTs = when {
        diffYears >= 1 -> "Years $diffYears"
        diffMonths >= 1 -> "Months $diffMonths"
        diffWeeks >= 1 -> "Weeks $diffWeeks"
        diffDays >= 1 -> "Days $diffDays"
        diffHours >= 1 -> "Hours $diffHours"
        diffMins >= 1 -> "Mins $diffMins"
        else -> "now"
    }
David_Wang
источник
1
Ужасный Calendarкласс был вытеснен много лет назад современными классами java.time с принятием JSR 310 . Плохой совет в 2019 году.
Бэзил Бурк,
Вы, должно быть var, имели в виду , что нет val.
Basil
0

Функция getrelativeDateTime предоставит вам дату и время, как вы видите в уведомлении WhatsApp.
Чтобы получить будущую относительную дату и время, добавьте для нее условия. Это создано специально для получения даты и времени, например уведомления WhatsApp.

private static String getRelativeDateTime(long date) {
    SimpleDateFormat DateFormat = new SimpleDateFormat("MMM dd, yyyy", Locale.getDefault());
    SimpleDateFormat TimeFormat = new SimpleDateFormat(" hh:mm a", Locale.getDefault());
    long now = Calendar.getInstance().getTimeInMillis();
    long startOfDay = StartOfDay(Calendar.getInstance().getTime());
    String Day = "";
    String Time = "";
    long millSecInADay = 86400000;
    long oneHour = millSecInADay / 24;
    long differenceFromNow = now - date;

    if (date > startOfDay) {
        if (differenceFromNow < (oneHour)) {
            int minute = (int) (differenceFromNow / (60000));
            if (minute == 0) {
                int sec = (int) differenceFromNow / 1000;
                if (sec == 0) {
                    Time = "Just Now";
                } else if (sec == 1) {
                    Time = sec + " second ago";
                } else {
                    Time = sec + " seconds ago";
                }
            } else if (minute == 1) {
                Time = minute + " minute ago";
            } else if (minute < 60) {
                Time = minute + " minutes ago";
            }
        } else {
            Day = "Today, ";
        }
    } else if (date > (startOfDay - millSecInADay)) {
        Day = "Yesterday, ";
    } else if (date > (startOfDay - millSecInADay * 7)) {
        int days = (int) (differenceFromNow / millSecInADay);
        Day = days + " Days ago, ";
    } else {
        Day = DateFormat.format(date);
    }
    if (Time.isEmpty()) {
        Time = TimeFormat.format(date);
    }
    return Day + Time;
}

public static long StartOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return calendar.getTimeInMillis();
}
Сумит Сингх
источник
Спасибо за желание внести свой вклад. Это не совсем то, о чем просили, но, возможно, кому-то это пригодится. Однако ни тот, ни кто-либо другой не должны захотеть использовать SimpleDateFormatand Calendar. Эти классы плохо спроектированы и давно устарели. Вместо этого прочтите ответы, в которых используется java.time, современный API даты и времени Java.
Оле В.В.
0

Из-за отсутствия простоты и обновленного ответа следует за более поздней версией Java 8 и выше.

import java.time.*;
import java.time.temporal.*;

public class Time {
    public static void main(String[] args) {

        System.out.println(LocalTime.now().minus(8, ChronoUnit.MINUTES));
        System.out.println(LocalTime.now().minus(8, ChronoUnit.HOURS));
        System.out.println(LocalDateTime.now().minus(8, ChronoUnit.DAYS));
        System.out.println(LocalDateTime.now().minus(8, ChronoUnit.MONTHS));
    }
}

Это версия, которая использует API времени Java, который пытается решить проблемы прошлого для работы с датой и временем.

Javadoc

версия 8 https://docs.oracle.com/javase/8/docs/api/index.html?java/time/package-summary.html

версия 11 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html

Учебное пособие по W3Schools - https://www.w3schools.com/java/java_date.asp

Статья DZone - https://dzone.com/articles/java-8-date-and-time

brunocrt
источник