Спецификация JDBC не определяет никаких деталей относительно часового пояса.Тем не менее, большинство из нас знает, что приходится сталкиваться с противоречиями часового пояса JDBC;просто посмотрите на все вопросы StackOverflow !
В конечном счете, обработка часового пояса для типов баз данных даты / времени сводится к серверу баз данных, драйверу JDBC и всему промежуточному.Вы даже во власти ошибок драйвера JDBC;PostgreSQL исправил ошибку в версии 8.3 , где
Методы Statement.getTime, .getDate и .getTimestamp, которые передаются объекту Calendar, вращали часовой пояс в неправильном направлении.
Когда вы создаете новую дату, используя new Date(0)
(допустим, вы используете Oracle JavaSE java.sql.Date
, ваша дата создается
с использованиемзаданное значение времени в миллисекундах. Если указанное значение в миллисекундах содержит информацию о времени, драйвер установит временные компоненты на время в часовом поясе по умолчанию (часовом поясе виртуальной машины Java, на которой выполняется приложение), что соответствует нулю по Гринвичу.
Итак, new Date(0)
должен использовать GMT.
Когда вы вызываете ResultSet.getDate(int)
, вы выполняете реализацию JDBC. Спецификация JDBC не делаетдиктовать, как реализация JDBC должна обрабатывать детали часового пояса, поэтому вы находитесь в зависимости от реализации. Глядя на Oracle 11g oracle.sql.DATE
JavaDoc, он неeem Oracle DB хранит информацию о часовом поясе, поэтому она выполняет свои собственные преобразования, чтобы получить дату в java.sql.Date
.У меня нет опыта работы с Oracle DB, но я предполагаю, что реализация JDBC использует настройки часового пояса сервера и вашей локальной JVM для преобразования из oracle.sql.DATE
в java.sql.Date
.
Вы упомянуличто несколько реализаций СУБД правильно обрабатывают часовой пояс, за исключением SQLite.Давайте рассмотрим, как H2 и SQLite работают при отправке значений даты в драйвер JDBC и при получении значений даты из драйвера JDBC.
Драйвер H2 JDBCPrepStmt.setDate(int, Date)
использует ValueDate.get(Date)
, который вызывает DateTimeUtils.dateValueFromDate(long)
, который выполняет преобразование часового пояса.
Использование этого SQLiteДрайвер JDBC , PrepStmt.setDate(int, Date)
вызывает PrepStmt.setObject(int, Object)
и не выполняет преобразование часового пояса.
Драйвер JDBC H2 JdbcResultSet.getDate(int)
возвращает get(columnIndex).getDate()
.get(int)
возвращает H2 Value
для указанного столбца.Поскольку тип столбца DATE
, H2 использует ValueDate
.ValueDate.getDate()
вызывает DateTimeUtils.convertDateValueToDate(long)
, что в конечном итоге создает java.sql.Date
после преобразования часового пояса.
Использование этого драйвера SQLite JDBC код RS.getDate(int)
намного проще;он просто возвращает java.sql.Date
, используя значение даты long
, хранящееся в базе данных.
Таким образом, мы видим, что драйвер JDBC H2 хорошо разбирается в обработке часовых поясов с датами, а драйвер SQLite JDBC - нет.(Нельзя сказать, что это решение не является разумным, оно может хорошо подойти к проектным решениям SQLite).Если вы будете искать источник для других драйверов RDBMS JDBC, о которых вы упомянули, вы, вероятно, обнаружите, что большинство приближается к дате и часовому поясу аналогично тому, как это делает H2.
Хотя спецификации JDBC не детализируют времяобработка зон, имеет смысл, что разработчики реализации RDBMS и JDBC приняли во внимание часовой пояс и будут обрабатывать его должным образом;особенно если они хотят, чтобы их продукция продавалась на мировой арене.Эти дизайнеры чертовски умны, и я не удивлен, что большинство из них понимают это правильно, даже при отсутствии конкретной спецификации.
Я нашел этот блог по Microsoft SQL Server, Используя времяданные о зонах в SQL Server 2008 , в которых объясняется, как часовой пояс усложняет ситуацию:
часовые пояса представляют собой сложную область, и каждому приложению необходимо будет указать, как вы собираетесь обрабатывать данные часового пояса, чтобы сделатьпрограммы более удобные для пользователя.
К сожалению, в настоящее время не существует международного стандарта для имен и значений часовых поясов. Каждая система должна использовать систему по своему выбору, и пока не существует международного стандарта, невозможно попытаться сделать так, чтобы SQL Server ее предоставил, и в конечном итоге это вызовет больше проблем, чем решит.