包 java.util 和包 java.sql 中日期类的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5298450/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 10:29:54  来源:igfitidea点击:

Difference between Date class in Package java.util & Package java.sql

javadate

提问by ram

In java, both the java.utiland the java.sqlpackage contain a Dateclass, So what is the difference between them?

在java中,thejava.utiljava.sqlpackage都包含一个Date类,那么它们有什么区别呢?

If one Dateclass is present in Java then what is the need of another Dateclass?

如果DateJava 中存在一个类,那么另一个Date类的需要是什么?

回答by Sean Patrick Floyd

From the JavaDoc of java.sql.Date:

来自JavaDoc 的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.

To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Dateinstance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.

毫秒值的薄包装器,允许 JDBC 将其标识为 SQL DATE 值。毫秒值表示自 1970 年 1 月 1 日 00:00:00.000 GMT 以来经过的毫秒数。

为了符合 SQL DATE 的定义,java.sql.Date必须通过在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零来“规范化”实例包装的毫秒值。

Explanation:A java.util.Daterepresents date and time of day, a java.sql.Dateonly represents a date (the complement of java.sql.Date is java.sql.Time, which only represents a time of day, but also extends java.util.Date).

说明:Ajava.util.Date代表日期和时间,ajava.sql.Date只代表日期(java.sql.Date 的补码是java.sql.Time,它只代表一天的时间,但也扩展了java.util.Date)。

回答by Ruik

These answers seem to be partially outdated.

这些答案似乎部分过时了。

I just read a little API Code (Java Version 1.8.0_91) and found this in java.sql.Date:

我刚刚阅读了一些 API 代码(Java 版本 1.8.0_91)并在java.sql.Date以下位置找到了它:

/**
 * Creates a date which corresponds to the day determined by the supplied
 * milliseconds time value {@code theDate}.
 *
 * @param theDate
 *            a time value in milliseconds since the epoch - January 1 1970
 *            00:00:00 GMT. The time value (hours, minutes, seconds,
 *            milliseconds) stored in the {@code Date} object is adjusted to
 *            correspond to 00:00:00 GMT on the day determined by the supplied
 *            time value.
 */
public Date(long theDate) {
    super(normalizeTime(theDate));
}

/*
 * Private method which normalizes a Time value, removing all low
 * significance digits corresponding to milliseconds, seconds, minutes and
 * hours, so that the returned Time value corresponds to 00:00:00 GMT on a
 * particular day.
 */
private static long normalizeTime(long theTime) {
    return theTime;
}

The method for normalizing the time is still there and even the comment says that the time will be normalized to 00:00:00 GMT but it does nothing. For some reason they removed the normalization, wich means, that a java.sql.Datecontains just like a java.util.Datejust the number of milliseconds since 1.1.1970. So there is a time component but it is not displayed externally.

标准化时间的方法仍然存在,甚至评论说时间将标准化为格林威治标准时间 00:00:00 但它什么也没做。出于某种原因,他们删除了标准化,这意味着 ajava.sql.Date包含java.util.Date自 1970 年 1 月 1 日以来的毫秒数。所以有一个时间组件,但它没有显示在外部。

For example the code

例如代码

java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(Calendar.getInstance().getTimeInMillis())

System.out.println(utilDate);
System.out.println(sqlDate);

produces the output

产生输出

Thu Jun 02 13:17:35 CEST 2016
2016-06-02

So be careful with sql dates and do not handle them like they would just contain a Date and no time information. For example:

所以要小心 sql 日期,不要像处理它们那样只包含日期而没有时间信息。例如:

java.sql.Date sqlDate1 = new java.sql.Date(Calendar.getInstance().getTimeInMillis());
java.sql.Date sqlDate2 = new java.sql.Date(Calendar.getInstance().getTimeInMillis());

System.out.println(sqlDate1);
System.out.println(sqlDate2);
System.out.println(sqlDate1.equals(sqlDate2));
System.out.println(sqlDate1.toString().equals(sqlDate2.toString()));

prints:

印刷:

2016-06-02
2016-06-02
false
true

回答by Nishan

Java.util.Date is the generic all-purpose Date object. It stores a Date (as a long) and allows you to display it.

Java.util.Date 是通用的通用 Date 对象。它存储一个日期(作为一个长)并允许您显示它。

java.sql.Date extends java.util.Date. Main difference to note is that java.sql.Date does not have a time component.

java.sql.Date 扩展了 java.util.Date。要注意的主要区别是 java.sql.Date 没有时间组件。

回答by Basil Bourque

The Old

老人

java.util.Date

java.util.Date

The java.util.Dateclass is part of the old date-time classes that have proven to be poorly designed, confusing, and troublesome. The intent is to represent a moment (a date and a time-of-day) on the timeline.

java.util.Date类是已被证明是设计不当,令人费解,麻烦的旧日期时间类的一部分。目的是在时间线上表示一个时刻(一个日期和一个时间)。

The class seems to represent a moment in UTC, except that its toStringmethod silently applies the JVM's current default time zone while generating the String which creates the illusion that a java.util.Date has a time zone but actually does not. Well, actually it doeshave a time zone assigned deep in its source code used for somethings internally but not obvious and not settable nor gettable. A confusing mess.

该类似乎代表了 UTC 中的一个时刻,除了它的toString方法在生成 String 时默默地应用 JVM 的当前默认时区,这会产生 java.util.Date 具有时区但实际上没有时区的错觉。好吧,实际上它确实在其源代码深处分配了一个时区,用于内部但不明显且不可设置或可获取的内容。一团乱麻。

java.sql.Date

java.sql.Date

The java.sql.Datemakes a bad situation worse by representing the a date-only value(as is meant by “DATE” in the SQL database world) but did so as a hack by extending java.util.Date. But the you are supposed to pretend it is nota subclass, as directed in the class doc. Furthermore, it has time-of-day but pretends not to by adjusting to first moment of the day in UTC. A confusing mess.

java.sql.Date通过表示仅限日期的值(正如SQL 数据库世界中的“DATE”所指),这使糟糕的情况变得更糟,但通过扩展java.util.Date. 但是您应该假装它不是子类,如类文档中所述。此外,它具有一天中的时间,但通过调整到UTC中的一天中的第一个时刻来假装没有。一团乱麻。

And one more thing… the java.sql.Dateclass adds on a fractional second with a resolution of nanoseconds. That goes beyond the millisecondsresolution used by java.util.Date. Many databases support finer resolutions such as microsecondor nanosecond.

还有一件事……java.sql.Date课程增加了一个小数秒,分辨率为纳秒。这超出了java.util.Date 使用的毫秒分辨率。许多数据库支持更精细的分辨率,例如微秒或纳秒。

So in these old date-time classes there is no way to truly represent a date-only value with no time-of-day nor time zone.

因此,在这些旧的日期时间类中,无法真正表示没有时间或时区的仅日期值。

The New

新的

The java.timeframework comes to the rescue. Inspired by the highly successful Joda-Timeproject. Built into Java 8 and later. Back-ported to Java 6 & 7, and further adapted to Android. See Oracle Tutorial.

java.time框架就派上用场了。受到非常成功的Joda-Time项目的启发。内置于 Java 8 及更高版本中。向后移植到 Java 6 & 7,并进一步适应 Android。请参阅Oracle 教程

Instant

Instant

The Instantclass represents a moment on the timeline in UTC with a resolution of nanoseconds. Clear and simple.

Instant类表示UTC时间线与纳秒的分辨率上一会儿。清晰而简单。

Instant instant = Instant.now();

instant.toString() → 2016-06-19T02:34:55.564Z

Instant.toString() → 2016-06-19T02:34:55.564Z

If a java.util.Dateis needed for use with old code, you can convert. See new methods added to the old class: java.util.Date::toInstant()and java.util.Date.from( Instant ).

如果java.util.Date需要与旧代码一起使用,则可以进行转换。查看添加到旧类的新方法:java.util.Date::toInstant()java.util.Date.from( Instant )

Zoned

分区

To adjust into some locality's wall-clock time, apply an offset-from-UTC(ZoneOffset) to get a OffsetDateTimeobject. Even better, if you know the proper time zone name, apply a ZoneIdto get a ZonedDateTime.

要调整到某个地方的挂钟时间,请应用偏移 UTC( ZoneOffset) 来获取OffsetDateTime对象。更好的是,如果您知道正确的时区名称,请应用 aZoneId以获取ZonedDateTime.

