假设我在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
:)
答案 0 :(得分:2)
这取决于您的阅读方式。 Instant
和SQL DATE
不等效,而且我不知道任何可靠的库甚至可以让您将DATE
读到Instant
。如果您编写自己的代码允许这样做,那么即使没有任何意义,也可以使其以小时,分钟,秒和毫秒的方式填充,即使这没有任何意义(因此,对您问题的真正回答是“除非您您明确编写代码以将java.sql.Date
转换为java.time.Instant
)。
如果您正在设计将瞬间存储为日期的软件,则说明您的设计存在缺陷。在Java端使用LocalDate
,或在数据库中使用TIMESTAMP
。
答案 1 :(得分:1)
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() ;
通过占位符在准备好的语句中交换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作为时区从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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要OffsetDateTime
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。