1. 引言
经常用Java相关的时间类比如Date,SimpleDateFormat,Calendar等,同时java.sql包中也有相应的包装类,做一总结以便记录和查看。
2. Date类
2.1 初始化类
java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象。
第一个构造函数使用当前日期和时间来初始化对象。
Date( )
第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
Date(long millisec)
2.2 常用方法
//若当调用此方法的Date对象在指定日期之后返回true,否则返回false
boolean after(Date date)
//若当调用此方法的Date对象在指定日期之前返回true,否则返回false
boolean before(Date date)
//比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数。
int compareTo(Date date)
//当调用此方法的Date对象和指定日期相等时候返回true,否则返回false
boolean equals(Object date)
//返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
long getTime()
//返回此对象的哈希码值
int hashCode()
//用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期
void setTime(long time)
//把此Date对象转换为以下形式的String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)
String toString()
3. 格式化日期
3.1 使用SimpleDateFormat格式化日期
SimpleDateFormat是一个以语言环境敏感的方式来格式化和分析日期的类。SimpleDateFormat允许你选择任何用户自定义日期时间格式来运行。
public class DateDemo {
public static void main(String args[]) {
Date dNow = new Date( );
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
System.out.println("当前时间为: " + ft.format(dNow));
}
}
3.1.1 SimpleDateFormat日期和时间的格式化编码
时间模式字符串用来指定时间格式。在此模式中,所有的 ASCII 字母被保留为模式字母,定义如下:
字母 | 描述 | 示例 |
---|---|---|
G | 纪元标记 | AD |
y | 四位年份 | 2001 |
M | 月份 | July or 07 |
d | 一个月的日期 | 10 |
h | A.M./P.M. (1~12)格式小时 | 12 |
H | 一天中的小时 (0~23) | 22 |
m | 分钟数 | 30 |
s | 秒数 | 55 |
S | 毫秒数 | 234 |
E | 星期几 | Tuesday |
D | 一年中的日子 | 360 |
F | 一个月中第几周的周几 | 2 (second Wed. in July) |
w | 一年中第几周 | 40 |
W | 一个月中第几周 | 1 |
a | A.M./P.M. 标记 | PM |
k | 一天中的小时(1~24) | 24 |
K | A.M./P.M. (0~11)格式小时 | 10 |
z | 时区 | Eastern Standard Time |
' | 文字定界符 | Delimiter |
" | 单引号 | ` |
3.1.2 SimpleDataFormat解析字符串为时间
SimpleDateFormat类有一些附加的方法,特别是parse(),它试图按照给定的SimpleDateFormat对象的格式化存储来解析字符串。
public class DateDemo {
public static void main(String args[]) {
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd");
String input = args.length == 0 ? "1818-11-11" : args[0];
System.out.print(input + " Parses as ");
Date t;
try {
t = ft.parse(input);
System.out.println(t);
} catch (ParseException e) {
System.out.println("Unparseable using " + ft);
}
}
}
3.2 使用printf格式化日期
printf 方法可以很轻松地格式化时间和日期。它以 %t开头并且以下面表格中的一个字母结尾。
转 换 符 | 说 明 | 示 例 |
---|---|---|
c | 包括全部日期和时间信息 | 星期六 十月 27 14:21:20 CST 2007 |
F | "年-月-日"格式 | 2007-10-27 |
D | "月/日/年"格式 | 10/27/07 |
r | "HH:MM:SS PM"格式(12时制) | 02:25:51 下午 |
T | "HH:MM:SS"格式(24时制) | 14:28:16 |
R | "HH:MM"格式(24时制) | 14:28 |
3.3 测量时间
下面的一个例子表明如何测量时间间隔(以毫秒为单位):
public class DiffDemo {
public static void main(String args[]) {
try {
long start = System.currentTimeMillis( );
System.out.println(new Date( ) + "\n");
Thread.sleep(5*60*10);
System.out.println(new Date( ) + "\n");
long end = System.currentTimeMillis( );
long diff = end - start;
System.out.println("Difference is : " + diff);
} catch (Exception e) {
System.out.println("Got an exception!");
}
}
}
/**
* 运行结果如下:
* Thu May 09 13:56:40 CST 2019
*
* Thu May 09 13:56:43 CST 2019
*
* Difference is : 3021
*/
4. Calendar日历类
Calendar类的功能要比Date类强大很多,Calendar类是一个抽象类,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可。
//默认是当前日期
Calendar c = Calendar.getInstance();
4.1 Calendar字段类型
常量 | 描述 |
---|---|
Calendar.YEAR | 年份 |
Calendar.MONTH | 月份 |
Calendar.DATE | 日期 |
Calendar.DAY_OF_MONTH | 日期,和上面的字段意义完全相同 |
Calendar.HOUR | 12小时制的小时 |
Calendar.HOUR_OF_DAY | 24小时制的小时 |
Calendar.MINUTE | 分钟 |
Calendar.SECOND | 秒 |
Calendar.DAY_OF_WEEK | 星期几 |
4.2 Calendar的简单操作
//获得Calendar实例
Calendar c1 = Calendar.getInstance();
//设置Calendar实例的年,月,日
public final void set(int year,int month,int date)
//把Calendar对象c1的年月日分别设这为:2009、6、12
c1.set(2009, 6, 12);
//设定某个字段,例如日期的值
public void set(int field,int value)
//把c1对象代表的日期设置为10号,其它所有的数值会被重新计算,其他字段设置以此类推
c1.set(Calendar.DATE,10);
//把c1对象的日期加上10,也就是c1也就表示为10天后的日期,其它所有的数值会被重新计算,其他字段设置以此类推
c1.add(Calendar.DATE, 10);
4.3 GregorianCalendar类
Calendar类实现了公历日历,GregorianCalendar是Calendar类的一个具体实现,Calendar的getInstance()方法返回一个默认用当前的语言环境和时区初始化的GregorianCalendar对象。GregorianCalendar定义了两个字段:AD和BC。这是代表公历定义的两个时代。
4.3.1 GregorianCalendar构造方法
序号 | 构造函数和说明 |
1 | GregorianCalendar() 在具有默认语言环境的默认时区内使用当前时间构造一个默认的 GregorianCalendar。 |
2 | GregorianCalendar(int year, int month, int date) 在具有默认语言环境的默认时区内构造一个带有给定日期设置的 GregorianCalendar |
3 | GregorianCalendar(int year, int month, int date, int hour, int minute) 为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。 |
4 | GregorianCalendar(int year, int month, int date, int hour, int minute, int second) 为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。 |
5 | GregorianCalendar(Locale aLocale) 在具有给定语言环境的默认时区内构造一个基于当前时间的 GregorianCalendar。 |
6 | GregorianCalendar(TimeZone zone) 在具有默认语言环境的给定时区内构造一个基于当前时间的 GregorianCalendar。 |
7 | GregorianCalendar(TimeZone zone, Locale aLocale) 在具有给定语言环境的给定时区内构造一个基于当前时间的 GregorianCalendar。 |
4.3.2 GregorianCalendar常用方法
序号 | 方法和说明 |
1 | void add(int field, int amount) 根据日历规则,将指定的(有符号的)时间量添加到给定的日历字段中。 |
2 | protected void computeFields() 转换UTC毫秒值为时间域值 |
3 | protected void computeTime() 覆盖Calendar ,转换时间域值为UTC毫秒值 |
4 | boolean equals(Object obj) 比较此 GregorianCalendar 与指定的 Object。 |
5 | int get(int field) 获取指定字段的时间值 |
6 | int getActualMaximum(int field) 返回当前日期,给定字段的最大值 |
7 | int getActualMinimum(int field) 返回当前日期,给定字段的最小值 |
8 | int getGreatestMinimum(int field) 返回此 GregorianCalendar 实例给定日历字段的最高的最小值。 |
9 | Date getGregorianChange() 获得格里高利历的更改日期。 |
10 | int getLeastMaximum(int field) 返回此 GregorianCalendar 实例给定日历字段的最低的最大值 |
11 | int getMaximum(int field) 返回此 GregorianCalendar 实例的给定日历字段的最大值。 |
12 | Date getTime() 获取日历当前时间。 |
13 | long getTimeInMillis() 获取用长整型表示的日历的当前时间 |
14 | TimeZone getTimeZone() 获取时区。 |
15 | int getMinimum(int field) 返回给定字段的最小值。 |
16 | int hashCode() 重写hashCode. |
17 | boolean isLeapYear(int year) 确定给定的年份是否为闰年。 |
18 | void roll(int field, boolean up) 在给定的时间字段上添加或减去(上/下)单个时间单元,不更改更大的字段。 |
19 | void set(int field, int value) 用给定的值设置时间字段。 |
20 | void set(int year, int month, int date) 设置年、月、日的值。 |
21 | void set(int year, int month, int date, int hour, int minute) 设置年、月、日、小时、分钟的值。 |
22 | void set(int year, int month, int date, int hour, int minute, int second) 设置年、月、日、小时、分钟、秒的值。 |
23 | void setGregorianChange(Date date) 设置 GregorianCalendar 的更改日期。 |
24 | void setTime(Date date) 用给定的日期设置Calendar的当前时间。 |
25 | void setTimeInMillis(long millis) 用给定的long型毫秒数设置Calendar的当前时间。 |
26 | void setTimeZone(TimeZone value) 用给定时区值设置当前时区。 |
27 | String toString() 返回代表日历的字符串。 |
5. 数据库中的时间类
java.util.Date日期格式为:年月日时分秒
下面的三个类都继承自java.util.Date类,他们对java.util.Date类进行了包装
- java.sql.Date日期格式为:年月日[只存储日期数据不存储秒、分、小时数据,是专门针对sql设计]
- java.sql.Time日期格式为:时分秒
- java.sql.Timestamp日期格式为:年月日时分秒纳秒(毫微秒)
5.1 java.sql.Date类
java.sql.Date类屏蔽了java.util.Date类的时间有关的方法(形如:hh:mm:ss),因此,不可以通过这个类访问时、分、秒有关的信息,比如,如果你通过sqlDate.getHour()方法去访问小时信息,此方法会抛出一个IllegalArgumentException异常。
这是因为java.sql.Date在继承java.util.Date类的时候对父类进行了重写,禁用了时、分、秒访问的方法。之所以这么处理,是为了和数据库的Date数据类型相匹配,数据库的Date数据类只是保存日期有关的字段。但是java.sql.Date类有getTime方法返回毫秒数,所以它可以与java.util.Date进行互换:
//java.sql.Date转为java.util.Date
java.sql.Date sqlDate=new java.sql.Date();
java.util.Date utilDate=new java.util.Date (sqlDate.getTime());
//java.util.Date转为java.sql.Date
java.util.Date utilDate=new Date();
java.sql.Date sqlDate=new java.sql.Date(utilDate.getTime());
5.2 java.sql.Time类
java.sql.Time类屏蔽了java.util.Date的日期有关的字段(形如:yyyy-MM-dd),因此,不能通过这个类访问日期有关的信息,比如:如果你通过sqlTime.getYear()方法去获取年有关的信息,此方法会抛出一个IllegalArgumentException异常。
这是因为java.sql.Time在继承java.util.Date类的时候对父类进行了重写,禁用了日期访问的方法。之所以这么处理,是为了和数据库的Time数据类型相匹配,数据库的Time数据类行只是保存时间有关的字段。
java.sql.date 是只包含了日期。而 java.sql.time 只包含了一个时间。java.sql.time,java.sql.date 二者如何组合成一个java.util.date呢?取毫秒相加,作为java.util.date的构造方法参数就可以了。
//将sql的date和time相加得到java.util.Date实例
java.sql.Date d = new java.sql.Date(new java.util.Date().getTime());
java.sql.Time t = new java.sql.Time(new java.util.Date().getTime());
java.util.Date day = new java.util.Date(d.getTime() + t.getTime());
5.3 java.sql.Timestamp
java.sql.Timestamp字段则对java.util.Date这个类进行了扩充,它在java.util.Date类的基础上增加了纳秒,因此,你可以通过getNanos方法去获取时间的纳秒值(1秒等于10的9次方纳秒),同样的,这也是为了和数据库中的Timestamp数据类型进行匹配。
但是需要注意的是,由于加入了纳秒字段,所以Timestampt的equeal方法与Date类Timestampt的hashcode方法不包括纳秒,由于Timestamp和java.util.Date之间的差异,建议代码不要将Timestamp作为java.util.Date的实例来对待,Timestampt和Date实际上表示实现继承,而不是类型继承。
6. @JsonFormat与@DateTimeFormat
@DateTimeFormat(pattern = “yyyy-MM-dd HH:mm:ss”)是将String转换成Date,一般前台给后台传值时用
@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone=”GMT+8”)将Date转换成String 一般后台传值给前台时
注意:pattern中的H不能小写,格式不能错误,写成小写h会报错
参考: