Летнее время в Java

Работаю над GPS-проектом и столкнулся с проблемой, когда трекер передает на сервер время на час большее, чем реальное. Причина выяснилась быстро - китайские производители устройства не учли переход на летнее время. Можно было оставить всё как есть и потерпеть несколько дней: в конце марта переведем часы и искажения исчезнут сами собой. Можно было избавиться от проблемы на скорую руку, т.е. где-нибудь в SQL-процедурах добавить что-то вроде "... - INTERVAL '1 HOUR' ". Но  решил таки сделать всё как следует.

Прежде всего прочитал статью в Википедии о летнем времени. Оказывается, тонкости есть. Во-первых, так называемые "малые устройства" как правило не оснащаются автоматическим механизмом перехода на летнее время и обратно, в отличие от персональных компьютеров, сотовых телефонов и т.п. Во-вторых, в Китае, где производятся наши трекеры, от летнего времени отказались вообще. Поэтому полгода сдвиг в передаваемых параметрах времени есть, полгода его нет. В-третьих, к немалому моему удивлению, в стандартных библиотеках Java не удалось найти готовой процедуры выяснения действует в данный момент летнее время или нет. Видимо, это связано с огромным разнобоем в вопросе перехода на него в разных странах. В Канаде, например, в ряде провинций люди бойкотируют летнее время, в США переход на зимнее осуществляется в 2 ночи, в России - в 3, плюс у нас оно накладывается на декретное время, которое действует не во всех регионах. Пришлось, короче говоря, писать механизм определения летнего времени самостоятельно. Если я плохо поискал и такая процедура есть в стандартном API - подскажите, буду признателен. Однако небольшое упражнение на использование класса java.util.Calendar никому не повредит. Вот какой фрагмент кода можно использовать чтобы определять действует летнее время или нет:


import java.util.Calendar;
import java.util.Date;

...

 private static Calendar cldr;
 private static boolean summerTime;

 static{
  cldr = Calendar.getInstance();
  cldr.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
  Calendar c = (Calendar)cldr.clone();
  c.set(c.MONTH,       c.MARCH);
  c.set(c.HOUR_OF_DAY, 2);
  for(int i = 31; i > 0; i--){
   c.set(c.DAY_OF_MONTH, i);
   if(c.get(c.DAY_OF_WEEK) == c.SUNDAY) break;
  }
  Date inMarch = c.getTime();
  c.set(c.MONTH,       c.OCTOBER);
  c.set(c.HOUR_OF_DAY, 3);
  for(int i = 31; i > 0; i--){
   c.set(c.DAY_OF_MONTH, i);
   if(c.get(c.DAY_OF_WEEK) == c.SUNDAY) break;
  }
  Date inOctober = c.getTime();
  Date now = new Date();
  sommerTime =  now.after(inMarch) && now.before(inOctober);
 }    

 public static boolean isSummerTime(){
  return summerTime;
 }

В переводе не обычный язык это означает, что если текущая дата находится между 2:00 последнего воскресенья марта и 3:00 последнего воскресенья октября, то время летнее. Отмечу, что в первых реализациях Java для работы с датами использовался напрямую класс java.util.Date. Но уже давно большинство его методов  помечены как deprecated, то есть их использования нужно по максимуму избегать и задействовать гораздо более гибкий Calendar.

TimeZone.inDaylightTime(Date

TimeZone.inDaylightTime(Date datetime)

Вот это правильное решение

Спасибо за TimeZone.inDaylightTime(Date datetime)

Отправить комментарий

КАПЧА
Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.
CAPTCHA на основе изображений
Enter the characters shown in the image.