java.time
import java.time.Instant;
import java.time.temporal.ChronoUnit;
fun timeSince(dateStr: String): String {
val diffHours = ChronoUnit.HOURS.between(Instant.parse(dateStr), Instant.now())
return "%d h ago".format(diffHours)
}
Давайте попробуем:
fun main() {
println(timeSince("2019-01-22T12:43:01Z"))
}
Это только что напечатано:
236 ч назад
Я использую java.time, современный Java-интерфейс даты и времени.По сравнению со старыми классами Date
и, что не менее важно, SimpleDateFormat
мне гораздо приятнее работать.Приведенный выше метод выдаст DateTimeParseException
, если переданная ему строка не соответствует формату ISO 8601.Для большинства целей это, вероятно, лучше, чем возвращать 0 h ago
.Метод допускает наличие и отсутствие (до 9) десятичных знаков в секундах, поэтому принимает, например, 2019-01-22T12:43:01.654321Z
.
Разве нам не нужен форматер?Нет. Я пользуюсь тем фактом, что ваша строка имеет формат ISO 8601, формат, который современные классы даты и времени анализируют (и также печатают) по умолчанию.
Хотелось бы использовать ChronoUnit
и Instant
Редактировать:
Я бы хотел использовать ChronoUnit & Instant, но для этого требуется минимум V26 Android.Мой текущий минимум составляет 23.
java.time прекрасно работает и на старых устройствах Android.Для этого требуется как минимум Java 6 .
- В Java 8 и более поздних версиях и на более новых устройствах Android (начиная с уровня API 26) современный API поставляется встроенным.
- В Java 6 и 7 получают ThreeTen Backport, бэкпорт современных классов (ThreeTen для JSR 310; см. Ссылки внизу).
- На (более старых) Android используется версия ThreeTen для AndroidBackport.Это называется ThreeTenABP.И убедитесь, что вы импортируете классы даты и времени из
org.threeten.bp
с подпакетами.
Что пошло не так в вашем коде?
Я вижу две ошибки в коде в вашем вопросе:
- Как уже указывал 10 芒 轻 胜 马 胜 в этом ответе , ваш формат ожидает 4 части между
T
и Z
, разделенные двоеточиями, но вашСтрока имеет только три части.С SimpleDateFormat
использование двух SS
для доли секунды также неправильно, так как верхний регистр S
предназначен для миллисекунд, поэтому имеет смысл только три SSS
(в отличие от современного DateTimeFormatter
S
для дробисекунды, поэтому любое число (до 9 SSSSSSSSS
) имеет смысл). - Вы рассматриваете
Z
в строке как литерал.Это смещение UTC, равное нулю, и его необходимо проанализировать как таковое, иначе вы получите неправильное время (в подавляющем большинстве JVM).
Links