Метод Time.valueOf, возвращающий неправильное значение - PullRequest
3 голосов
/ 27 апреля 2020

Я использовал метод Time.valueOf для преобразования строки «09:00:00» в объект Time следующим образом: Time.valueOf (LocalTime.parse («09:00:00»)).

Когда я вызываю getTime () для отображения значения, которое я получаю: 28800000 мс вместо 32400000 мс (рассчитано по калькулятору).

Ошибка при использовании Time.value Of? Потому что я не понимаю, почему я получаю неправильное значение.

Спасибо.

Ответы [ 2 ]

3 голосов
/ 27 апреля 2020

Это вызвано проблемами с часовыми поясами. Если вы сделаете

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

Перед вашим кодом вы получите 32400000, как вы ожидаете.

Time.valueOf (LocalTime.parse("09:00:00")) предполагает, что девятка находится в вашем местном часовом поясе, поэтому она преобразует его в UT C.

Например, если часовой пояс "Asia/Jerusalem" (вы можете смоделировать его с помощью TimeZone.setDefault(TimeZone.getTimeZone("Asia/Jerusalem"));, который был UTC + 2 на 1 января 1970 года, он преобразует 9 часов в 7 часов. Вы можете увидеть это с System.out.println(time.toGMTString());

Как всегда в вопросах о старом java API времени, я должен дать вам обязательную рекомендацию всегда использовать только modern post java8 api.

2 голосов
/ 27 апреля 2020

Придерживайтесь java .time.LocalTime

Я рекомендую придерживаться LocalTime из java .time, современного Java API даты и времени, и не использовать java.sql.Time. Последний класс плохо спроектирован, настоящий взлом на самом деле над уже плохо спроектированным java.util.Date классом. К счастью, он также давно устарел. Было время, когда нам требовался объект Time для хранения времени суток в столбце базы данных типа данных time или для передачи времени в запрос SQL с использованием этого типа данных. С JDB C 4.2 это уже не так. Теперь ваш драйвер JDB C принимает объект LocalTime и передает его значение времени в базу данных.

Итак, если у вас есть строка, проанализируйте ее в объект LocalTime так, как вы уже did:

    LocalTime time = LocalTime.parse("09:00:00");

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

    LocalTime time = LocalTime.of(9, 0);

Я не знаю, почему вы хотите преобразовать его в миллисекунды, но вы можете:

    int milliOfDay = time.get(ChronoField.MILLI_OF_DAY);
    System.out.println(milliOfDay);

Вывод:

32400000

Это значение, которое вы ожидали.

Чтобы вставить LocalTime в вашу базу данных:

    PreparedStatement ps = yourDatabaseConnection.prepareStatement(
            "insert into your_table(your_time_col) values (?)");
    ps.setObject(1, time);
    int rowsInserted = ps.executeUpdate();

Обратите внимание на использование setObject(), а не setTime().

Если вам нужен объект Time для какого-либо устаревшего API, который вы не хотите обновлять прямо сейчас, то сделанная вами конверсия верна.

Ваши ожидания не оправдались, ваша конверсия была правильной

Я сделал ошибку, когда использовал Time.value Of? Потому что я не понимаю, почему я получаю неправильное значение.

Нет, наоборот. Вы не ошиблись. И в этом случае вы получили правильное значение. Это плохой и запутанный дизайн Time, который подшучивает над вами (я сказал, что вы не должны использовать этот класс). Я не уверен, что это задокументировано, но Time.valueOf (LocalTime.parse("09:00:00")) дает вам объект Time, который внутренне содержит момент времени 1 января 1970 г. 09:00 в часовом поясе вашей JVM . Из полученного значения в миллисекундах, 28 800 000, кажется, что это время равно 08:00 UT C. Был ли ваш часовой пояс в UT C со смещением +01: 00 зимой 1970 года? Метод getTime() возвращает количество миллисекунд с 1 января 1970 г. 00:00 UT C.

...