Как рассчитать «время назад» в Java? - PullRequest
114 голосов
/ 05 октября 2010

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

Например:

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

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

Ответы [ 25 ]

3 голосов
/ 19 октября 2015

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

Из документов для

CharSequence getRelativeTimeSpanString (долгое время, долгое время,long minResolution)

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

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

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

3 голосов
/ 03 декабря 2015

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

 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 голосов
/ 05 мая 2016

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

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

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();
    }
}
3 голосов
/ 05 октября 2010

Пакет joda-time , имеет понятие Periods . Вы можете делать арифметику с Periods и DateTimes.

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

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = new  Period().withDays(2).withHours(12);
  return datetimeRented.plus(rentalPeriod).isBeforeNow();
}
2 голосов
/ 27 января 2018

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

2 голосов
/ 05 октября 2010

Это не красиво ... но самое близкое, что я могу вспомнить, это использование Joda-Time (как описано в этом посте: Как рассчитать прошедшее время с помощью Joda Time?

1 голос
/ 04 июня 2019

java.time

Ответ от Habsq имеет правильную идею, но неправильные методы.

Для промежутка времени, не привязанного к временной шкале в шкале лет-месяцев-дней, используйте 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 );

С: 2010-09-27 по: 2019-06-04

8 дней назад

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

8 лет назад


О java.time

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

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

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

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

Где получить классы java.time?

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

1 голос
/ 27 января 2016

для 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. Я получаю данные с сервера в формате Ср, 27 января 2016 09:32:35 GMT [это, вероятно, НЕ ваш случай]

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

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

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

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

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

1 голос
/ 11 сентября 2015

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

    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;
    }
}
0 голосов
/ 03 июня 2019

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

    /*
    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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...