2014-10-03 2 views
1

Я борюсь за это в течение нескольких дней.Java Дата проблемы с TIMEZONE

У меня есть поле даты, которое дает дату в формате «yyyy-MM-dd».

Мой объект есть это поле, как этот

@Temporal(TemporalType.DATE) 
private Date finishdate; 

я на UTC, и эта потребность работать во всем мире, так и на UTC-7 или UTC + 7

На DataBase это значение необходимо хранить в течение 0 часов.

Когда finishdate заполнен, формат дать мне временную зону, так, например:

Я хочу 2014-10-01 с НОЛЬ ЧАСОВ И минутами и секундами, на Diferent часовых поясов Ловлю:

2014-10-01 07: 00: 00: 000 или 2014-09-01 17: 00: 00: 000

проблемные швы быть из-за Дата liybrary, и я нашел решение с библиотекой JODA, но мне сказали не использовать его, и мне нужно найти другое решение п.

Так что вам необходимо конвертировать в UTC Дата, все даты или что-то еще, но день должен быть таким же, как 1 октября.

Любое проходит через это?

+1

Я всегда использую библиотеки joda для всех связанных по дате полей. Преобразование между часовыми поясами является простым, и я считаю, что потокобезопасность. Кроме того, joda formatters (в отличие от родной java DateFormatter) - это потокобезопасный – Josh

+0

Итак, босс позволяет добавлять Spring, но не Joda-Time? Вам нужно объяснить боссу, насколько очень плохи связанные классы времени и времени, и вам очень нужно Joda-Time. Joda-Time широко используется, стабильна и износостойка. Новый пакет java.time в комплекте с Java 8 тоже хорош, вдохновленный Joda-Time, но переработанный. У Joda-Time и java.time есть свои преимущества. Я использую оба. –

ответ

0

Решение этой проблемы.

Мы создали собственный десериализатор для каждого объекта типа Date.

На ObjectMapperFactory, где мы сериализации или десериализации, я сопоставляются в другой класс, как это:

module.addDeserializer(Date.class, new DateDeserializerByDefault()); 

Тогда в этом классе мы сделали:

private static SimpleDateFormat dateFormatWithoutTimezome = new SimpleDateFormat("yyyy-MM-dd"); 
private static SimpleDateFormat dateFormatWithTimezone= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 
private static Pattern pattern = Pattern.compile("([0-9]{4})-([0-9]{2})-([0-9]{2})"); 

@Override 
public Date deserialize(JsonParser jparser, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
    String content = jparser.getValueAsString(); 
    DateFormat format=(pattern.matcher(content).matches()) ? dateFormatWithoutTimezome : dateFormatWithTimezone;   

try { 
    return format.parse(content); 
} catch (ParseException e) { 
    throw new JsonParseException("Date parse failed", jparser.getCurrentLocation(),e); 
} 
} 

И с этим, когда мы получаем Даты в другом формате или с часовым поясом, которые мы должны хранить, мы можем изменить его на то, что хотим.

Надеюсь, что это решение может помочь, я застрял на нем в течение 3,5 дней. Даты - это боль в а **.

1

Библиотека Joda-Time исправляет такие проблемы, и я считаю, что это также является основой пакета java.time в Java 8, но для старых версий Java эта проблема возникает постоянно.

Единственный последовательный способ, с которым я столкнулся с этим без времени Джоды, - рассматривать чистые даты как строковые («2014-10-01») или целочисленные типы (20141001) вместо даты. и только конвертировать в даты, когда это необходимо в расчетах. Это настоящая боль.

1

Не забывайте, что SimpleDateFormat не является потокобезопасным. Ответ saga56 дает работу, но у вас появятся очень странные даты, если есть одновременное использование десериализатора. Вы должны «обновлять» SimpleDateFormat каждый раз или (менее благоприятно) делать что-то еще, чтобы SimpleDateFormat строго ограничивался одним потоком за раз.

0

Другие ответы верны, но устарели.

java.time

java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытесняют старые неприятные классы времени, такие как java.util.Date, .Calendar, & java.text.SimpleDateFormat. Команда Joda-Time также рекомендует перейти на java.time.

Чтобы узнать больше, см. Oracle Tutorial. И поиск Stack Overflow для многих примеров и объяснений.

Большая часть функциональности java.time портирована на Java 6 & 7 в ThreeTen-Backport и далее адаптирована для Android в ThreeTenABP.

LocalDate

A LocalDate представляет собой дату только значение без времени суток и без временной зоны.

Ваша входная строка соответствует стандарту ISO 8601, поэтому ее можно разобрать непосредственно на LocalDate. Нет необходимости указывать шаблон форматирования.

String input = "2014-10-01"; 
LocalDate localDate = LocalDate.parse(input); 

ZonedDateTime

Вы предполагаете день начинается во время 00:00:00. Но это не всегда случай. В некоторых часовых поясах летнее время (DST) или, возможно, другие аномалии могут означать, что день начинается в другое время на часах, таких как 01:00:00. Пусть java.time определяет время начала первого момента дня. Укажите часовой пояс, и при условии, что tz database в комплекте с Java обновлен, тогда звонок LocalDate::atStartOfDay создает ZonedDateTime для вашей даты и первого момента.

ZoneId zoneId = ZoneId.of("America/Los_Angeles"); 
ZonedDateTime zdt = localDate.atStartOfDay(zoneId); 

Если вы хотите первый момент дня в UTC указать константу ZoneOffset.UTC (ZoneOffset быть подклассом ZoneId).

ZonedDateTime zdt = localDate.atStartOfDay(ZoneOffset.UTC); 

В качестве альтернативы используйте более подходящий класс OffsetDateTime. Это значение для значений с offset-from-UTC, но не имеет набора правил для обработки аномалий, таких как DST, найденных в полном размере time zone. В UTC день всегда начинается с 00:00:00, который хранится в константе LocalTime.MIN.

OffsetTime ot = OffsetTime.of(LocalTime.MIN , ZoneOffset.UTC); 
OffsetDateTime odt = localDate.atTime(offsetTime); 

Database

Для работы с базами данных, если вы хотите даты только значения, хранящегося вам следует использовать тип данных вдоль линий SQL Standard type of DATE.

Для значения даты и времени почти каждая серьезная база данных преобразует входящие данные в UTC для хранения в столбце типа TIMESTAMP WITH TIME ZONE. Драйвер JDBC должен помочь с этим. Но тест и эксперимент, так как поведение драйверов и баз данных колеблется чрезвычайно.

С JDBC 4.2 и более поздними версиями вы можете передавать/извлекать типы java.time напрямую через setObject/getObject. Если нет, перейдите в типы java.sql с помощью новых методов, добавленных в старые классы.