For example America/Montrealis four hours behind UTCin summer under Daylight Saving Time (DST), so we see 10 PM (22:00) on the previous datein code below rather than 2 AM in the example above. Going back four hours crossed over midnight into the previous date. But both the instantobject seen above and the zdtobject seen next both represent the same simultaneous momenton the timeline. Same moment in history but is “tomorrow” in Paris, Kolkata, and Auckland while “yesterday” in Montréal, Mexico City, and Honolulu.

例如,在夏令时 (DST)下,夏季America/MontrealUTC晚 4 小时,因此我们在下面的代码中看到上一个日期的晚上 10 点(22:00),而不是上面示例中的凌晨 2 点。返回四个小时跨越午夜进入前一个日期。但是上面看到的物体和接下来看到的物体都代表时间线上的同一时刻。历史上的同一时刻,但在巴黎、加尔各答和奥克兰是“明天”,而在蒙特利尔、墨西哥城和檀香山则是“昨天”。instantzdt

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

zdt.toString() → 2016-06-18T22:34:55.564-04:00[America/Montreal]

zdt.toString() → 2016-06-18T22:34:55.564-04:00[美国/蒙特利尔]

LocalDate

LocalDate

For a date-only value, use the LocalDateclass. No time-of-day nor time zone is retained.

对于仅限日期的值,请使用LocalDate该类。不保留时间或时区。

LocalDate localDate = zdt.toLocalDate();

But note that a time zone is crucial in determining a dateas for any given moment the date can vary around the globe by time zone. Thus the discussion above about specifying a time zone. For example, see next how we get the 18thof June rather than the 19th.

但请注意,时区对于确定日期至关重要,因为对于任何给定时刻,日期在全球范围内都可能因时区而异。因此,上面关于指定时区的讨论。例如,接下来看看我们如何获得18thof June 而不是19th

localDate.toString() → 2016-06-18

localDate.toString() → 2016-06-18

If this distinction between dates by time zone is significant to your business, you should be using a date-time value stored in a database column type of TIMESTAMP WITH TIME ZONErather than DATE.

如果按时区区分日期对您的业务很重要,则您应该使用存储在数据库列类型中的日期时间值TIMESTAMP WITH TIME ZONE而不是DATE

Search Stack Overflow for much more information and many examples of java.time (tag: java-time).

搜索 Stack Overflow 以获取更多信息和 java.time(标签:)的许多示例java-time

Database

数据库

So save to a database, use a JDBCdrivercomplying with JDBC 4.2spec(see Guide). Call setObjectand getObjecton PreparedStatementto directly use the java.time objects.

所以保存到数据库,使用符合JDBC 4.2规范JDBC驱动程序(参见指南)。调用and on直接使用 java.time 对象。setObjectgetObjectPreparedStatement

If your JDBC driver does not yet support such direct use of the java.time types, use the new methods added to the old classesto facilitate conversion. But minimize your use of the old classes; convert into java.time immediately and use only java.time objects in your business logic.

如果您的 JDBC 驱动程序尚不支持此类直接使用 java.time 类型,请使用添加到旧类中新方法以方便转换。但是尽量减少对旧类的使用;立即转换为 java.time 并在您的业务逻辑中仅使用 java.time 对象。

java.sql.Date mySqlDate = java.sql.Date.valueOf( localDate );

And the other direction.

而另一个方向。

LocalDate localDate = mySqlDate.toLocalDate();

回答by Athiruban

java.sql.Date accepts a long integer which represents the amount of milliseconds since January 1, 1970. If the given number is negative it refers time before January 1, 1970. Remember, the encapsulated value inside the object represents only date like January 1, 1970 and no time information is stored.

java.sql.Date 接受一个长整数,表示自 1970 年 1 月 1 日以来的毫秒数。如果给定的数字是负数,则表示 1970 年 1 月 1 日之前的时间。请记住,对象内部的封装值仅表示日期,如 1 月 1 日, 1970 并且不存储时间信息。

java.util.Date stores both date as well as time information. It is more commonly used than java.sql.Date.

java.util.Date 存储日期和时间信息。它比 java.sql.Date 更常用。