Хорошо вы нашли решение, я только как добавить некоторые идеи и предложить небольшое улучшение до your answer.
Установка часового пояса по умолчанию JVM с использованием TimeZone.setDefault
- не лучший способ достичь этого. Хотя это может работать в большинстве случаев, это немного рискованно и подвержено ошибкам, если вы считаете, что этот код работает в более сложной среде.
Это потому, что TimeZone.setDefault
изменяет часовой пояс по умолчанию для всего JVM. Любое другое приложение, работающее в одной JVM, будет затронуто этим. Другие части одного и того же приложения также будут затронуты, и даже этот же код, работающий в нескольких потоках, может привести к неправильным результатам (и race conditions are hard to debug).
Я заметил, что вы используете TimeZone.setDefault(TimeZone.getTimeZone(timezone));
. Это означает, что вы уже работаете с определенным часовым поясом, поэтому нет необходимости полагаться на JVM по умолчанию. Если у вас есть определенное имя часового пояса, просто используйте его вместо стандартного. Поэтому я предлагаю вам, что метод addDays
должен быть таким:
public ZonedDateTime addDays(long myUTCTimeInSeconds, int days, String timezone) {
// get the instant from the UTC seconds
Instant instant = Instant.ofEpochSecond(myUTCTimeInSeconds);
// get the instant at the specified timezone
ZonedDateTime z = instant.atZone(ZoneId.of(timezone));
// add days
return z.plusDays(days);
}
Улучшения сделаны:
plusDays
уже вычитает 1 день, если вы передаете -1
к нему. Нет необходимости проверять значение и использовать метод abs
.
- не использовать JVM часовой пояс по умолчанию: вместо
ZoneId.systemDefault()
, используйте timezone
, что у вас уже есть (тот, который вы использовали, в методе setDefault
)
instant.atZone
эквивалентно ZonedDateTime.ofInstant
.IMO, atZone
более «читабельна», но в данном случае это вопрос выбора и стиля кода. Это не влияет на конечный результат.
При этом, вы можете сделать:
// call directly, no need to change the default timezone
System.out.println(addDays(1459123200, -1, "Europe/Stockholm"));
Это будет печатать:
2016-03-27T03: 00 + 02: 00 [Европа/Стокгольм]
Вы не можете вычесть день из * локального * даты/времени, который не имеет понятия о дневном свете, и ожидать, что он применит правила летнего времени. – RealSkeptic
@RealSkeptic Не могли бы вы предложить, как это сделать. –
Если вы хотите зонированную дату/время, используйте ZonedDateTime. Не используйте 'LocalDateTime'. – RealSkeptic