Как вычислить "время назад" в Java: гуманитарный формат даты
Быстрый ответ
Java 8 предлагает API java.time
, который позволяет определить интервал времени, пройденный с некоторой точки времени, на основании экземпляров LocalDateTime
:
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 минут назад".
Грамматические правила: обработка единственного и множественного числа
Необходимо аккуратно обращаться с окончаниями для обозначения временных интервалов, учитывая число. Вот улучшенный код для русского языка:
String dayUnit = duration.toDays() == 1 ? " день" : " дней";
String timeAgo = duration.toDays() > 0 ? duration.toDays() + dayUnit + " назад" : ...
Полезно применить такую же логику для обозначения часов, минут и секунд, в знак уважения к грамматике.
Локализация с помощью PrettyTime и Android DateUtils
Мультиязычные приложения могут использовать библиотеку PrettyTime, создающую строки вида "сколько времени прошло" на разных языках:
PrettyTime p = new PrettyTime(new Locale("ru")); // Локализация это важно
System.out.println(p.format(new Date())); // Вывод времени в удобной форме
Для приложений на Android у нас ещё есть встроенный класс DateUtils, который предоставляет схожий функционал: getRelativeTimeSpanString
.
Формирование строки "сколько времени прошло"
Лучший подход к сборке строки "сколько времени прошло" – использовать StringBuilder
:
StringBuilder sb = new StringBuilder(); // StringBuilder более эффективен, чем конкатенация строк
if (duration.toDays() > 0) {
sb.append(duration.toDays()).append(" дней ");
}
...
String timeAgo = sb.toString(); // Получаем готовую строку
Визуализация
Возможный вариант визуализации "сколько времени прошло":
👣👣👣👣👣👣👣👣🌊🕒
1мин 5мин 10мин 1ч Сейчас
Обозначения:
- Свежие следы (👣): Обозначают недавние события.
Волны (🌊): Символизируют прошествие времени.
Толкование следов:
- "Только что" – для новых 👣
- "Минуты назад" – для следов на водной поверхности 👣
- "Часы назад" – для бледных 👣
- "Дни назад" – когда отпечатки уже практически не видны.
Обратите внимание на изменение следов, чтобы лучше передать идею "сколько времени прошло". 🕒
Точное преобразование временных единиц
Для точного измерения используйте TimeUnit
:
long milliseconds = ... // Ваше время
long hours = TimeUnit.MILLISECONDS.toHours(milliseconds); // Преобразование без лишних сложностей
long minutes = TimeUnit.MILLISECONDS.toMinutes(milliseconds) –
TimeUnit.HOURS.toMinutes(hours); // Дополнительные вычисления для точности
Применение подхода с TimeUnit
обеспечит точность вычислений, независимо от единиц измерения времени.
Надёжность за счёт обработки ошибок
При работе со специальными случаями, такими как "0 секунд" или даты из будущего, можно использовать блоки try-catch
:
try {
// Ваш код
} catch (DateTimeException e) {
// Обработка ошибки
}
Не только дни и часы
Для более детального представления о времени можно создать метод millisToLongDHMS
:
String timeAgoDetailed = millisToLongDHMS(milliseconds); // Подробная информация о временном интервале
Обратное вычисление времени
Корпусом полезных функций будет функция, которая превращает строку "сколько времени прошло" обратно в миллисекунды — нечто вроде машины времени.
Завершающий штрих: очистка и форматирование
В завершение строки "сколько времени прошло" следует очистить от лишних пробелов и символов:
if (sb.length() > 0) sb.setLength(sb.length() – 2); // Убираем всё лишнее
timeAgo = sb.append("назад").toString();