在创建 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.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));
}
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);
}
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);
}
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);
}
}
重新设置时间
通过 setTime() 函数可以重设日期时间值,方法如下:
public void setTime(long date) {
// If the millisecond date value contains time info, mask it out.
super.setTime(date);
}
方法说明
- 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());
}
}
执行结果:
2017-01-16 16:37:55 520
year:117
month:0
date:16
day:1
hours:16
minutes:37
seconds:55
time:1484555875520
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());
}
}
执行结果:
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
可以看出 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);
}
执行结果如下:
date:1484557195481
time:1484557195481
utilDate:Sat Feb 02 01:59:50 CST 2064
经验证该方案是错误的,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,后续的文章会对其进行分析。