java .time и JDB C 4.2 или более поздней версии
Я рекомендую использовать java .time, современный Java API даты и времени, для работы с датой и временем. Класс java.sql.Timestamp
плохо спроектирован, настоящий взлом на фоне уже плохо спроектированного класса java.util.Date
. К счастью, оба они также давно устарели. Возможно, вы подумали, что вам нужна Timestamp
для передачи значения даты и времени в вашу базу данных SQL. Начиная с JDB C 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
. Что рекомендуется для отметок времени. В этом случае начиная с JDB C 4.2 вы напрямую передаете наш OffsetDateTime
драйверу JDB C. Для упрощенного примера:
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
не может иметь часовой пояс или смещение от UT C. Хороший способ получить Timestamp
- это конвертировать из Instant
, другого современного класса:
Instant instant = dateTime.toInstant();
Timestamp ts = Timestamp.from(instant);
System.out.println(ts);
В моем часовом поясе, Европа / Копенгаген, получается:
2020-01-20 11: 40: 34.0
Это правильно, хотя может показаться, что это 6 часов неправильно. Европа / Копенгаген был в UT C со смещением +01: 00 в январе. Когда мы печатаем Timestamp
, мы неявно вызываем его метод toString
. Timestamp.toString()
использует настройку часового пояса JVM для визуализации возвращаемой строки. Таким образом, ваша строка даты и времени была сначала преобразована из UT C offset -05: 00 в какой-то внутренний формат, который нам не нужен, а затем в смещение +01:00
, разница в 6 часов от начального точка.
Ссылки