在 java.util.Date 或 java.sql.Date 之间进行选择
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24650186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Choosing between java.util.Date or java.sql.Date
提问by Carlos Goce
Should I use java.util.Date or java.sql.Date?
我应该使用 java.util.Date 还是 java.sql.Date?
I have a VisualFox database and I have retrieved the entities with the IntelliJ Idea wizard using an appropiate jdbc type 4 driver.
我有一个 VisualFox 数据库,并且使用合适的 jdbc 类型 4 驱动程序通过 IntelliJ Idea 向导检索了实体。
The ide (or the driver) has created the date fields as Timestamp. However, the date fields are not timestamps but Date fields, they store year, month and day only.
ide(或驱动程序)已将日期字段创建为时间戳。但是,日期字段不是时间戳而是日期字段,它们仅存储年、月和日。
So I wonder if I should switch to java.util.Date or java.sql.Date. At first glance I thought that java.sql.Date should be the appropiate one, but it has many methods declared as deprecated.
所以我想知道我是否应该切换到 java.util.Date 或 java.sql.Date。乍一看,我认为 java.sql.Date 应该是合适的,但它有许多方法声明为已弃用。
采纳答案by Basil Bourque
tl;dr
tl;博士
Should I use java.util.Date or java.sql.Date?
我应该使用 java.util.Date 还是 java.sql.Date?
Neither.
两者都不。
Both are obsolete as of JDBC4.2 and later. Use java.timeclasses instead.
从JDBC4.2 及更高版本开始,两者都已过时。改用java.time类。
- date-only value
For a database type akin to SQL-standardDATE
, usejava.time.LocalDate
.LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
myPreparedStatement.setObject( ld , … ) ;
- date with time-of-day in UTC value
For a database type akin to SQL-standardTIMESTAMP WITH TIME ZONE
, usejava.time.Instant
.Instant instant = myResultSet.getObject( … , Instant.class ) ;
myPreparedStatement.setObject( instant , … ) ;
- date-only 值
对于类似于 SQL-standard 的数据库类型DATE
,请使用java.time.LocalDate
.LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
myPreparedStatement.setObject( ld , … ) ;
- date with time-of-day in UTC value
对于类似于 SQL-standard 的数据库类型TIMESTAMP WITH TIME ZONE
,使用java.time.Instant
.Instant instant = myResultSet.getObject( … , Instant.class ) ;
myPreparedStatement.setObject( instant , … ) ;
Details
细节
The question and other answers seem to be over-thinking the issue. A java.sql.Dateis merely a java.util.Datewith its time set to 00:00:00
.
问题和其他答案似乎过度思考了这个问题。一个java.sql.Date仅仅是一个java.util.Date其时间设置为00:00:00
。
From the java.sql.Date doc(italicized text is mine)…
从java.sql.Date 文档(斜体文本是我的)...
Class Date
java.lang.Object
????java.util.Date????????← Inherits from j.u.Date
????????java.sql.Date
…
A thin wrapper around a millisecond value that allows JDBC to identify this as an SQL DATE value. A milliseconds value represents the number of milliseconds that have passed since January 1, 1970 00:00:00.000 GMT.??← Time-of-day set to Zero, midnight GMT/UTC
To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.
上课日期
对象
??????java.util.Date???????? ← 继承自 juDate
????????java.sql.Date
…
毫秒值的薄包装器,允许 JDBC 将其标识为 SQL DATE 值。毫秒值表示自 1970 年 1 月 1 日 00:00:00.000 GMT 以来经过的毫秒数。?? ← 时间设置为零,午夜 GMT/UTC
为了符合 SQL DATE 的定义,java.sql.Date 实例包装的毫秒值必须通过在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零来“标准化” .
Date-Only versus Date-Time
仅日期与日期时间
The core problem is:
核心问题是:
- SQL
In SQL, theDATE
data type stores a date-only, without a time-of-day. - JAVA
In the badly designed date-time library bundled with the early versions of Java, they failed to include a class to represent a date-only.
- SQL
在 SQL 中,DATE
数据类型只存储日期,不存储时间。 - JAVA
在与早期 Java 版本捆绑在一起的设计糟糕的日期时间库中,它们未能包含一个表示仅日期的类。
Instead of creating a date-only class, the Java team made a terrible hack. They took their date-time class (the misnamed java.util.Date
class, containing both date andtime) and extended it to have an instance set its time-of-day to midnight UTC, 00:00:00
. That hack, that subclass of j.u.Date, is java.sql.Date
.
Java 团队没有创建一个仅限日期的类,而是做了一个可怕的 hack。他们采用了日期时间类(错误命名的java.util.Date
类,包含日期和时间)并将其扩展为有一个实例将其时间设置为UTC午夜, 00:00:00
。那个hack,juDate的子类,是java.sql.Date
.
All this hacking, poor design, and misnaming has made a confusing mess.
所有这些黑客行为、糟糕的设计和错误的命名都造成了混乱。
Which To Use
使用哪个
So when to use which? Simple, after cutting through the confusion.
那么什么时候使用哪个?简单,在消除混乱之后。
- When reading or writing to a database's date-only column, use
java.sql.Date
as it clumsily tries to mask its time-of-day. - Everywhere else in Java, where you need a time-of-dayalong with your date, use
java.util.Date
. - When you have a java.sql.Date in hand but need a java.util.Date, simply pass the java.sql.Date. As a subclass, a java.sql.Date isa java.util.Date.
- 读取或写入数据库的仅日期列时,请使用
java.sql.Date
它,因为它笨拙地试图掩盖其时间。 - 在 Java 中的其他任何地方,如果您需要一天中的时间和日期,请使用
java.util.Date
. - 当您手头有 java.sql.Date 但需要 java.util.Date 时,只需传递 java.sql.Date。作为子类,java.sql.Date是java.util.Date。
Even Better
更好
In modern Java, you now have a choice of decent date-time libraries to supplant the old and notoriously troublesome java.util.Date, Calendar, SimpleTextFormat, and java.sql.Date classes bundled with Java. The main choices are:
在现代 Java 中,您现在可以选择合适的日期时间库来取代与 Java 捆绑在一起的旧的、臭名昭著的麻烦 java.util.Date、Calendar、SimpleTextFormat 和 java.sql.Date 类。主要选择有:
- Joda-Time
- java.time
(inspired by Joda-Time, defined by JSR 310, bundled with Java 8, extended by the ThreeTen-Extraproject)
Both offer a LocalDate
class to represent a date only, with no time-of-day and no time zone.
两者都提供一个LocalDate
仅表示日期的类,没有时间和时区。
A JDBC driverupdated to JDBC 4.2 or later can be used to directly exchange java.timeobjects with the database. Then we can completely abandon the ugly mess that is the date-time classes in the java.util.* and java.sql.* packages.
一个JDBC驱动程序更新到JDBC 4.2或更高版本可用于直接交换java.time与数据库对象。然后我们可以完全放弃 java.util.* 和 java.sql.* 包中日期时间类的丑陋混乱。
setObject | getObject
设置对象 | 获取对象
This articlepublished by Oracle explains that the JDBC in Java 8 has been updated transparently to map a SQL DATE
value to the new java.time.LocalDate type if you call getObject
and setObject
methods.
Oracle 发布的这篇文章解释说,Java 8 中的 JDBC 已被透明更新,DATE
如果您调用getObject
和setObject
方法,则将SQL值映射到新的 java.time.LocalDate 类型。
In obtuse language, the bottom of the JDBC 4.2 update specconfirms that article, with new mappings added to the getObject
and setObject
methods.
在钝语言中,JDBC 4.2 更新规范的底部证实了该文章,并在getObject
和setObject
方法中添加了新映射。
myPreparedStatement.setObject( … , myLocalDate ) ;
…and…
…和…
LocalDate myLocalDate = myResultSet.getObject( … , LocalDate.class ) ;
Convert
转变
The spec also says new methods have been added to the java.sql.Date class to convert back and forth to java.time.LocalDate.
该规范还表示,新方法已添加到 java.sql.Date 类中,以便来回转换为 java.time.LocalDate。
public java.time.instant toInstant()
public java.time.LocalDate toLocalDate()
public static java.sql.Date valueOf(java.time.LocalDate)
public java.time.instant toInstant()
public java.time.LocalDate toLocalDate()
public static java.sql.Date valueOf(java.time.LocalDate)
Time Zone
时区
The old java.util.Date
, java.sql.Date
, and java.sql.Timestamp
are always in UTC. The first two (at least) have a time zone buried deep in their source code but is used only under-the-surface such as the equals
method, and has no getter/setter.
旧的java.util.Date
、java.sql.Date
和java.sql.Timestamp
始终使用UTC。前两个(至少)在其源代码中深埋了一个时区,但仅在表面下使用,例如equals
方法,并且没有 getter/setter。
More confusingly, their toString
methods apply the JVM's current default time zone. So to the na?ve programmer it seemslike they have a time zone but they do not.
更令人困惑的是,他们的toString
方法应用了 JVM 当前的默认时区。所以对于天真的程序员来说,他们似乎有一个时区,但他们没有。
Both the buried time zone and the toString
behavior are two of many reasons to avoid these troublesome old legacy classes.
隐藏时区和toString
行为都是避免这些麻烦的旧遗留类的众多原因中的两个。
Write your business logic using java.time(Java 8 and later). Where java.time lacks, use Joda-Time. Both java.time and Joda-Time have convenient methods for going back and forth with the old classes where need be.
使用java.time(Java 8 及更高版本)编写业务逻辑。在 java.time 缺乏的地方,使用Joda-Time。java.time 和 Joda-Time 都有方便的方法来在需要的地方来回使用旧类。
Replacements:
更换:
java.util.Date
is replaced byjava.time.Instant
java.sql.Timestamp
is replaced byjava.time.Instant
java.sql.Date
is replaced byjava.time.LocalDate
.java.sql.Time
is replaced byjava.time.LocalTime
.
java.util.Date
被替换为java.time.Instant
java.sql.Timestamp
被替换为java.time.Instant
java.sql.Date
由 代替java.time.LocalDate
。java.sql.Time
由 代替java.time.LocalTime
。
The Instant
class represents a moment on the timeline in UTCwith a resolution of nanoseconds(up to nine (9) digits of a decimal fraction).
该Instant
级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。
All three java.time.Local…
classes are all lacking any concept of time zoneor offset-from-UTC.
所有三个java.time.Local…
类都缺乏任何时区概念或offset-from-UTC。
About java.time
关于java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*
classes.
您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8, Java SE 9, Java SE 10, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9、Java SE 10及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- java.time 类的更高版本的 Android 捆绑实现。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
回答by kostja
In general, I find it advisable to use the java.util.Date
, since you can use it anywhere in your program without either converting the type or polluting your application with SQL-specific code.
通常,我认为最好使用java.util.Date
,因为您可以在程序中的任何位置使用它,而无需转换类型或使用 SQL 特定代码污染您的应用程序。
I am not aware of a scenario where 'java.sql.Date' would be a better fit.
我不知道“java.sql.Date”更适合的场景。
回答by Petr Mensik
Well, according to this articleyou can use javax.sql.Date
without @Temporal
annotation which can save some coding from you. However java.util.Date
is easier to use across your whole application.
好吧,根据这篇文章,您可以在javax.sql.Date
没有@Temporal
注释的情况下使用,这可以节省您的一些编码。但是java.util.Date
在整个应用程序中更易于使用。
So I would use
所以我会用
@Column(name = "date")
@Temporal(TemporalType.DATE)
private java.util.Date date;
回答by Sandeep Kumar
According to Java doc, it is suggested to use appropriate Date type as per underlying database. However, with Java 8, a rich set of classes under java.time package have been provided and it must be used if application is written with Java 8.
根据 Java 文档,建议根据底层数据库使用适当的 Date 类型。但是,Java 8 在 java.time 包下提供了一组丰富的类,如果应用程序是用 Java 8 编写的,则必须使用它。
The class javaxjava.sql.Date extends java.util.Date with minor changes for miliseconds container so that it can support the Database DATE type effectively. This, we can save the @Temporal annotation typing from entity class.
类 javaxjava.sql.Date 扩展了 java.util.Date 对毫秒容器进行了微小的更改,以便它可以有效地支持数据库 DATE 类型。这样,我们可以保存实体类中的 @Temporal 注释类型。
However, java.util.Date could be used for better scalability in entire application so that it can be easily used to store time along with date.
但是,java.util.Date 可以用于在整个应用程序中获得更好的可伸缩性,以便可以轻松地将时间与日期一起存储。