无法重现您的测试失败
你的代码:
LocalDate.parse( "1900-01-01" )
…按照记录工作,生成 1900 年 1 月 1 日的值。
LocalDate ld = LocalDate.parse("1900-01-01") ;
System.out.println( ld ) ;
看到那个代码在 IdeOne.com 上实时运行 https://ideone.com/SzzeJ2.
1900-01-01
➥ 您的代码一定比您向我们展示的更多。
使用 H2 的示例应用程序
你说:
我猜想更改是在 H2 数据库的保存操作期间进行的。
我们来试试吧。这是使用 H2 版本 1.4.200 的完整示例应用程序。在 macOS Mojave 上使用 Java 14 从 IntelliJ 2020.1 运行。
我们有一张桌子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-0972ff70ca2c |当_:1900-01-01
不要依赖默认时区
你的代码:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
……部署时风险很大。设置时区会立即影响该 JVM 中运行的所有应用程序的所有线程中的所有代码。您可能会从其他应用程序或您自己的应用程序的其他部分中拔出地毯。
➥ 最好不要依赖 JVM 当前的默认时区。
要捕获 UTC 中的当前时刻,只需调用Instant.now
. An Instant
表示 UTC 中的一个时刻,分辨率为纳秒。这个类取代了java.util.Date
.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
对于数据库工作,使用更灵活的类OffsetDateTime
。 JDBC 4.2 规范莫名其妙地需要支持OffsetDateTime
但不是更常用的Instant
and ZonedDateTime
.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ; // Capture the current moment in UTC.
将其写入数据库。
myPreparedStatement.setObject( … , odt ) ;
恢复。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
记录某个时刻(时间轴上的特定点)时,例如由OffsetDateTime
,数据库中的列必须是类似于 SQL 标准类型的数据类型TIMESTAMP WITH TIME ZONE
(not WITHOUT
)。在 H2 中,要使用的数据类型就是这个名字,TIMESTAMP WITH TIME ZONE https://h2database.com/html/datatypes.html#timestamp_with_time_zone_type.