欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp之间的区别

程序员文章站 2022-05-02 16:32:25
...

在创建 Date 对象的时候,总会有两个选择 java.util.Date、java.sql.Date,我们直观的认为在操作数据库时间字段时,我们使用 java.sql.Date 创建 Date 对象,其他情况下使用 java.util.Date 创建 Date 对象。

类的关系如下图:

java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp之间的区别

java.util.Date 是 java.sql.Date java.sql.Time java.sql.Timestamp 的父类,java.security.Timestamp 集成与 java.lang.Object 类。

构造函数

java.util.Date: 提供了完整的日期时间功能,通过 getTime() 方法可以获取到毫秒数。该类提供了以下几种构造方法:

public Date() {
    this(System.currentTimeMillis());
}

public Date(long date) {
    fastTime = date;
}

@Deprecated
public Date(int year, int month, int date) {
    this(year, month, date, 0, 0, 0);
}

@Deprecated
public Date(int year, int month, int date, int hrs, int min) {
    this(year, month, date, hrs, min, 0);
}

@Deprecated
public Date(int year, int month, int date, int hrs, int min, int sec) {
    int y = year + 1900;
    // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
    if (month >= 12) {
        y += month / 12;
        month %= 12;
    } else if (month < 0) {
        y += CalendarUtils.floorDivide(month, 12);
        month = CalendarUtils.mod(month, 12);
    }
    BaseCalendar cal = getCalendarSystem(y);
    cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());
    cdate.setNormalizedDate(y, month + 1, date).setTimeOfDay(hrs, min, sec, 0);
    getTimeImpl();
    cdate = null;
}

