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类对象,并将它的引用赋值给对象变量createTimeDate 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:19System.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 LocalDateimplements 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-21System.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-21System.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.328System.out.println(localTime1);// 打印结果:16:50:50System.out.println(localTime2);// 格式化后,打印结果:16时50分50秒System.out.println(localTime1.format(DateTimeFormatter.ofPattern("HH时mm分ss秒")));// 获取三小时后的时间,打印结果:19:50:50.328System.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.614System.out.println(localDateTime1);// 打印结果:2021-07-21T17:02:50System.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.614System.out.println(localDateTime1.plusDays(-30L));
