java.time и JDBC 4.2 или новее
Я рекомендую вам использовать java.time, современный API даты и времени Java, для вашей работы с датой и временем. Класс java.sql.Timestamp
плохо разработан, настоящий хак поверх уже плохо спроектированного класса java.util.Date
. К счастью, оба тоже давно устарели. Возможно, вы подумали, что вам нужен Timestamp
для передачи значения даты и времени в вашу базу данных SQL. Начиная с JDBC 4.2 это уже не так.
Во-первых, чтобы проанализировать вашу строку:
DateTimeFormatter uiFormatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendPattern("XX")
.toFormatter();
String stringFromUi = "2020-01-20T05:40:34-0500";
OffsetDateTime dateTime = OffsetDateTime.parse(stringFromUi, uiFormatter);
System.out.println(dateTime);
Выведите это далеко:
2020-01-20T05:40:34-05:00
Я исправил вашу строку, однако. Он настолько близок к формату ISO 8601, что я был убежден, что он должен соответствовать этому стандарту. Если вы намеревались указать миллисекунды, не проблема, код будет работать и с дробью секунд, например 2020-01-20T05:40:30.334-0500
. Если бы вы могли убедить своих UI-специалистов отправлять строку с двоеточием в смещении, например, 2020-01-20T05:40:34-05:00
, вам не понадобился бы форматтер, но вы могли бы использовать OffsetDateTime.parse(String)
с одним аргументом.
Затем я предположил, что вы запросили Timestamp
для взаимодействия с вашей базой данных. И поскольку вы запросили Timestamp
с часовым поясом из ввода, я также предположил, что тип данных на стороне SQL — timestamp with time zone
. Что рекомендуется для временных меток. В этом случае, начиная с JDBC 4.2, вы напрямую передаете наш OffsetDateTime
драйверу JDBC. Для упрощенного примера:
PreparedStatement ps = yourDatabaseConnection.prepareStatement(
"insert into your_table(your_timestamp_with_time_zone_column) values (?);");
ps.setObject(1, dateTime);
int rowsInserted = ps.executeUpdate();
Если вам нужен Timestamp
для какого-то устаревшего API, который вы не можете позволить себе изменить прямо сейчас, сначала знайте, что java.sql.Timestamp
не может иметь часовой пояс или смещение от UTC. Хороший способ получить Timestamp
— преобразовать Instant
, другой современный класс:
Instant instant = dateTime.toInstant();
Timestamp ts = Timestamp.from(instant);
System.out.println(ts);
Вывод в моем часовом поясе, Европа/Копенгаген:
2020-01-20 11:40:34.0
Это правильно, даже если может показаться, что это 6 часов неправильно. Европа/Копенгаген в январе был со смещением UTC +01:00. Когда мы печатаем Timestamp
, мы неявно вызываем его метод toString
. Timestamp.toString()
использует настройку часового пояса JVM для рендеринга возвращаемой строки. Таким образом, ваша строка даты и времени теперь была преобразована сначала из смещения UTC -05:00 в какой-то внутренний формат, о котором нам не нужно заботиться, а затем в смещение +01:00
, разница в 6 часов с начальной точки.
Ссылки
person
Ole V.V.
schedule
30.04.2020
java.sql.Timestamp
. Этот класс плохо разработан и давно устарел. Вместо этого используйте либоOffsetDateTime
, либоLocalDateTime
, оба из java.time, современного API даты и времени Java< /а>. - person Ole V.V.   schedule 30.04.2020timestamp
без часового пояса илиtimestamp with time zone
? (Последнее рекомендуется.) - person Ole V.V.   schedule 30.04.20202020-01-20'T'05:40:334-0500
не совсем верно? (1) Хотя у вас есть одинарные кавычки вокругT
в шаблоне формата, вы не должны этого делать в самой строке. (2) Это 334 секунды после 05:40 утра??! Наверное опечатка? - person Ole V.V.   schedule 30.04.2020