PostgreSQL日期与Java即时

时间:2019-02-21 13:10:52

标签: java postgresql date java.time.instant

假设我在Java应用程序中有一个类型为Instant的字段,并将其存储为PostgreSQL类型为DATE

例如,如果我保存21.02.2019 14:03:59,它将存储为21.02.2019,但是当我从数据库中读取时如何重新翻译?

会是:

  • 21.02.2019 00:00:00.000
  • 21.02.2019 23:59:59.000吗?

PS。我知道我应该改用Timestamp:)

2 个答案:

答案 0 :(得分:2)

这取决于您的阅读方式。 Instant和SQL DATE不等效,而且我不知道任何可靠的库甚至可以让您将DATE读到Instant。如果您编写自己的代码允许这样做,那么即使没有任何意义,也可以使其以小时,分钟,秒和毫秒的方式填充,即使这没有任何意义(因此,对您问题的真正回答是“除非您明确编写代码以将java.sql.Date转换为java.time.Instant)。

如果您正在设计将瞬间存储为日期的软件,则说明您的设计存在缺陷。在Java端使用LocalDate,或在数据库中使用TIMESTAMP

答案 1 :(得分:1)

tl; dr

  • 符合SQL标准的数据库(例如Postgres)中的DATE列仅存储日期,时间和区域。
  • 使用LocalDate作为仅日期的值,没有时间和区域。
  • 要从LocalDate中获取Instant,请指定要确定日期的特定区域(时区)的人们使用的挂钟时间。
  • 如果要存储时刻(由Instant对象表示),请使用SQL标准类型TIMESTAMP WITH TIME ZONE而不是DATE

详细信息

Instant位于UTC

Instant对象代表UTC中的时刻,始终为UTC。换句话说,offset-from-UTC为零时分秒的时刻。

确定日期需要时区

因此,从Instant获取日期需要一个time zone(一个ZoneId)。巴黎午夜过后的一刻,法国是一个新的约会日期,例如 23日,而在魁北克省蒙特利尔,它仍然是“昨天” 22日。在任何给定时刻,日期都会在全球范围内变化。

因此,如果您要指的是魁北克省的日期,请指定时区“美国/蒙特利尔”。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

您说您的数据库列的类型为DATE。在Postgres中,就像SQL标准一样,它表示仅日期的值,没有日期和时区。

要仅存储日期(没有日期和时区),请提取LocalDate。 “本地”一词的意思是任何个地方或所有个地方,但不是任何一个特定地方。

LocalDate ld = zdt.toLocalDate() ;

JDBC 4.2

通过占位符在准备好的语句中交换LocalDate

myPreparedStatement.setObject( … , ld ) ; 

检索:

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

存储日期,获取日期

  

当我从数据库中读取时,它将如何重新翻译?

     

会是:

     

21.02.2019 00:00:00.000或…

这个问题没有道理。当您从符合SQL标准的数据库(如Postgres)中读取DATE时,您将获得一个日期,只有一个日期-没有日期,也没有时区。

如果将值LocalDate的{​​{1}}存储在2019-02-21列中,则会得到相同的结果:值DATE的{​​{1}}。

一天中的第一时刻

如果要在一天的第一时刻添加时间,请 java.time 为您确定。在某些时区的某些日期,日期不是不是开始于00:00:00,而是开始于01:00:00之类的时间。

LocalDate

UTC

如果您要使用UTC作为时区从2019-02-21中提取日期,即从UTC偏移零小时-分钟-秒,请使用LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ; ZoneId z = ZoneId.of( "Pacific/Auckland" ) ; ZonedDateTime zdt = ld.atStartOfDay( z ) ; // Returns a `ZonedDateTime` object set to the first moment of the day as seen on that date in that time zone. May or may not be the time 00:00:00. 类和常量ZoneOffset.UTC

Instant

关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要OffsetDateTime类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore