Невозможно воспроизвести ваш тестовый сбой
Ваш код:
LocalDate.parse( "1900-01-01" )
… работает в соответствии с документацией, выдавая значение 1 января 1900 года.
LocalDate ld = LocalDate.parse("1900-01-01") ;
System.out.println( ld ) ;
См. код запускается на IdeOne.com .
1900-01-01
must В вашем коде должно быть больше, чем вы нам показали .
Пример приложения с использованием H2
Вы сказали:
Полагаю, что изменение сделано во время действия сохранения в базе данных H2.
Давайте попробуем. Вот целый пример приложения с использованием H2 версии 1.4.200. Запускается из IntelliJ 2020.1 в macOS Mojave с Java 14.
У нас есть таблица event_
с id_
столбцом типа UUID и столбцом when_
типа LocalDate
. Мы записываем одно значение для значения 1900-01-01.
Как вы можете видеть, если вы запустите этот код, мы получим LocalDate
объект, для которого метод toString
возвращает 1900-01-01
.
package work.basil.example;
import org.h2.jdbcx.JdbcDataSource;
import java.sql.*;
import java.time.LocalDate;
import java.util.Objects;
import java.util.UUID;
public class H2Example
{
public static void main ( String[] args )
{
H2Example app = new H2Example();
app.doIt();
}
private void doIt ( )
{
JdbcDataSource dataSource = Objects.requireNonNull( new JdbcDataSource() ); // Implementation of `DataSource` bundled with H2.
dataSource.setURL( "jdbc:h2:mem:localdate_example_db;DB_CLOSE_DELAY=-1" ); // Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
dataSource.setUser( "scott" );
dataSource.setPassword( "tiger" );
String sql = null;
try (
Connection conn = dataSource.getConnection() ;
)
{
String tableName = "event_";
sql = "CREATE TABLE " + tableName + " (\n" +
" id_ UUID DEFAULT random_uuid() PRIMARY KEY ,\n" +
" when_ DATE NOT NULL\n" +
");";
try ( Statement stmt = conn.createStatement() ; )
{
stmt.execute( sql );
}
// Insert row.
sql = "INSERT INTO event_ ( when_ ) " + "VALUES ( ? ) ;";
try (
PreparedStatement preparedStatement = conn.prepareStatement( sql ) ;
)
{
LocalDate localDate = LocalDate.parse( "1900-01-01" );
preparedStatement.setObject( 1 , localDate ); // Yesterday.
preparedStatement.executeUpdate();
}
// Query all.
sql = "SELECT * FROM event_ ;";
try (
Statement stmt = conn.createStatement() ;
ResultSet rs = stmt.executeQuery( sql ) ;
)
{
while ( rs.next() )
{
//Retrieve by column name
UUID id = rs.getObject( "id_" , UUID.class ); // Pass the class to be type-safe, rather than casting returned value.
LocalDate localDate = rs.getObject( "when_" , LocalDate.class ); // Ditto, pass class for type-safety.
//Display values
System.out.println( "id_: " + id + " | when_: " + localDate );
}
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
}
}
Когда приложение этого примера запускается :
id_: 949830e0-77c8-49a3-8804-0972ff70ca2 c | когда_: 1900-01-01
Не полагаться на часовой пояс по умолчанию
Ваш код:
TimeZone.setDefault (TimeZone. getTimeZone ("UT C"));
… довольно рискован при развертывании. Установка часового пояса немедленно влияет на весь код во всех потоках всех приложений, работающих в этой JVM. Возможно, вы вытаскиваете ковер из-под ног других приложений или других частей вашего собственного приложения.
➥ Лучше никогда не полагаться на текущий часовой пояс JVM по умолчанию.
Чтобы зафиксировать текущий момент, показанный в UT C, просто позвоните Instant.now
. Instant
представляет момент в UT C с разрешением наносекунд. Этот класс заменяет java.util.Date
.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
Для работы с базой данных используйте более гибкий класс OffsetDateTime
. Спецификация JDB C 4.2 необъяснимо требует поддержки OffsetDateTime
, но не более широко используемых Instant
и ZonedDateTime
.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ; // Capture the current moment in UTC.
Запишите это в базу данных.
myPreparedStatement.setObject( … , odt ) ;
Извлечение.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
При записи момента (точная c точка на временной шкале), например, представленного OffsetDateTime
, ваш столбец в базе данных должен иметь тип данных, близкий к SQL стандартный тип TIMESTAMP WITH TIME ZONE
( не WITHOUT
). Во H2, тип данных для использования имеет то же имя, TIMESTAMP WITH TIME ZONE
.