导航
我们为什么需要Date、SimpleDateFormat与GregorianCalendar?
时间,是一种很奇妙玄幻的东西,关于时间的思考,就不在这里思考了,可以去看《时间简史》。我们必须承认,生活,离不开时间。而程序,就是用来解决生活问题的,所以,程序也离不开时间。那么,我们如何在Java中表示和使用时间呢?此时,我们就需要用到Java提供的Date类了。
Java是面向对象的,通过类提供了很多方法,方便日常的开发与使用。SimpleDateFormat类与GregorianCalendar类,就是两个包含了许多时间方法的实现类。
Date类
在java.util 包中,Java提供了 Date 类来封装当前的日期和时间。
通过查看源码,可以看到Date类一共提供了6个构造方法,但有四个已经不再建议使用。现常用的两个构造方法为:
Date( )
Date(long date)
第一个构造函数使用当前日期和时间来初始化对象。
第二个构造函数接收一个long型参数,该参数是从1970年1月1日起的毫秒数。
Date类的常用方法:
方法 | 说明 |
---|---|
boolean after(Date date) | 若当调用此方法的Date对象在指定日期之后返回true,否则返回false。 |
boolean before(Date date) | 若当调用此方法的Date对象在指定日期之前返回true,否则返回false。 |
int compareTo(Date date) | 比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数。 |
boolean equals(Object date) | 当调用此方法的Date对象和指定日期相等时候返回true,否则返回false。 |
long getTime( ) | 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。 |
void setTime(long time) | 用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期。 |
String toString( ) | 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。 |
来个实例,使用一下Date类:
public class Test {
public static void main(String[] args) {
Date date1 = new Date(); // 当前(电脑系统)时间
Date date2 = new Date(1000); //距1970年1月1日,1000毫秒的日期。会有时区差。
System.out.println(date1.toString()); //Date的toString()方法,
System.out.println(date2); //println中打印对象,其实就会默认调用它的toString()方法
System.out.println(date1.after(date2)); //Date的after()方法
System.out.println(date1.compareTo(date2)); //Date的compareTo()方法
System.out.println(date1.getTime()); //Date的getTime()方法,返回距1970年1月1日的毫秒数
}
}
-----------------------------------------------------------------------------------------
输出结果:
Sat Mar 21 13:08:01 CST 2020
Thu Jan 01 08:00:01 CST 1970
true
1
1584767281027
判断相差天数
如何判断指定日期与当前日期相差多少天?我们用Date类就可以实现这个需求,实例:
public class Test {
public static void main(String[] args) throws ParseException {
String str = "2020-3-7";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = simpleDateFormat.parse(str);
Date date2 = new Date();
long time1 = date1.getTime();
long time2 = date2.getTime();
long day = (time2 - time1) / 1000 / 60 / 60 / 24;
System.out.println(day+"天");
}
}
-------------------------------------------------------------
输出结果:
14天 //我已经连续更博14天了
在将指定格式的字符串,转换为Date类时,使用到了SimpleDateFormat类。SimpleDateFormat类是什么类呢?请看下面的介绍。
SimpleDateFormat类
SimpleDateFormat类是DateFormat的实现类。DateFormat是一个抽象类,抽象类不能实例出对象,所以我们常用SimpleDateFormat类,来使用它的格式化日期功能。
格式化字符含义
SimpleDateFormat类是用来将日期格式化的,首先我们得了解它的格式化字符的含义(注意大小写):
字符 | 含义 | 示例 |
---|---|---|
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 |
format()
使用SimpleDateFormat类的format()方法,将时间转成格式化的字符串,实例:
public class Test {
public static void main(String[] args) {
Date date1 = new Date(); // 当前时间
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd"); // 常用的两种日期格式
String str1 = simpleDateFormat1.format(date1);
String str2 = simpleDateFormat2.format(date1);
System.out.println(str1);
System.out.println(str2);
}
}
-------------------------------------------------------------------------
输出结果:
2020-03-21 01:21:33
2020-03-21
parse()
使用SimpleDateFormat类的parse()方法,将符合格式的字符串,转换为时间对象,注意一定要符合格式,否则会抛出异常。实例:
public class Test {
public static void main(String[] args) throws ParseException {
String str1 = "2020-03-21 01:21:33";
String str2 = "2020-03-21";
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = simpleDateFormat1.parse(str1); //返回值为Date对象
Date date2 = simpleDateFormat2.parse(str2);
System.out.println(date1); //默认调用了toString()
System.out.println(date2);
}
}
-----------------------------------------------------------------------------------
输出结果为:
Sat Mar 21 01:21:33 CST 2020
Sat Mar 21 00:00:00 CST 2020
判断周几
通过SimpleDateFormat类还可以快速得到指定日期是周几、一年中第几周等信息,具体看实际需求。可以先一个个试试这些格式化字符熟悉一下,我这里只举一个例子,获得指定日期是星期几的实例:
public class Test {
public static void main(String[] args) throws ParseException {
String str = "2222-02-22 22:22:22"; // 指定任意日期
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // 格式需要与String格式一致
Date date1 = simpleDateFormat1.parse(str); // 将String转换成Date
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("E"); //只需要取日期
System.out.println(simpleDateFormat2.format(date1)); // 再将转换后的Date格式化
}
}
---------------------------------------------------------------------------------------
输出结果:
星期五
GregorianCalendar
Calendar类,是一个抽象类,提供了有关日期计算的功能(方法),
GregorianCalendar类是Calendar的实现类,提供了大多数国家/地区的标准日历系统。
使用Calendar类的时候,需要注意,Java里的日期观念都是以西方国家的观念来设计的,毕竟Java是西方国家开发的语言(有点感到悲哀,希望能早日有国产编程语言)
在西方世界里,周日,星期天,是一周的开始,所以1代表星期天、2代表星期一、3代表星期二,以此类推。
在西方世界里,也没有一月二月这样的用数字表示月份的方式,都是直接用January、February、March这样的单词,结合编程里,都是以0开始的逻辑,所以0代表一月、1代表二月,以此类推。
实在用不惯他们这一套的话,我们开发人员也是有办法的,比如再包装一下,有兴趣的话可以试试。
构造方法
要使用一个类,首先得实例化;要实例化,那就调用它的构造方法。下面列出GregorianCalendar对象的几个构造方法:
方法 | 说明 |
---|---|
GregorianCalendar() | 在具有默认语言环境的默认时区内使用当前时间构造一个默认的 GregorianCalendar。 |
GregorianCalendar(int year, int month, int date) | 在具有默认语言环境的默认时区内构造一个带有给定日期设置的 GregorianCalendar |
GregorianCalendar(int year, int month, int date, int hour, int minute) | 为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。 |
GregorianCalendar(int year, int month, int date, int hour, int minute, int second) | 为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。 |
GregorianCalendar(Locale aLocale) | 在具有给定语言环境的默认时区内构造一个基于当前时间的 GregorianCalendar。 |
GregorianCalendar(TimeZone zone) | 在具有默认语言环境的给定时区内构造一个基于当前时间的 GregorianCalendar。 |
GregorianCalendar(TimeZone zone, Locale aLocale) | 在具有给定语言环境的给定时区内构造一个基于当前时间的 GregorianCalendar。 |
实例:
Calendar calendar1 = new GregorianCalendar();
Calendar calendar2 = new GregorianCalendar(2020,2,21); // 注意,这里的,2,表示的是3月哦,在上面介绍过了
Calendar calendar3 = new GregorianCalendar(2020,2,21,13,53,49);
System.out.println(calendar1.get(Calendar.YEAR));
System.out.println(calendar1.get(Calendar.MONTH));
System.out.println(calendar1.get(Calendar.DATE));
System.out.println(calendar1.get(Calendar.DAY_OF_WEEK));
----------------------------------------------------------------------------
输出结果:
2020
2 //2代表3月
21
7 //7表示周六
常用方法
记住常用的几个,其他的需要用到时查看源码或API即可。
方法 | 说明 |
---|---|
void add(int field, int amount) | 根据日历规则,将指定的(有符号的)时间量添加到给定的日历字段中。 |
protected void computeFields() | 转换UTC毫秒值为时间域值 |
protected void computeTime() | 覆盖Calendar ,转换时间域值为UTC毫秒值 |
boolean equals(Object obj) | 比较此 GregorianCalendar 与指定的 Object。 |
int get(int field) | 获取指定字段的时间值 |
int getActualMaximum(int field) | 返回当前日期,给定字段的最大值 |
int getActualMinimum(int field) | 返回当前日期,给定字段的最小值 |
int getGreatestMinimum(int field) | 返回此 GregorianCalendar 实例给定日历字段的最高的最小值。 |
Date getGregorianChange() | 获得格里高利历的更改日期。 |
int getLeastMaximum(int field) | 返回此 GregorianCalendar 实例给定日历字段的最低的最大值 |
int getMaximum(int field) | 返回此 GregorianCalendar 实例的给定日历字段的最大值。 |
Date getTime() | 获取日历当前时间。 |
long getTimeInMillis() | 获取用长整型表示的日历的当前时间 |
TimeZone getTimeZone() | 获取时区。 |
int getMinimum(int field) | 返回给定字段的最小值。 |
int hashCode() | 重写hashCode。 |
boolean isLeapYear(int year) | 确定给定的年份是否为闰年。 |
void roll(int field, boolean up) | 在给定的时间字段上添加或减去(上/下)单个时间单元,不更改更大的字段。 |
void set(int field, int value) | 用给定的值设置时间字段。 |
void set(int year, int month, int date) | 设置年、月、日的值。 |
void set(int year, int month, int date, int hour, int minute) | 设置年、月、日、小时、分钟的值。 |
void set(int year, int month, int date, int hour, int minute, int second) | 设置年、月、日、小时、分钟、秒的值。 |
void setGregorianChange(Date date) | 设置 GregorianCalendar 的更改日期。 |
void setTime(Date date) | 用给定的日期设置Calendar的当前时间。 |
void setTimeInMillis(long millis) | 用给定的long型毫秒数设置Calendar的当前时间。 |
void setTimeZone(TimeZone value) | 用给定时区值设置当前时区。 |
常用类的实例:
public class Test {
public static void main(String[] args) {
Calendar calendar1 = new GregorianCalendar();
//set()方法
calendar1.set(Calendar.YEAR, 2222);
System.out.println(calendar1.get(Calendar.YEAR));
//add()方法
calendar1.add(Calendar.YEAR, -202);
System.out.println(calendar1.get(Calendar.YEAR));
//Calendar转换为Date
Date date1 = calendar1.getTime();
System.out.println(date1);
//Date转换为Calendar
Calendar calendar2 = new GregorianCalendar();
calendar2.setTime(date1);
System.out.println(calendar1.get(Calendar.YEAR));
}
}
-------------------------------------------------------------------------------
输出结果为:
2222
2020
Sat Mar 21 14:30:48 CST 2020
2020
判断闰年
在上面,列举了用SimpleDateFormat类判断指定日期是周几的问题。在面试时,还经常会被问到,如何判断指定年份是不是闰年?来个用GregorianCalendar类解决此问题的实例:
public class Test {
public static void main(String[] args) throws ParseException {
String str = "2222"; //此处也可改为手动输入
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy");
Date date = simpleDateFormat.parse(str);
GregorianCalendar gregoriancalendar = new GregorianCalendar();
gregoriancalendar.setTime(date);
System.out.print(gregoriancalendar.get(Calendar.YEAR)+"年,");
if(gregoriancalendar.isLeapYear(gregoriancalendar.get(Calendar.YEAR))) {
System.out.println("是闰年");
}else {
System.out.println("不是闰年");
}
}
}
-------------------------------------------------------------
输出结果为:
2222年,不是闰年
注意,isLeapYear方法为SimpleDateFormat类的方法,而不是其父类Calendar的方法。