Как справиться с летней экономией, используя TimeZone в Java

Мне нужно напечатать время EST в своем приложении Java. Я установил часовой пояс для EST, используя:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));

Но когда в этот часовой пояс выполняется переход на летнее время, мой код не печатает правильное время (он печатает на 1 час меньше).

Как заставить код работать, чтобы читать правильное время всегда, независимо от того, соблюдается ли дневная экономия или нет?

PS: Я попытался установить часовой пояс на EDT, но это не решает проблему.

Ответ 1

Это проблема, с которой можно начать:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));

3-буквенные сокращения должны быть полностью исключены в пользу идентификаторов зоны TZDB. EST - Восточное стандартное время - и стандартное время никогда не соблюдает DST; это не действительно полное имя часового пояса. Это имя используется для части часового пояса. (К сожалению, я не нашел хорошего термина для этой концепции "половины часового пояса".)

Вы хотите указать полное имя часового пояса. Например, America/New_York находится в восточном часовом поясе:

TimeZone zone = TimeZone.getTimeZone("America/New_York");
DateFormat format = DateFormat.getDateTimeInstance();
format.setTimeZone(zone);

System.out.println(format.format(new Date()));

Ответ 2

Другие ответы верны, особенно тот, что был Джон Скит, но устарел.

java.time

Эти старые классы даты были вытеснены с помощью java.time, встроенной в Java 8 и более поздних версий.

Если вам просто нужно текущее время в UTC, используйте класс Instant.

Instant now = Instant.now();

EST не является часовым поясом, как описано в правильном ответе Jon Skeet. Такие 3-4 буквенные коды не являются ни стандартизированными, ни уникальными, а также путаница в отношении летнего времени (DST). Используйте правильное имя часового пояса в формате "континент/регион".

Возможно, вы имели в виду Восточное стандартное время на восточном побережье Северной Америки? Или египетское стандартное время? Или европейское стандартное время?

ZoneId zoneId = ZoneId.of( "America/New_York" );
ZoneId zoneId = ZoneId.of( "Africa/Cairo" );
ZoneId zoneId = ZoneId.of( "Europe/Lisbon" );

Используйте любой такой объект ZoneId, чтобы получить текущий момент, скорректированный на определенный часовой пояс, чтобы создать объект ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;

Отрегулируйте этот ZonedDateTime в другой часовой пояс, создав другой объект ZonedDateTime из первого. Рамка java.time использует неизменяемые объекты вместо изменения (мутирования) существующих объектов.

ZonedDateTime zdtGuam = zdt.withZoneSameInstant( ZoneId.of( "Pacific/Guam" ) ) ;

Ответ 3

Вместо ввода "EST" для часового пояса вы можете ввести "EST5EDT" как таковой. Как вы отметили, просто "EDT" не работает. Это будет учитывать проблему летнего времени. Строка кода выглядит так:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST5EDT"));

Ответ 4

В соответствии с этим answer:

TimeZone tz = TimeZone.getTimeZone("EST");
boolean inDs = tz.inDaylightTime(new Date());

Ответ 5

Внедрение класса TimeZone для установки часового пояса в календарь обеспечивает уход за летним днем.

java.util.TimeZone представляет смещение часового пояса, а также определяет летнее время.

пример кода:

TimeZone est_timeZone = TimeZoneIDProvider.getTimeZoneID(TimeZoneID.US_EASTERN).getTimeZone();
Calendar enteredCalendar = Calendar.getInstance();
enteredCalendar.setTimeZone(est_timeZone);

Ответ 6

В java DateFormatter по умолчанию использует DST, Чтобы избежать экономии времени (DST), вам нужно вручную сделать трюк,
сначала вы должны получить смещение DST, то есть за сколько миллисекунд DST применяется, например, где-то DST также составляет 45 минут, а для некоторых мест - 30 минут
но в большинстве случаев DST составляет 1 час.
вы должны использовать объект Timezone и проверять дату, независимо от того, попадает ли она под DST или нет, а затем вам нужно вручную добавить в нее смещение DST. например:

 TimeZone tz = TimeZone.getTimeZone("EST");
 boolean isDST = tz.inDaylightTime(yourDateObj);
 if(isDST){
 int sec= tz.getDSTSavings()/1000;// for no. of seconds
 Calendar cal= Calendar.getInstance();
 cal.setTime(yourDateObj);
 cal.add(Calendar.Seconds,sec);
 System.out.println(cal.getTime());// your Date with DST neglected
  }