tl; dr
myPreparedStatement.setObject( // Pass java.time objects directly to database, as of JDBC 4.2.
… , // Indicate which placeholder in your SQL statement text.
OffsetDateTime.parse( // Parse input string as a `OffsetDateTime` as it indicates an offset-from-UTC but not a time zone.
"20180531_132001Z" , // Define a formatting pattern to match your particular input.
DateTimeFormatter.ofPattern( "uuuuMMdd_HHmmssX" ) // TIP: When exchanging date-time values as text, use use standard ISO 8601 formats rather than inventing your own.
) // Returns a `OffsetDateTime` object.
.toInstant() // Returns a `Instant` object, always in UTC by definition.
)
Подробности
В других ответах есть некоторая полезная информация, но все они содержат некоторую дезинформацию, которую я пытался исправить, публикуя комментарии.
Самое главное, ваш код использует неправильный класс Java и неверный тип данных базы данных для данного ввода.
Ниже приведено объяснение вместе с полным примером кода с использованием современного java.time классы с JDBC 4.2 или более поздней версии.
Z
= UTC
DateTimeFormatter.ofPattern ("yyyyMMdd_HHmmss'Z '")
Никогда не ставьте одинарные кавычки вокруг важных частей вашего ввода, как вы сделали здесь с Z
.Это Z
означает UTC и произносится как «зулу».Он говорит нам, что текст даты и времени суток следует интерпретировать как использование часового времени UTC, а не, скажем, America/Montreal
или Pacific/Auckland
часовых поясов.
не используйте LocalDateTime
для таких входов. В этом классе отсутствует понятие часового пояса или смещения от UTC.Таким образом, этот класс не представляет момент и является не точкой на временной шкале.LocalDateTime
представляет набор потенциальных моментов в диапазоне около 26-27 часов (во всех часовых поясах).Используйте LocalDateTime
, когда вы имеете в виду любые или все часовые пояса, а не одну конкретную зону / смещение.Напротив, Z
говорит нам, что этот ввод использует время по часам UTC.
Синтаксический анализ
Определение шаблона форматирования для соответствия всем важным частям вашей входной строки.
String input = "20180531_132001Z" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMdd_HHmmssX" ) ;
Кстати, когда это возможно, используйте стандартные форматы ISO 8601 , а не пользовательский формат, как показано в вашем вопросе.Эти форматы разработаны так, чтобы их было легко анализировать на машине и легко читать людям в разных культурах, устраняя при этом неоднозначность.
Анализировать как OffsetDateTime
, потому что ваш ввод показывает смещение от UTC (ноль часов).Смещение от UTC - это просто количество часов и минут, ни больше, ни меньше.
Используйте класс ZonedDateTime
только в том случае, если во входной строке указан часовой пояс .Часовой пояс имеет имя Contintent/Region
, например Africa/Tunis
.Зона представляет историю прошлых, настоящих и будущих изменений в смещении, используемом людьми определенного региона.
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;
odt.toString (): 2018-05-31T13: 20: 01Z
База данных
Чтобы сообщить об этом моменте базе данных, используя JDBC 4.2 и выше, мы можем напрямую передать java.time object.
myPreparedStatement.setObject( … , odt ) ;
Если ваш драйвер JDBC не принимает OffsetDateTime
, извлеките более простой класс Instant
.Instant
всегда в UTC, по определению.
Instant instant = odt.toInstant() ;
myPreparedStatement.setObject( … , instant ) ;
И поиск.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Осторожно - неверный тип данных в вашей базе данных
Я не пользователь MS SQL Server, но согласно этодокументация , тип данных столбца DATETIME2
не подходит для вашего ввода.Этот тип данных, кажется, эквивалентен стандартному типу SQL DATETIME WITHOUT TIME ZONE
.Такой тип никогда не должен использоваться при записи определенного момента в истории.
В отсутствие какой-либо концепции часового пояса или смещения от UTC этот тип столбца следует использовать только для трех ситуаций:
- Зона или смещение неизвестно .Это плохо.Это неверные данные.Аналогично наличию цены / стоимости без знания валюты.Вы должны отвергать такие данные, а не хранить их.
- Намерение «везде» , как в каждом часовом поясе.Например, корпоративная политика, которая гласит: «Все наши фабрики будут работать на обед в 12:30» означает, что фабрика в Дели сломается за несколько часов до фабрики в Дюссельдорфе, которая ломается за несколько часов до фабрики в Детройте.
- A speНамечается важный момент в будущем, но мы боимся политиков переопределить часовой пояс .Правительства меняют правила своих часовых поясов с удивительной частотой и с удивительно небольшим предупреждением (даже [без предупреждения] [10]).Поэтому, если вы хотите записаться на прием в 3 часа дня на определенную дату, и вы действительно имеете в виду 3 часа дня, независимо от какого-либо сумасшедшего решения, которое правительство может принять за это время, сохраните
LocalDateTime
.Чтобы распечатать отчет или отобразить календарь, динамически примените часовой пояс (ZoneId
), чтобы сгенерировать определенный момент (ZonedDateTime
или Instant
).Это нужно делать на лету, а не сохранять значение.
Поскольку ваш ввод - это определенный момент, определенная точка на временной шкале, вы должны хранить его в базе данных, используя столбецтип сродни стандартному SQL-типу TIMESTAMP WITH TIME ZONE
.
О 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 .