@Deprecated
public Date(String s) {
    this(parse(s));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

java.sql.Date: 该类屏蔽了时间值,只返回年月日,如:yyyy-MM-dd,该类的主要作用是为了与数据库字段的 Date 类型进行匹配。该类没有提供无参的构造函数,只能通过 long 值或者 year month day 进行初始化。我们可以使用 java.util.Date.getTime() 获取到 long 值,然后构造 java.sql.Date 对象。该类提供了以下几种构造方法:

public Date(long date) {
    // If the millisecond date value contains time info, mask it out.
    super(date);

}

public Date(int year, int month, int day) {
    super(year, month, day);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

java.sql.Time: 该类屏蔽了日期值,只返回时分秒,如:HH:mm:ss,该类的主要作用是为了与数据库字段的 Time 类型进行匹配。该类没有提供无参的构造函数,只能通过 long 值或者 hour minute second 进行初始化。我们可以使用 java.util.Date.getTime() 获取到 long 值,然后构造 java.sql.Time 对象。该类提供了以下几种构造方法:

@Deprecated
public Time(int hour, int minute, int second) {
    super(70, 0, 1, hour, minute, second);
}

public Time(long time) {
    super(time);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

java.sql.Timestamp: 该类对 java.util.Date 类进行了扩充,该类提供了 getNanos() 方法,通过它可以访问毫微秒数(注:1秒 = 10亿毫微秒),该类的主要作用是为了与数据库字段的 Time 类型进行匹配。该类没有提供无参的构造函数,只能通过 long 值或者 year month date hour minute second nano 进行初始化。我们可以使用 java.util.Date.getTime() 获取到 long 值,然后构造 java.sql.Time 对象。该类提供了以下几种构造方法:

@Deprecated
public Timestamp(int year, int month, int date,
                 int hour, int minute, int second, int nano) {
    super(year, month, date, hour, minute, second);
    if (nano > 999999999 || nano < 0) {
        throw new IllegalArgumentException("nanos > 999999999 or < 0");
    }
    nanos = nano;
}

public Timestamp(long time) {
    super((time/1000)*1000);
    nanos = (int)((time%1000) * 1000000);
    if (nanos < 0) {
        nanos = 1000000000 + nanos;
        super.setTime(((time/1000)-1)*1000);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

重新设置时间

通过 setTime() 函数可以重设日期时间值,方法如下:

public void setTime(long date) {
    // If the millisecond date value contains time info, mask it out.
    super.setTime(date);
}
  • 1
  • 2
  • 3
  • 4
  • 5

方法说明

  • getYear:返回年份,值为年份减去1900,如当前年份为 2017,则返回值为 2017 - 1900 = 117;
  • getMonth:返回月份,月份是从 0 开始的,如当前月份为 1 月,则返回值为 0;
  • getDate:返回日期,一月中的某天,取值范围为 1 - 31,如日期为 1 月 1 日,则返回值为 1;
  • getDay:返回一周中的某天,取值范围为 0 - 6,对应的星期数:0 = Sunday, 1 = Monday, 2 = Tuesday, 3 = Wednesday, 4 = Thursday, 5 = Friday, 6 = Saturday,如当前是星期一,则返回 1;
  • getHours:返回小时数,取值范围为 0 - 23,如当前时间为 16:17:10,则返回 16;
  • getMinutes:返回分钟数,取值范围为 0 - 59,如当前时间为 16:17:10,则返回 17;
  • getSeconds:返回秒数,取值范围为 0 - 61,61 是由于闰秒的缘故,如当前时间为 16:17:10,则返回 10;
  • getTime:返回从 1970-1-1 00:00:00 GMT 开始到目标时间的毫秒数;
  • getNanos:返回当前时间的毫微秒数,1毫秒 = 1000000毫微秒,1秒 = 1000000000 毫微秒。

示例

java.util.Date 示例:

import java.text.SimpleDateFormat;

public class DateDemo {

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        java.util.Date utilDate = new java.util.Date();
        System.out.println(sdf.format(utilDate));
        System.out.println("year:" + utilDate.getYear());
        System.out.println("month:" + utilDate.getMonth());
        System.out.println("date:" + utilDate.getDate());
        System.out.println("day:" + utilDate.getDay());
        System.out.println("hours:" + utilDate.getHours());
        System.out.println("minutes:" + utilDate.getMinutes());
        System.out.println("seconds:" + utilDate.getSeconds());
        System.out.println("time:" + utilDate.getTime());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

执行结果:

2017-01-16 16:37:55 520
year:117
month:0
date:16
day:1
hours:16
minutes:37
seconds:55
time:1484555875520
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

java.sql.Timestamp 示例:

import java.text.SimpleDateFormat;

public class TimestampDemo {

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        java.util.Date utilDate = new java.util.Date();
        java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp(utilDate.getTime());

        System.out.println(sdf.format(sqlTimestamp));
        System.out.println("year:" + sqlTimestamp.getYear());
        System.out.println("month:" + sqlTimestamp.getMonth());
        System.out.println("date:" + sqlTimestamp.getDate());
        System.out.println("day:" + sqlTimestamp.getDay());
        System.out.println("hours:" + sqlTimestamp.getHours());
        System.out.println("minutes:" + sqlTimestamp.getMinutes());
        System.out.println("seconds:" + sqlTimestamp.getSeconds());
        System.out.println("nanos:" + sqlTimestamp.getNanos());
        System.out.println("time:" + utilDate.getTime());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

执行结果:

2017-01-16 16:38:59 571
year:117
month:0
date:16
day:1
hours:16
minutes:38
seconds:59
nanos:571000000
time:1484555939571
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以看出 571毫秒 = 571000000毫微秒,1毫秒 = 1000000毫微秒,1秒 = 1000000000 毫微秒。

如何将 java.sql.Date 和 java.sql.time 的值转化为 java.util.Date,网上有人提出的方案是获取 java.sql.Date java.sql.Time 两个对象的毫秒数进行相加,然后通过该值构造 java.util.Date 对象,实现代码如下:

public class DateDemo {

public static void main(String[] args) {

    java.sql.Date date = new java.sql.Date(new java.util.Date().getTime());
    java.sql.Time time = new java.sql.Time(new java.util.Date().getTime());
    java.util.Date utilDate = new java.util.Date(date.getTime() + time.getTime());
    System.out.println("date:" + date.getTime());
    System.out.println("time:" + time.getTime());
    System.out.println("utilDate:" + utilDate);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

}

执行结果如下:

date:1484557195481
time:1484557195481
utilDate:Sat Feb 02 01:59:50 CST 2064
  • 1
  • 2
  • 3
  • 4

经验证该方案是错误的,java.sql.Date java.sql.time 本身都存储了距离 1970-1-1 00:00:00 GMT的绝对毫秒数,显然通过 getTime 方法取到毫秒数的方案是错误的。最原始的实现方式是通过 getYear getMonth getDate getHours getMinutes getSeconds 实现。

总结

java.util.Date 是 java 中标准的日期时间类,java.sql.Date java.sql.Time java.sql.Timestamp 是 Java为了适配数据库字段类型对 java.util.Date 类的封装。

java.util.Date 中的很多方法已经不被推荐使用了(@Deprecated),取而代之的是 java.util.Calendar,后续的文章会对其进行分析。