2016-09-09 1 views
2

Мне нужно изменить каждый часовой пояс моего DTO во время выполнения. Сегодня часовой пояс сообщается параметром, когда Пользователь выполняет запрос на моем веб-сервисе, интересно, можно ли применить новый часовой пояс для всех атрибутов дат. Единственное, что я не могу использовать, это «TimeZone.setDefault (myTimeZone)», потому что этот способ применим ко всем JVM, и как существуют пользователи разных часовых поясов, это решение неосуществимо.Java - изменить часовой пояс все атрибуты в моем классе

Я пытался что-то вроде этого:

Query query = em.createNativeQuery(SQL.toString(), AgendamentoDTO.class); 
collection = query.setParameter(1, idEmpresa).getResultList(); 

for (Field atributo : AgendamentoDTO.class.getDeclaredFields()) { 
    if (atributo.getType().isAssignableFrom(Date.class)) { 
     //Change time zone here 
    } 
} 

Tks

+1

Для большей ясности вы считаете, что используете один стандартный часовой пояс? Скажите UTC? Поскольку вы упомянули, что ваши абоненты предоставляют часовой пояс, могут ли они быть преобразованы в UTC? Таким образом, JVM и другой часовой пояс Пользователей не имеют значения? –

+0

Спасибо за ответ. Дата всегда будет сохранена с часовым поясом по умолчанию (UTC), однако для того, чтобы сделать запрос типа, будет отправлен , который будет вести учет времени для UTC для пользователя. – mPissolato

ответ

0

Избегайте часовой пояс настройки по умолчанию

Как мудро советовали в вопросе, вы должны установить часовой пояс в JVM по умолчанию только последнее средство в самой отчаянной ситуации. Установка значения по умолчанию затрагивает весь код во всех потоках всех приложений, запущенных в этой JVM, и сразу же затрагивает их при их выполнении (!).

Вместо этого во всей вашей работе с датой всегда передавайте необязательный аргумент часового пояса различным методам. Никогда не полагайтесь на действующую по умолчанию зону JVM.

Избегайте классов старой даты и времени

Старые устаревшие классы даты и времени в комплекте с самыми ранними версиями Java доказали, плохо разработаны, хлопотно, и сбивает с толку. Избежать их. Теперь вытесняется классами java.time.

Итак, вместо java.util.Date, используйте java.time.Instant. Класс Instant представляет собой момент на временной шкале в UTC с разрешением nanoseconds. Этот класс Instant является основным строительным блоком обработки даты и времени. Используйте этот класс часто, так как большая часть вашей бизнес-логики, хранения данных, обмена данными и работы с базами данных должна быть в UTC. Не думайте о UTC, как о другом варианте часового пояса, скорее, о UTC, как о One True Time. Во время программирования забывайте о своем собственном местном часовом поясе, поскольку это ограниченное мышление путает ваше программирование.

Instant

Вообще говоря, ваш веб-сервис должен принять и дать значения UTC. Класс Instant может непосредственно анализировать и генерировать строки для представления этих значений в стандартном формате ISO 8601.

Instant instant = Instant.parse("2016-09-09T22:34:08Z"); 
String output = instant.toString(); // Generates: 2016-09-09T22:34:08Z 

Так что не нужно манипулировать этими значениями UTC. Держите их вокруг. Служба предоставления данных должна придерживаться UTC по большей части.

В вашем случае DTOS, будучи DTOs, должны придерживаться хранения значений в формате UTC (либо Instant объекта или строки в формате ISO 8601 в формате UTC с Z на конце). By definition, DTO должен быть «глупым» в смысле отсутствия бизнес-объекта и вместо этого должен просто переносить базовые элементы данных. Другие объекты, потребляющие эти DTO, должны обрабатывать любые необходимые назначения часового пояса.

ZonedDateTime

Генерация строки в других часовых поясах только для представления пользователям. Здесь мы назначаем часовой пояс Квебека для просмотра момента через линзу другого wall-clock time.Примените ZoneId, чтобы получить ZonedDateTime. ZonedDateTime и Instant обе представляют в тот же момент в истории, в то же время на шкале времени.

ZoneId z = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = instant.atZone(z); 

Обратите внимание, что мы держим Instant объекта вокруг в нашей бизнес-объекте, без изменений. Мы генерируем отдельный отдельный объект, ZonedDateTime, для другого времени настенных часов.

  • При выполнении этих заданий в часовом поясе в вашем коде пройдите около ZoneId объектов.
  • При указании этих назначений часовых поясов через API веб-службы передайте имя часового пояса в виде строки. Всегда используйте proper IANA ‘tz’ time zone names в формате continent/region, например America/Montreal или Pacific/Auckland. Никогда не используйте аббревиатуру 3-4 буквы, такую ​​как EST или IST, поскольку они не являются настоящими часовыми поясами, а не стандартизированы и даже не уникальны (!).

Генерация строки

Когда веб-служба , обслуживающие данные потребляться как данные, а не представления, генерировать строки в формате ISO 8601. Классы java.time используют эти стандартные форматы по умолчанию для разбора и генерации строк. Просто вызовите toString, чтобы сгенерировать строку в стандартном формате. Обратите внимание, что ZonedDateTime расширяет стандартный формат, добавляя имя часового пояса в квадратных скобках.

String output = instant.toString(); // 2016-09-09T22:34:08Z 
String output = zdt.toString(); // 2016-09-09T19:34:08-03:00[America/Montreal] 

Когда ваш веб-сервис служит информации для представления к пользователю, а не для потребления в качестве данных, генерировать строки в формате, соответствующие человеческом язык пользователя и культурные нормы. Вы можете указать конкретный формат. Но в целом лучше всего позволить java.time автоматически локализовать для вас.

Locale locale = Locale.CANADA_FRENCH; 
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(l); 
String output = zdt.format(f);