Package java.util&中Date类的区别包java.sql

时间:2011-03-14 12:16:47

标签: java date

在java中,java.utiljava.sql包都包含Date类,那么它们之间的区别是什么?

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

5 个答案:

答案 0 :(得分:16)

来自the JavaDoc of java.sql.Date

  

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

     

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

说明java.util.Date表示日期和时间,java.sql.Date仅表示日期(java.sql.Date的补码为java.sql.Time ,它只代表一天中的某个时间,但也会延伸java.util.Date)。

答案 1 :(得分:4)

这些答案似乎已经过时了。

我刚刚阅读了一些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;
}

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

例如代码

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);

产生输出

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

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

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()));

打印:

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

java.util.Date

java.util.Date类是旧日期时间类的一部分,它们被证明设计糟糕,令人困惑且麻烦。目的是在时间轴上表示一个时刻(日期和时间)。

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

java.sql.Date

java.sql.Date通过表示仅限日期的值(由“DATE” in the SQL database world表示)使情况更糟,但通过扩展{{ 1}}。但你应该假装它是一个子类,如类doc中的指示。此外,它有时间,但假装不在UTC调整到当天的第一时刻。令人困惑的混乱。

还有一件事...... java.util.Date类在小数秒内加上nanoseconds的分辨率。这超出了java.util.Date使用的milliseconds分辨率。许多数据库支持更精细的分辨率,例如microsecond或纳秒。

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

java.time框架得到了拯救。受到非常成功的Joda-Time项目的启发。内置于Java 8及更高版本。 Back-ported to Java 6 & 7,以及adapted to Android。请参阅Oracle Tutorial

java.sql.Date

Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒。简单明了。

Instant
  

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

如果使用旧代码需要Instant instant = Instant.now(); ,您可以进行转换。查看添加到旧班级的新方法:java.util.Date::toInstant()java.util.Date.from( Instant )

分区

要调整到某个地区的wall-clock time,请应用offset-from-UTCZoneOffset)来获取OffsetDateTime个对象。更妙的是,如果您知道正确的时区名称,请应用ZoneId获取ZonedDateTime

例如,America/MontrealUTC夏季落后Daylight Saving Time (DST)四小时,因此我们在上一个日期中看到晚上10点(22:00)在上面的示例中,代码低于上午而不是凌晨2点。回到过去的四个小时,越过上午的日期。但是,上面显示的java.util.Date对象和下一个所见的instant对象都表示时间轴上的同时时刻。历史上的同一时刻,但在巴黎,加尔各答和奥克兰的“明天”,而在蒙特利尔,墨西哥城和檀香山的“昨天”。

zdt
  

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

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

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

LocalDate

但请注意,时区对于确定日期至关重要,因为任何特定时刻日期可能会因时区而异。因此,上面关于指定时区的讨论。例如,请参阅接下来我们如何获得6月的 18th 而不是 19

  

localDate.toString()→2016-06-18

如果按时区区分日期对您的业务有重要意义,则应使用存储在数据库列类型LocalDate localDate = zdt.toLocalDate(); 而不是TIMESTAMP WITH TIME ZONE中的日期时间值。

搜索Stack Overflow以获取更多信息和许多java.time示例(标记:DATE)。

数据库

因此请保存到数据库,使用符合JDBC driverJDBC 4.2 spec(请参阅Guide)。在PreparedStatement上调用java-timesetObject可直接使用java.time对象。

如果您的JDBC驱动程序尚不支持直接使用java.time类型,请使用添加到旧类的新方法来促进转换。但最大限度地减少对旧班级的使用;立即转换为java.time并在业务逻辑中仅使用java.time对象。

getObject

另一个方向。

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

答案 4 :(得分:0)

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

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