Я понял, что мне нужно считать 12 месяцев не 360 днями, а также
рассчитать високосные годы. Есть идеи для этого?
Сначала вам нужно выбрать часовой пояс для этого. Зачем? Скажем, вы использовали этот код в (UTC) 2019-02-28T23: 00: 00Z и хотите вычесть 1 месяц. На данный момент в Мехико 28 февраля, поэтому результат должен упасть 28 января. Для сравнения, в Шанхае уже 1 марта, поэтому результат должен упасть 1 февраля. Разница составляет 3 дня (72 часа).
Как только вы определились с часовым поясом, проще всего использовать ZonedDateTime
. Вы всегда можете конвертировать в Instant
после вычитания, это тоже просто.
Например:
ZoneId zone = ZoneId.of("Asia/Ashkhabad");
Map<Unit, ChronoUnit> units = Map.of(Unit.days, ChronoUnit.DAYS,
Unit.months, ChronoUnit.MONTHS, Unit.years, ChronoUnit.YEARS);
Time timeToSubtract = new Time(15, Unit.months);
Instant result = ZonedDateTime.now(zone)
.minus(timeToSubtract.getNumber(), units.get(timeToSubtract.getUnit()))
.toInstant();
System.out.println("15 months ago was " + result);
При запуске только сейчас (2019-05-08T07: 06: 45Z) я получил этот вывод:
15 месяцев назад было 2018-02-08T07: 06: 45.353746Z
Метод ZonedDateTime.minus
, который я использую, понимает ChronoUnit
, но, конечно, не ваше Unit
перечисление, поэтому, поскольку вы получаете последнее, нам нужно перевести (иначе ваше перечисление должно было бы реализовать TemporalUnit
, но это было бы излишним). Я использую карту для перевода. Я инициализирую карту Java 9 способом. Если вы все еще на Java 8, я надеюсь, что вы заполните его другим способом.
В моем коде я предполагал, что у вашего Time
класса есть обычный конструктор и геттеры.
ZonedDateTime
также учитывает, что день не всегда 24 часа. Например, когда начинается весеннее летнее время (DST) и часы переводятся вперед, день составляет всего 23 часа. И затем 25 часов в день, когда часы возвращаются осенью.