Как вычислить "время назад" в Java: гуманитарный формат даты

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Java 8 предлагает API java.time, который позволяет определить интервал времени, пройденный с некоторой точки времени, на основании экземпляров LocalDateTime:

Java
Скопировать код
LocalDateTime past = LocalDateTime.of(2023, 1, 1, 8, 30); // Указываем нужную дату в прошлом
Duration duration = Duration.between(past, LocalDateTime.now()); // Производим вычисления
String timeAgo = duration.toDays() > 0 ? duration.toDays() + " дня назад" :
                 duration.toHours() > 0 ? duration.toHours() + " часа назад" :
                 duration.toMinutes() > 0 ? duration.toMinutes() + " минуты назад" :
                 duration.getSeconds() + " секунд назад";
System.out.println(timeAgo); // Выводим готовый текст

В результате мы получим строку, отражающую сколько времени прошло с указанного момента, в форме "2 дня назад" или "10 минут назад".

Кинга Идем в IT: пошаговый план для смены профессии

Грамматические правила: обработка единственного и множественного числа

Необходимо аккуратно обращаться с окончаниями для обозначения временных интервалов, учитывая число. Вот улучшенный код для русского языка:

Java
Скопировать код
String dayUnit = duration.toDays() == 1 ? " день" : " дней";
String timeAgo = duration.toDays() > 0 ? duration.toDays() + dayUnit + " назад" : ...

Полезно применить такую же логику для обозначения часов, минут и секунд, в знак уважения к грамматике.

Локализация с помощью PrettyTime и Android DateUtils

Мультиязычные приложения могут использовать библиотеку PrettyTime, создающую строки вида "сколько времени прошло" на разных языках:

Java
Скопировать код
PrettyTime p = new PrettyTime(new Locale("ru")); // Локализация это важно
System.out.println(p.format(new Date())); // Вывод времени в удобной форме

Для приложений на Android у нас ещё есть встроенный класс DateUtils, который предоставляет схожий функционал: getRelativeTimeSpanString.

Формирование строки "сколько времени прошло"

Лучший подход к сборке строки "сколько времени прошло" – использовать StringBuilder:

Java
Скопировать код
StringBuilder sb = new StringBuilder(); // StringBuilder более эффективен, чем конкатенация строк
if (duration.toDays() > 0) {
    sb.append(duration.toDays()).append(" дней ");
}
...
String timeAgo = sb.toString(); // Получаем готовую строку

Визуализация

Возможный вариант визуализации "сколько времени прошло":

Markdown
Скопировать код
👣👣👣👣👣👣👣👣🌊🕒
1мин 5мин 10мин  1ч   Сейчас

Обозначения:

  • Свежие следы (👣): Обозначают недавние события.
  • Волны (🌊): Символизируют прошествие времени.

Markdown
Скопировать код
Толкование следов:
- "Только что" – для новых 👣
- "Минуты назад" – для следов на водной поверхности 👣
- "Часы назад" – для бледных 👣
- "Дни назад" – когда отпечатки уже практически не видны.

Обратите внимание на изменение следов, чтобы лучше передать идею "сколько времени прошло". 🕒

Точное преобразование временных единиц

Для точного измерения используйте TimeUnit:

Java
Скопировать код
long milliseconds = ... // Ваше время
long hours = TimeUnit.MILLISECONDS.toHours(milliseconds); // Преобразование без лишних сложностей
long minutes = TimeUnit.MILLISECONDS.toMinutes(milliseconds) – 
               TimeUnit.HOURS.toMinutes(hours); // Дополнительные вычисления для точности

Применение подхода с TimeUnit обеспечит точность вычислений, независимо от единиц измерения времени.

Надёжность за счёт обработки ошибок

При работе со специальными случаями, такими как "0 секунд" или даты из будущего, можно использовать блоки try-catch:

Java
Скопировать код
try {
    // Ваш код
} catch (DateTimeException e) {
    // Обработка ошибки
}

Не только дни и часы

Для более детального представления о времени можно создать метод millisToLongDHMS:

Java
Скопировать код
String timeAgoDetailed = millisToLongDHMS(milliseconds); // Подробная информация о временном интервале

Обратное вычисление времени

Корпусом полезных функций будет функция, которая превращает строку "сколько времени прошло" обратно в миллисекунды — нечто вроде машины времени.

Завершающий штрих: очистка и форматирование

В завершение строки "сколько времени прошло" следует очистить от лишних пробелов и символов:

Java
Скопировать код
if (sb.length() > 0) sb.setLength(sb.length() – 2); // Убираем всё лишнее
timeAgo = sb.append("назад").toString();

Полезные материалы

  1. Официальное руководство Oracle по работе с датами и временем
  2. SimpleDateFormat
  3. Duration и Period
  4. Веб-сайт PrettyTime
  5. Как рассчитать разницу времени в Java – Stack Overflow
  6. Библиотека Joda-Time
  7. Класс Instant