tibo的回答是正确的。我的其他想法如下。
采用TIMESTAMP WITH TIME ZONE
您提到TIMESTAMP WITHOUT TIME ZONE
在 Postgres 中使用数据类型。该类型仅适用于与任何特定时区无关的日期时间。例如,“圣诞节从 2015 年 12 月 25 日午夜开始”翻译为任何特定时区的不同时刻。例如,圣诞节在巴黎比在蒙特利尔更早开始。这种数据类型很少适用于业务应用程序。请参阅此 Postgres 专家的帖子,始终使用 TIMESTAMP WITH TIME ZONE。
在 Postgres 中,另一种类型的TIMESTAMP WITH TIME ZONE
意思是“尊重时区”。使用传入数据与 UTC 或时区信息的任何偏移都用于调整为 UTC。然后丢弃伴随的偏移量或时区信息。一些数据库保留此信息,但不保留 Postgres。
您的声明:
该数据库在 PostgreSQL 中。数据库已配置亚洲/德黑兰时区。
…没有意义。数据类型TIMESTAMP WITHOUT TIME ZONE
没有时区(尽管您可能将其视为 UTC),并且数据类型TIMESTAMP WITH TIME ZONE
始终为UTC。关于存储日期时间值,没有这样的时区配置。
您可能的意思是数据库会话的默认时区设置为德黑兰时区。见SET TIME ZONE
命令。但该设置只是装点门面,在生成日期时间值的字符串表示时应用。当使用 JDBC 和 java.sql.Timestamp 类时,该会话设置是无关紧要的,因为 Postgres 没有生成任何字符串。您对时区的关注应该放在 Java 端(参见下面的代码)而不是 Postgres。
一般来说,您的主机服务器操作系统应设置为 UTC。但是您的应用程序的代码不应该依赖于此,而是指定任何所需/预期的时区。
java.time
在 Java 8 及更高版本中,新的 java.time 包取代了旧的 java.util.Date/.Calendar 类。这些新类受到 JSR 310 定义的 Joda-Time 库的启发,并由ThreeTen-Extra项目扩展。
最终 JDBC 驱动程序将被更新以直接处理这些新类型。同时使用添加到旧类和新类中的转换方法。
java.sql.Timestamp ts = myResultSet.getTimestamp( 1 );
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
或者给定您从Unix 时间纪元开始的整秒数,构造一个 Instant。
long secondsSinceUnixEpoch = 1_333_436_817L ;
Instant instant = Instant.ofEpochSecond( secondsSinceUnixEpoch );
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );