Date类
说Java 8中新的时间类之前,咱们先来说说Date类
- 构造对象:平时构造Date类对象时,一般都会调用它的无参构造器,比如:获取当前时间作为创建时间
Date createTime = new Date();
- 源码分析:它的源码非常简洁,就是获取系统当前的时间戳(毫秒),赋值到内部变量fastTime中,并且提供了一个setTime方法来修改(非线程安全)
public Date() {
this(System.currentTimeMillis());
}
public Date(long date) {
fastTime = date;
}
public void setTime(long time) {
fastTime = time;
cdate = null;
}
- 格式化时间:Date类默认提供的时间格式很难让人阅读,为了返回大家熟悉的时间格式(如”2021-07-21 12:00:00”),就需要通过SimpleDateFormat类(非线程安全)来协助格式化时间
- 时间参照:有时,我们又需要以某个时间为准,获取它之前的n天,或者它之后的n天,就需要依赖Calendar类(非线程安全)
// 构造一个新的Date类对象,并将它的引用赋值给对象变量createTime
Date createTime = new Date();
// 打印结果:1626851179912(毫秒时间戳)
System.out.println(createTime.getTime());
// 打印结果:Wed Jul 21 15:06:19 CST 2021(默认调用toString方法)
System.out.println(createTime);
// 使用SimpleDateFormat类来格式化时间
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 打印结果:2021-07-21 15:06:19
System.out.println(simpleDateFormat.format(createTime));
// 获取当前时间30天之前
Calendar calendar = Calendar.getInstance();
calendar.setTime(createTime);
calendar.add(Calendar.DATE, -30);
Date beforeDay = calendar.getTime();
System.out.println(simpleDateFormat.format(beforeDay));
可以看出,要想满足我们日常的时间处理,Date类需依赖其他类一起使用才能够满足,实现起来也略微繁琐;并且这些类都是非线程安全的(源码中的方法可以直接修改变量),在一些多线程的场景可能会出现超出预期的结果。
而Java 8中新的日期类就是为了解决这些问题:LocalDate,LoccalTime,LocalDateTime
LocalDate
首先来说说LocalDate类,它主要存储的是时间的年、月、日
- 构造对象:使用LocalDate类的静态方法:now或of
- 源码分析:LocalDate是主要有三个变量year, month, day,它们都声明了final,一经赋值不再改变,因此Local类本身是不可变类;其次,它的许多操作数据的方法每次调用都会构建一个新的对象,如plusDays方法;并且,这个类是官方宣称的线程安全类(见类注释)
/**
* This class is immutable and thread-safe.
* @since 1.8
*/
public final class LocalDate
implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable {
...
private final int year;
private final short month;
private final short day;
/**
* 底层初始化数据方法,now和of方法最终都会调用这个私有的构造器,差别在于now获取的是当前系统的年月日,而of方法是校验当前输入的年月日
*/
private LocalDate(int year, int month, int dayOfMonth) {
this.year = year;
this.month = (short) month;
this.day = (short) dayOfMonth;
}
public LocalDate plusDays(long daysToAdd) {
if (daysToAdd == 0) {
return this;
}
long mjDay = Math.addExact(toEpochDay(), daysToAdd);
return LocalDate.ofEpochDay(mjDay);
}
public static LocalDate ofEpochDay(long epochDay) {
...
return new LocalDate(year, month, dom);
}
}
- 格式化时间:LocalDate类默认的时间非常容易阅读(如2021-07-21),若需要做特殊格式(如2021年07月21日),就可以使用它内置的format方法,结合DateTimeFormatter类的ofPattern静态方法来实现
- 时间参照:使用内置的plusDays就可以获取它之前的n天,或者它之后的n天
LocalDate localDate1 = LocalDate.now();
LocalDate localDate2 = LocalDate.of(2021, 7, 21);
// 打印结果:2021-07-21
System.out.println(localDate1);
System.out.println(localDate2);
// 使用本身的format方法结合DateTimeFormatter类的ofPattern方法来格式化时间
// 打印结果:2021年07月21日
System.out.println(localDate1.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
// 获取当前时间30天之前,打印结果:2021-06-21
System.out.println(localDate1.plusDays(30L));
LoccalTime
与LocalTime类区别在于,它存储的是小时、分钟、秒,其他如下:
- 构造方法:同样使用静态方法now和of构造
- 同样是不可变类,并且是线程安全
- 格式化时间的方式也一样,只是可操作的只有时、分、秒
- 获取相对时间方式,内置了plusHours,plusMinutes,plusSeconds等
LocalTime localTime1 = LocalTime.now();
LocalTime localTime2 = LocalTime.of(16, 49, 50);
// 打印结果:16:50:50.328
System.out.println(localTime1);
// 打印结果:16:50:50
System.out.println(localTime2);
// 格式化后,打印结果:16时50分50秒
System.out.println(localTime1.format(DateTimeFormatter.ofPattern("HH时mm分ss秒")));
// 获取三小时后的时间,打印结果:19:50:50.328
System.out.println(localTime1.plusHours(3L));
LocalDateTime
LocalDateTime类可以理解为是LocalDate和LocalTime的结合,存储年、月、日、小时、分、秒
- 构造方法:同样使用静态方法now和of构造
- 同样是不可变类,并且是线程安全
- 格式化时间的方式也一样,不过操作范围更广了,是年、月、日、小时、分钟、秒
- 获取相对时间方式更加丰富,内置了plusDays,plusHours,plusMinutes,plusSeconds等等
LocalDateTime localDateTime1 = LocalDateTime.now();
LocalDateTime localDateTime2 = LocalDateTime.of(2021, 7, 21, 17, 2, 50);
// 打印结果:2021-07-21T17:02:50.614
System.out.println(localDateTime1);
// 打印结果:2021-07-21T17:02:50
System.out.println(localDateTime2);
// 格式化,打印结果:2021年07月21日 17时02分50秒
System.out.println(localDateTime1.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒")));
// 获取30天之前的时间,打印结果:2021-06-21T17:02:50.614
System.out.println(localDateTime1.plusDays(-30L));