ТЛ; др
LocalDateTime later =
LocalDateTime
.parse (
"2010-01-14 19:16:17"
.replace ( " " , "T" )
)
.plus( Period.parse ( "P10M3D" ) )
.plus( Duration.parse ( "PT1H10M5S" ) )
;
ISO 8601
Представление промежутка времени в том же формате, что и момент, создает путаницу. Размах совсем не совпадает с моментом.
Вместо использования формата YYYY-MM-DD HH-MM-SS
для определенного промежутка времени, я предлагаю использовать стандартный ISO 8601 формат PnYnMnDTnHnMnS . В этом формате P
отмечает начало (предположительно, «Период»), а T
отделяет часть года-месяца-дня от части часов-минут-секунд.
Пример значения:
PT1H30M
→ Полтора часа.
P3Y6M4DT12H30M5S
→ Три года, шесть месяцев, четыре дня, двенадцать часов, тридцать минут и пять секунд.
P10M3DT1H10M5S
→ Продолжительность вашего вопроса 0000-10-03 01:10:05
.
java.time
В Вопросе и других Ответах используются проблемные старые классы даты и времени, которые в настоящее время устарели из java.time фреймворка, встроенного в Java 8 и более поздние версии. См. Oracle Tutorial . Большая часть функциональности java.time была перенесена в Java 6 & 7 в ThreeTen-Backport и дополнительно адаптирована для Android в ThreeTenABP .
Классы java.time по умолчанию используют форматы ISO 8601 при разборе и генерации строк, представляющих значения даты и времени.
Вопрос не предоставляет никакой информации о часовом поясе, поэтому здесь мы используем класс LocalDateTime
. Если мы знаем смещение от UTC, мы будем использовать класс OffsetDateTime
, а если еще лучше, мы будем знать часовой пояс, мы будем использовать класс ZonedDateTime
.
Периоды времени в java.time делятся на пару классов. Годы-месяцы-дни представлены классом Period
, а часы-минуты-секунды обрабатываются классом Duration
.
Объединяя это время, мы действительно можем выполнять математику даты и времени. Здесь мы добавляем промежуток времени к начальной дате и времени, чтобы получить итоговую дату и время. И мы делаем это в очень мало строк кода. Результат действительно ожидаемый Вопросом.
Мы преобразуем входные строки в канонический формат ISO 8601, заменив пробел в середине на T
.
LocalDateTime ldt = LocalDateTime.parse ( "2010-01-14 19:16:17".replace ( " " , "T" ) );
//"0000-10-03 01:10:05"
Period period = Period.parse ( "P10M3D" );
Duration duration = Duration.parse ( "PT1H10M5S" );
LocalDateTime result = ldt.plus ( period ).plus ( duration );
Сравните с результатом, ожидаемым в Вопросе.
LocalDateTime expectation = LocalDateTime.parse ( "2010-11-17 20:26:22".replace ( " " , "T" ) );
Boolean isSame = result.equals ( expectation );
Дамп на консоль.
System.out.println ( "ldt: " + ldt + " + period: " + period + " + duration: " + duration + " is result: " + result + " compared to expectation: " + expectation + " is the same: " + isSame );
ldt: 2010-01-14T19: 16: 17 + период: P10M3D + продолжительность: PT1H10M5S - результат: 2010-11-17T20: 26: 22 по сравнению с ожиданием: 2010-11-17T20: 26: 22 - то же самое : true