包 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
Difference between Date class in Package java.util & Package java.sql
提问by ram
In java, both the java.util
and the java.sql
package contain a Date
class, So what is the difference between them?
在java中,thejava.util
和java.sql
package都包含一个Date
类,那么它们有什么区别呢?
If one Date
class is present in Java then what is the need of another Date
class?
如果Date
Java 中存在一个类,那么另一个Date
类的需要是什么?
回答by Sean Patrick Floyd
From the JavaDoc of 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.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.
毫秒值的薄包装器,允许 JDBC 将其标识为 SQL DATE 值。毫秒值表示自 1970 年 1 月 1 日 00:00:00.000 GMT 以来经过的毫秒数。
为了符合 SQL DATE 的定义,
java.sql.Date
必须通过在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零来“规范化”实例包装的毫秒值。
Explanation:A java.util.Date
represents date and time of day, a java.sql.Date
only 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.Date
contains just like a java.util.Date
just 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.Date
class 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 toString
method 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.Date
makes 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.Date
class 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 Instant
class 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.Date
is 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 OffsetDateTime
object. Even better, if you know the proper time zone name, apply a ZoneId
to get a ZonedDateTime
.
要调整到某个地方的挂钟时间,请应用偏移 UTC( ZoneOffset
) 来获取OffsetDateTime
对象。更好的是,如果您知道正确的时区名称,请应用 aZoneId
以获取ZonedDateTime
.
For example America/Montreal
is 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 instant
object seen above and the zdt
object 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/Montreal
比UTC晚 4 小时,因此我们在下面的代码中看到上一个日期的晚上 10 点(22:00),而不是上面示例中的凌晨 2 点。返回四个小时跨越午夜进入前一个日期。但是上面看到的物体和接下来看到的物体都代表时间线上的同一时刻。历史上的同一时刻,但在巴黎、加尔各答和奥克兰是“明天”,而在蒙特利尔、墨西哥城和檀香山则是“昨天”。instant
zdt
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 LocalDate
class. 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 ZONE
rather 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 setObject
and getObject
on PreparedStatement
to directly use the java.time objects.
所以保存到数据库,使用符合JDBC 4.2规范的JDBC驱动程序(参见指南)。调用and on直接使用 java.time 对象。setObject
getObject
PreparedStatement
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 更常用。