lambda表达式Stream流学习十四,十五—Java8中新增的时间API:LocalDate、LocalTime、LocalDateTime、DateTimeFormatter
Java8 新增的时间日期类都在 java.time.*
包下,不可变元素,线程安全。
LocalDate、LocalTime、LocalDateTime 类的实例是不可变对象,,分别表示使用 ISO-8601 日历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
注 : ISO-8601 日历系统是国际标准化组织制定的现代公民的日期和时间的表示法
public class Time8 {
@Test
public void test1() throws Exception {//传统时间API存在多线程安全性问题
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
/*Callable cal = new Callable() {
@Override
public Date call() throws Exception {
return sdf.parse("20211227");
}
};*/
Callable<Date> cal = () -> sdf.parse("20211227");
ExecutorService pool = Executors.newFixedThreadPool(10);//创建一个线程池
List<Future<Date>> results = new ArrayList<>();
for (int i=0; i<10; i++){
results.add(pool.submit(cal));
}
for (Future f : results){
System.out.println(f.get());//多线程环境下,传统的时间API转换时间格式会报错
}
}
@Test
public void test2() throws Exception {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
Callable<LocalDate> cal = () -> LocalDate.parse("20211227", dtf);
ExecutorService es = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> list = new ArrayList<>();
for (int i=0; i<10; i++){
list.add(es.submit(cal));
}
for (Future<LocalDate> f : list){
System.out.println(f.get());//java8中新增的localDate是不可变的,和String一样每次操作都会创建一个新的对象,线程安全
}
}
}
时间格式,LocalDateTime
//LocalDate LocalTime LocalDateTime, 三者很类似,很多的API也都是相同方法调用的
@Test
public void test1(){
LocalDateTime time1 = LocalDateTime.now();//.now() 获取当前时间
System.out.println(time1);//2021-12-27T23:15:25.332
LocalDateTime time2 = LocalDateTime.of(2021, 12, 27, 23, 15);//.of() 获得一个实例时间
System.out.println(time2);//2021-12-27T23:15
LocalDateTime time3 = time1.plusYears(2);//.plus() 可以往时间里面添加年月日,时分秒,自动计算年份,和String一样,任何操作都会创建一个新的对象
System.out.println(time3);//2023-12-27T23:19:10.464
LocalDateTime time4 = time1.minusMonths(2);//.minus() 可以减少年月日,时分秒,自动计算年份,和String一样,任何操作都会创建一个新的对象
System.out.println(time4);//2021-10-27T23:22:40.331
}
时间戳格式,Instance
//Instant : 时间戳 (以 Unix 元年 : 1970年1月1日 00:00:00 到某个时间之间的毫秒值)
@Test
public void test2(){
Instant ins1 = Instant.now();//默认获取UTC时区,相差8个小时
System.out.println(ins1);//2021-12-27T15:27:00.353Z
OffsetDateTime ins2 = ins1.atOffset(ZoneOffset.ofHours(8));//.atOffset() 偏移量,对时间进行处理
System.out.println(ins2);//2021-12-27T23:31:16.248+08:00
System.out.println(ins1.toEpochMilli());//1640619138313, 返回时间戳
System.out.println(Instant.ofEpochSecond(1));//1970-01-01T00:00:00 添加一秒
}
计算时间之间的间隔,Duration
//Duration : 计算两个时间之间的间隔
@Test
public void test3() throws Exception{
Instant ins1 = Instant.now();
Thread.sleep(1000);
Instant ins2 = Instant.now();
Duration duration = Duration.between(ins1, ins2);//参数可以是时间戳也可以是时间类型
System.out.println(duration.toMillis());//1003
LocalDateTime ldt1 = LocalDateTime.now();
Thread.sleep(1000);
LocalDateTime ldt2 = LocalDateTime.now();
Duration duration2 = Duration.between(ldt1, ldt2);
System.out.println(duration2.toMillis());//1010
}
计算日期之间的间隔,Period
//Period : 计算两个日期之间的间隔
@Test
public void test4(){
LocalDate ld1 = LocalDate.of(2000, 01, 15);
LocalDate ld2 = LocalDate.now();
Period p = Period.between(ld1, ld2);//得到的是一个Period对象
System.out.println(p.getYears());//21
System.out.println(p.getMonths());//11
System.out.println(p.getDays());//12
}
TemporalAdjuster
:时间矫正器,可以对时间做特殊的矫正处理,有时我们可能需要获取例如将日期调整到"下个周日"等操作。
TemporalAdjusters
:该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。
//时间矫正器, 对时间进行特殊的处理后拿到自己想要的时间
@Test
public void test1(){
LocalDateTime ldt1 = LocalDateTime.now();
System.out.println(ldt1);//2021-12-28T22:28:07.984
LocalDateTime ldt2 = ldt1.withDayOfMonth(10);//指定月中的天
System.out.println(ldt2);//2021-12-10T22:28:07.984
LocalDateTime ldt3 = ldt1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));//下一个周日
System.out.println(ldt3);//2022-01-02T22:30:32.590
//配合lambda自定义方法, 计算下一个工作日
LocalDateTime nextWorkday = ldt1.with(e -> {
LocalDateTime time = (LocalDateTime) e;
if (DayOfWeek.FRIDAY.equals(time.getDayOfWeek())) {
return time.plusDays(3);
}else if (DayOfWeek.SATURDAY.equals(time.getDayOfWeek())) {
return time.plusDays(2);
}else {
return time.plusDays(1);
}
});
System.out.println(nextWorkday);
}
Java8 中加入了对时区的支持,带时区的时间分别为:ZonedDate、ZonedTime、ZonedDateTime。
其中每个时区都对应着ID,地区ID都为 “{区域} / {城市}” 的格式,例如 Asia/Shanghai 等。
ZoneId : 该类中包含了所有的时区信息,getAvailableZonedIds () : 获取所有可用时区信息,of (id) : 用指定的时区信息获取ZoneId 对象。
//时间格式化
@Test
public void test1(){
LocalDateTime ldt1 = LocalDateTime.now();
System.out.println(ldt1);//2021-12-28T22:52:06.605
DateTimeFormatter dtf1 = DateTimeFormatter.ISO_DATE;//DateTimeFormatter 里面有很多封装好的时间格式可供使用
String ldt2 = ldt1.format(dtf1);
System.out.println(ldt2);//2021-12-28
//可以自定义时间格式类型
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
String ldt3 = dtf2.format(ldt1);
System.out.println(ldt3);//2021年12月28日 23时15分11秒
//将时间按照某种格式转回来
LocalDateTime time = ldt1.parse(ldt3, dtf2);
System.out.println(time);//2021-12-28T23:15:11
}
//时区处理
@Test
public void test2(){
Set<String> set = ZoneId.getAvailableZoneIds();//得到所有的时区
set.forEach(System.out::println);
}
@Test
public void test3(){
LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("America/Marigot"));//获取指定时区的当前时间
System.out.println(ldt1);//2021-12-28T11:15:27.017
LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Asia/Shanghai"));//得到一个带时区格式的时间
System.out.println(zdt);//2021-12-28T23:17:29.521+08:00[Asia/Shanghai]
}