Java8 日期和时间API
在Java8以前我们通常用java.util.Date
类和java.util.Calendar
类表示日期和时间,这两个类在使用上不是很方便,而且存在线程安全性问题,于是Java8引入了java.time
包,将日期和时间类设计成了不可变的(类似于String),因为无法修改所以在多线程环境下也不会出现问题。
LocalDate、LocalTime、LocalDateTime类
LocalDate
类用于表示日期,LocalTime
类用于表示时间,LocalDateTime
类用于表示日期和时间(即包含了前两个类的功能)。这三个类的方法都类似,使用方法相同,可以根据实际需要来选择。
因为使用方法相同,所以仅测试LocalDateTime
类,示例代码:
@Test
public void test01(){
// 获取当前系统时间的实例
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
// 获取自定义时间的实例 参数:年、月、日、时、分、秒
LocalDateTime ldt2 = LocalDateTime.of(2017, 10, 15, 3, 15, 20);
System.out.println(ldt2);
// 改变或计算日期和时间 (无论发生什么改变,都会产生一个新的实例,因为这三个对象都是不可变的)
// 加时间
LocalDateTime ldt3 = ldt2.plusYears(2)
.plusMonths(1)
.plusDays(10)
.plusHours(3)
.plusMinutes(50)
.plusSeconds(7);
System.out.println(ldt3);
// 减时间
LocalDateTime ldt4 = ldt3.minusWeeks(2)
.minusNanos(10000); // 纳秒
System.out.println(ldt4);
// 单独提取各个部分
System.out.println(ldt.getYear());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());
}
Instant类
Java8用Instant
类表示时间戳(从1970年1月1日00:00:00到某个时刻之间的毫秒数)。
示例代码:
@Test
public void test02(){
// 获取当前时间戳 默认获取 UTC 时区的时间 (美国时间)
Instant instant = Instant.now();
System.out.println(instant); // 输出 2020-04-24T04:37:48.943079200Z
// 转换到中国时区的两种方法---设置时区偏移量或者设定指定的时区
System.out.println(instant.atOffset(ZoneOffset.ofHours(8))); // 输出 2020-04-24T12:37:48.943079200+08:00
System.out.println(instant.atZone(ZoneId.of("Asia/Shanghai"))); // 输出 2020-04-24T12:37:48.943079200+08:00[Asia/Shanghai]
// 获取毫秒数
System.out.println(instant.toEpochMilli()); // 输出 1587703068943
// 构造时间戳--获取距离1970年1月1日00:00:00这个时刻1516513毫秒的时间戳
Instant instant2 = Instant.ofEpochMilli(1516513);
System.out.println(instant2); // 输出 1970-01-01T00:25:16.513Z
}
Duration类和Period类
Duration
类用于计算两个时间之间的间隔,Period
类用于计算两个日期之间的间隔。
静态方法:between()
示例代码:
@Test
public void test03() throws InterruptedException {
Instant instant = Instant.now();
Thread.sleep(2000);
Instant instant2 = Instant.now();
System.out.println(Duration.between(instant, instant2).toMillis());
System.out.println("-----------------------------");
LocalTime localTime = LocalTime.now();
Thread.sleep(300);
LocalTime localTime2 = LocalTime.now();
System.out.println(Duration.between(localTime, localTime2).toMillis());
System.out.println("-----------------------------");
LocalDate localDate = LocalDate.now();
LocalDate localDate2 = LocalDate.of(2008, 5, 25);
System.out.println(Period.between(localDate2, localDate).getYears());
}
DateTimeFormatter类
DateTimeFormatter
类用于格式化日期和时间,相比于 Java8之前的SimpleDateFormat
,它是线程安全的。
示例代码:
@Test
public void test04(){
// 将日期和时间格式化成字符串
// DateTimeFormatter中提供了很多标准,可以直接使用
DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;
LocalDateTime ldt = LocalDateTime.now();
String str1 = ldt.format(dtf);
System.out.println(str1); // 输出 2020-04-24
// 也可以自定义自己需要的格式
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
String str2 = dtf2.format(ldt);
System.out.println(str2); // 输出 2020-04-24 12:45:58
}
TemporalAdjusters类
TemporalAdjusters
是时间校正器类,有时我们可能需要将日期调整到“下个周日”或者“下个工作日”之类的操作。
示例代码:
@Test
public void test05(){
LocalDateTime ldt1 = LocalDateTime.now();
// 获得当前的时间的下一个周日的时间
LocalDateTime ldt2 = ldt1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt1);
System.out.println(ldt2);
System.out.println("-------------------");
// 自定义:下一个工作日
LocalDateTime ldt3 = ldt1.with((l) -> {
LocalDateTime ldt = (LocalDateTime) l;
if(ldt.getDayOfWeek().equals(DayOfWeek.FRIDAY)){
return ldt.plusDays(3);
}else if(ldt.getDayOfWeek().equals(DayOfWeek.SATURDAY)){
return ldt.plusDays(2);
}else{
return ldt.plusDays(1);
}
});
System.out.println(ldt1.getDayOfWeek());
System.out.println(ldt3.getDayOfWeek());
}
TemporalAdjusters
的next()
方法表示获取下一个时间,除此之外TemporalAdjusters
还有一些类似的方法可以校正时间。DayOfWeek
是一个枚举类,包含了MONDAY
到SUNDAY
。如果够使用我们也可以自定义,例如获取下一个工作日,LocalDateTime
的with()
方法可以传入一个lambda表达式。