Вопрос

Я работаю с веб-сервисами, вставляя записи, которые возвращают значение метки времени в типе XMLGregorianCalendar.Мне нужно преобразовать его в значение java.sql.Timestamp, поэтому я использую функцию, подобную этой.

public static java.sql.Timestamp getSqlTimeStamp(XMLGregorianCalendar xgc) {
    if (xgc == null) {
        return null;
    } else {
        return new Timestamp(xgc.toGregorianCalendar().getTime().getTime());
    }
}
Timestamp timestamp=getSqlTimeStamp(ExitInXMLGregor.getTimestamp());

Моя проблема в том, что на сервере значение метки времени, когда я вставляю запись, выглядит следующим образом:2012-10-03T19:23:22.342+02:00

Но когда я выполняю преобразование типа, я получаю значение временной метки следующим образом:2012-10-03T17:23:22.342

Время на сервере (где расположен веб-сервис) на 2 часа больше, чем в моей локали, и по какой-то причине я получаю свое время вставки локали после его преобразования.Проблема в том, что мне действительно нужно получить серверное время, потому что в базе данных значение метки времени совпадает с серверным, и у меня возникают проблемы при операции обновления из-за разных значений метки времени.

Пожалуйста, я был бы признателен за любую помощь.Спасибо!

Редактировать:Я вроде как нахожу решение, но это не совсем то, что мне нужно.Когда я конвертирую свою временную метку в формате java.sql.Timestamp в XMLGregorian, я устанавливаю часовой пояс сервера (setTimeZone(TimeZone.getTimeZone("GMT + 02:00"))).Это действительно работает, но далеко от идеального решения (может случиться так, что изменится часовой пояс или даже сервер) Было бы здорово узнать в этот момент часовой пояс сервера динамически, но я не знаю как...

public static XMLGregorianCalendar getXMLGregorianCalendar(Timestamp timestamp)
        throws BaseException {
    try {
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTimeZone(TimeZone.getTimeZone("GMT+02:00"));
        gc.setTimeInMillis(timestamp.getTime());
        return DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
    } catch (DatatypeConfigurationException ex) {
        throw new BaseException(ex);
    }
}
Это было полезно?

Решение

Я подозреваю, что временная метка действительно указывает правильное время, просто не отображается с правильным часовым поясом.2012-10-03T17: 23: 22.342 совпадает с 2012-10-03T19: 23: 22.342 +02:00, предполагая, что (скрытый) часовой пояс первого равен +00:00.

Другие советы

tl;dr

  • Обе строки представляют один и тот же момент, просто скорректированный с учетом часового пояса, но без учета смещение-от-UTC.
  • Избегайте подобной путаницы, всегда включая информацию о смещении и зоне в такие строки.
  • Используйте современные java.время классы, которые вытесняют проблемные устаревшие классы.(Instant, не Timestamp)

Пример кода.

myPreparedStatement.setObject( 
    … , 
    myXMLGregorianCalendar  // If forced to work with a `javax.xml.datatype.XMLGregorianCalendar` object rather than a modern java.time class…
    .toGregorianCalendar()  // …convert to a `java.util.GregorianCalendar`, and then…
    .toZonedDateTime()      // …convert to modern `java.time.ZonedDateTime` class.
    .toInstant()            // Adjust to UTC by extracting an `Instant` object.
)

Извлечение из базы данных, начиная с JDBC 4.2 и более поздних версий.

Instant instant = myResultSet.getObject( … , Instant.class ) ;

java.время

В качестве правильный принятый ответ Роберта Тупело-Шнека говорит, кажется, все хорошо в том смысле, что обе строки представляют один и тот же момент, но скорректированы на другой часовой пояс с другим смещением от UTC.Проблема в том, что в одной из этих двух строк отсутствует индикатор ее смещения от UTC.

Такое упущение является плохой практикой, поскольку создает эту путаницу.Всегда включайте смещение от UTC, если только вы не абсолютно уверены, что контекст делает смещение / зону понятными.

Работа в UTC

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

Кроме того, вы используете ужасно проблемные старые классы, которые теперь вытеснены java.время классы.Преобразуйте свой XMLGregorianCalendar Для java.time.ZonedDateTime.

ZonedDateTime zdt = myXMLGregorianCalendar.toGregorianCalendar().toZonedDateTime() ;

Скорректируйтесь в соответствии с UTC, извлекая Instant объект.

Instant instant = zdt.toInstant() ;

Начиная с JDBC 4.2 и более поздних версий, вы можете напрямую обмениваться java.время объекты с базой данных.Нет необходимости когда-либо использовать наследие java.sql.Timestamp снова урок.

myPreparedStatement.setObject( … , instant ) ;

Поиск:

Instant instant = myResultSet.getObject( … , Instant.class ) ;

Перейдите с UTC на какой-то конкретный часовой пояс, если вы хотите просмотреть тот же момент, используя время настенных часов, используемых жителями определенного региона.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

Преобразовать

Если вам необходимо взаимодействовать с каким-то старым кодом, требующим java.sql.Timestamp, вы можете конвертировать туда-обратно с помощью java.time.Instant.Вызовите новые методы преобразования, добавленные к старым классам.

java.sql.Timestamp ts = java.sql.Timestamp.from( instant ) ;

Иду в другую сторону.

Instant instant = ts.toInstant() ;

Смотрите также мой Ответ на аналогичный Вопрос.


О нас java.время

Тот Самый java.время фреймворк встроен в Java 8 и более поздние версии.Эти классы вытесняют старые, вызывающие беспокойство наследие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Тот Самый Джода-Время проект, находящийся сейчас в режим технического обслуживания, рекомендует перейти на java.время классы.

Чтобы узнать больше, смотрите Учебное пособие по Oracle.И найдите в Stack Overflow множество примеров и объяснений.Спецификация такова JSR 310.

Вы можете обменять java.время объекты непосредственно связаны с вашей базой данных.Используйте Драйвер JDBC соответствует требованиям JDBC 4.2 или позже.Нет необходимости в строках, нет необходимости в java.sql.* классы.

Где взять классы java.time?

Тот Самый Три дня-Дополнительно проект расширяет java.time дополнительными классами.Этот проект является испытательным полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter, и Еще.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top