Как избежать переноса даты в формат часового пояса? - PullRequest
0 голосов
/ 16 января 2019

У меня есть DateAdapter

public class DateAdapter extends XmlAdapter<String, Date> {
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");

    @Override
    public String marshal(Date v) throws Exception {
        synchronized (dateFormat) {
            return dateFormat.format(v);
        }
    }

    @Override
    public Date unmarshal(String v) throws Exception {
        synchronized (dateFormat) {
            return dateFormat.parse(v);
        }
    }
}

Итак, я ввожу "2009-12-31T23: 59: 59.999 +0000" при передаче строки в дату

Но при попытке разобрать изDate to String -> 2010-01-01T02: 59: 59.999 +0300 (часы изменились и часовой пояс тоже)

Итак, как отключить передачу времени?

Ответы [ 3 ]

0 голосов
/ 16 января 2019

Результат, который вы получаете, абсолютно верен (но, очевидно, не то, что вы хотите). Это точно такой же момент времени, как тот, который вы проанализировали, только представленный по-другому. Есть миллионы различных строк, как записать данный момент времени, и один из параметров является предпочтительным часовым поясом.

Вы, кажется, живете в +0300 часовом поясе, и поэтому SimpleDateFormat предпочитает представлять любой данный Date в соответствии с этим часовым поясом, независимо от того, какой часовой пояс был входным.

Если вы хотите сохранить не только исходный момент времени, но также информацию о представлении источника (включая указанный часовой пояс), то Date не может смоделировать это (если вы не хотите использовать устаревшие, устарела часть его API), и вам придется искать другой класс представления.

При Date и SimpleDateFormat свойства SimpleDateFormat определяют итоговое представление, одно свойство - строка формата, а другое - предпочтительный часовой пояс. Вы устанавливаете последнее, вызывая setTimeZone() в экземпляре SimpleDateFormat. Таким образом, вы можете решить, какой (фиксированный) часовой пояс будет использоваться при форматировании, например, что вы хотите, чтобы все даты были представлены в соответствии с UTC.

0 голосов
/ 17 января 2019

tl; dr

Всегда используйте java.time классы, никогда не применяйте ужасные унаследованные классы, такие как java.util.Date.Для взаимодействия преобразуйте.

Я подозреваю, что вы действительно намеревались использовать стандартный формат ISO 8601, например 2009-12-31T23:59:59.999Z.

. Не допускайте срабатывания анти-функции в Date::toString, которая применяется динамически.часовой пояс к значению, которое фактически находится в UTC.

java.time классы поточно-ориентированные по своей конструкции, используя неизменяемые объекты .Так что нет необходимости в synchronized звонках.

public class DateAdapter extends XmlAdapter< String, Date > {

    @Override
    public String marshal( Date v ) throws Exception {      // `Instant` generates standard ISO 8601 strings by default. No need to specify a formatting pattern. 
        return v.toInstant().toString() ;                   // Convert from legacy `Date` to modern `Instant`. 
    }

    @Override
    public Date unmarshal( String v ) throws Exception {    // `Instant` parses standard ISO 8601 strings by default. No need to specify a formatting pattern. 
        return java.util.Date.from( Instant.parse( v ) ) ;  // Convert from modern `Instant` to legacy `Date`. 
    }
}

ISO 8601

Ваша строка ввода близка к стандартному формату ISO 8601 .Я настоятельно рекомендую придерживаться стандарта везде, где это возможно.Опустить ПРОБЕЛ до смещения от UTC.

И, лучше всего включать COLON в смещение между часами и минутами - хотя это необязательно в стандарте, некоторые библиотеки ожидают символ.

String input = "2009-12-31T23:59:59.999+00:00" ;

Кстати, обычное сокращениесмещения от UTC нуля - это буква Z, произносится как «зулу».

String input = "2009-12-31T23:59:59.999Z"  ;

java.time

Вы используете ужасных классов даты и времени, связанных с самыми ранними версиями Java.Эти унаследованные классы были полностью вытеснены классами java.time .

Проверьте , посмотрите, обновлены ли ваши библиотеки для работы с java.time .Если нет, вы можете конвертировать туда и обратно, вызывая новые методы, добавленные к старым классам.

A java.util.Date Объект - это момент, точка на временной шкале в UTC.Теперь он заменен классом java.time.Instant.

Instant instant = myJavaUtilDate.toInstant() ;   // Convert by calling new method added to the old class.

Чтобы сгенерировать строку в стандартном формате с Z, просто наберите toString.

String output = instant.toString() ;

Разбор строки в стандартном формате прост с Instant.parse.Не нужно указывать шаблон форматирования.

Instant instant = Instant.parse( "2009-12-31T23:59:59.999Z" ) ;

Преобразование с использованием другого нового метода, добавленного к старому классу.

java.util.Date d = java.util.Date.from( instant ) ;

Если вы не можете перейти на использование стандарта ISO 8601 текстовые форматы, используйте объект DateTimeFormatter для анализа и генерации строк в альтернативных форматах.Переполнение стека поиска, так как это уже много раз уже освещалось.

Date::toString ложь

Имейте в виду, что java.util.Date::toString ложь вам .Этот метод динамически применяет текущий часовой пояс JVM по умолчанию.Внутреннее значение указано в UTC, но этот метод сообщает об обратном.Несмотря на благие намерения, эта анти-функция не вызывала путаницы и страданий у программистов на Java.Напротив, классы java.time сообщают о своих значениях напрямую без таких ложных инъекций.


О java.time

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

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

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

Где получить классы java.time?

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

0 голосов
/ 16 января 2019

Я думаю, что ваша система устанавливает часовой пояс как системный часовой пояс. Для вывода вы можете использовать другой SimpleDateFormat без часового пояса, т.е.

private final SimpleDateFormat noTimeZoneDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

вы также можете использовать этот формат даты для ввода, если вам вообще не нужен часовой пояс

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...