Java8新特性(五)日期、时间API

一,旧API的问题

旧的API主要存在两个问题:

1,线程不安全

2,使用较麻烦

使用SimpleDateFormat演示线程不安全的示例:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestSimpleDateFormat {
    public static void main(String[] args) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for(int i=0;i<100;i++){
            executorService.execute(()->{
                try {
                    Date  date = format.parse("2023-03-19");
                    System.out.println(date);
                } catch (ParseException e) {
                    e.printStackTrace();
                }

            });
        }
        executorService.shutdown();
    }
}

运行后偶尔会报错如下:

使用LocalDate、DateTimeFormatter对上述代码进行改写之后,不再有线程安全问题:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestSimpleDateFormat {
    public static void main(String[] args) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for(int i=0;i<100;i++){
            executorService.execute(()->{
                LocalDate date = LocalDate.parse("2023-03-19",format);
                System.out.println(date);
            });
        }
        executorService.shutdown();
    }
}

二,常用API介绍

日期类LocalDate 、时间类LocalTime、日期时间类LocalDateTime

时间戳类型Instant、时间差Duration和Period 使用实例

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;

public class LocalTest {
    public static void main(String[] args) throws InterruptedException {
        LocalDate localDate = LocalDate.now();
        //默认的格式是iso-8601,即yyyy-MM-dd
        System.out.println("localdate=" + localDate);


        LocalTime localTime = LocalTime.now();
        //默认的格式是iso-8601,即HH:mm:ss.SSS
        System.out.println("localTime=" + localTime);
        //格式化成自定义格式
        String myTime = localTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        System.out.println("myTime=" + myTime);


        LocalDateTime localDateTime = LocalDateTime.now();
        //默认的格式是iso-8601,即yyyy-MM-ddTHH:mm:ss.SSS
        System.out.println("localDateTime=" + localDateTime);
        //格式化成自定义格式
        String myDateTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println("myDateTime=" + myDateTime);

        //从字符串解析出LocalDateTime
        localDateTime = LocalDateTime.parse("2023-02-10 08:10:30", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        //根据指定的年月日时分秒创建LocalDateTime
        localDateTime = LocalDateTime.of(2023, 3, 19, 10, 30, 15);

        //对LocalDateTime做加减,可对年、月、周、日、时、分、秒、毫秒等做加减操作,
        //加的方法以plus开头,减的方法以minus开头
        localDateTime = localDateTime.plusDays(5);
        System.out.println("执行plusDays后:"+localDateTime);

        localDateTime = localDateTime.minusHours(2);
        System.out.println("执行minusHours后:"+localDateTime);

        //获取年、月、周、日、时、分、秒、毫秒等
        System.out.println(localDateTime.getYear());
        System.out.println(localDateTime.getMonthValue());
        System.out.println(localDateTime.getDayOfWeek().getValue());
        System.out.println(localDateTime.getDayOfMonth());
        System.out.println(localDateTime.getHour());
        System.out.println(localDateTime.getYear());
        System.out.println(localDateTime.getSecond());
        System.out.println(localDateTime.getNano());

        //修改年、月、周、日、时、分、秒、毫秒等,以with开头的方法,修改后返回新的localDateTime对象
        System.out.println("执行with前:"+localDateTime);
        localDateTime = localDateTime.withYear(2024);//将年改为2024年
        localDateTime = localDateTime.withMonth(5);//将月份改为5月
        System.out.println("执行with后:"+localDateTime);

        //获取当前月份第一天
        localDateTime = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
        System.out.println("执行with后,当前月份第一天:"+localDateTime);

        //获取下一个周日
        localDateTime = localDateTime.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
        System.out.println("执行with后,下个周日:"+localDateTime);

        //自定义TemporalAdjuster实现类,将时间调整到下一个工作日
        localDateTime = localDateTime.with(temporal -> {
            //入参类型为Temporal,强转为子类型
            LocalDateTime input =  (LocalDateTime)temporal;
            //获取DayOfWeek
            DayOfWeek dayOfWeek = input.getDayOfWeek();

            if(dayOfWeek.equals(DayOfWeek.FRIDAY)){
                //入参是周五,则加3天
                return input.plusDays(3);
            }else if(dayOfWeek.equals(DayOfWeek.SATURDAY)){
                //入参是周六,则加2天
                return input.plusDays(2);
            }else{
                //其余加1天
                return input.plusDays(1);
            }
          }
        );
        System.out.println("下一个工作日是:"+localDateTime);

        Instant ins = Instant.now();
        System.out.println("当前UTC时区的时间戳:"+ins);//默认获取UTC时区(0时区),即格林威治时间,比Asia/Shanghai慢8小时
        System.out.println("在UTC时区基础上加8个小时:"+ins.atOffset(ZoneOffset.ofHours(8)));//加8个小时
        System.out.println("toEpochMilli转为毫秒值:"+ins.toEpochMilli());//转为毫秒值

        ins = Instant.ofEpochMilli(1679224886288L);//从时间戳创建Instant
        System.out.println("ofEpochMilli毫秒值转Instant:"+ins);

        //Duration计算两个Instant之间时差
        Instant instant1 = Instant.now();
        Thread.sleep(1000);
        Instant instant2 = Instant.now();
        Duration duration1 = Duration.between(instant1, instant2);
        System.out.println("Duration有几个to开头的方法:"+duration1.toMillis());
        System.out.println("Duration有几个get开头的方法:"+duration1.getSeconds());
        System.out.println("Duration也有plus/minus等方法:"+duration1.plusSeconds(10).toMillis());

        //Duration计算两个LocalTime之间时差
        LocalTime localTime1 = LocalTime.now();
        Thread.sleep(1000);
        LocalTime localTime2 = LocalTime.now();
        Duration duration2 = Duration.between(localTime1, localTime2);

        //Duration计算两个LocalTime之间时差
        LocalDateTime localDateTime1 = LocalDateTime.now();
        Thread.sleep(1000);
        LocalDateTime localDateTime2 = LocalDateTime.now();
        Duration duration3 = Duration.between(localDateTime1, localDateTime2);

        //Duration计算两个LocalDate之间时差
        LocalDate localDate1 = LocalDate.of(2023,1,1);
        LocalDate localDate2 = LocalDate.now();
        //Duration不能计算LocalDate之间的时差,虽然语法不报错,但执行时会报错
        //Duration duration4 = Duration.between(localDate1, localDate2);
        Period period = Period.between(localDate1, localDate2);
        System.out.println(period);//输出P2M18D, 2M表示2个月,18D表示18天,即两者之间相差2个月18天
        System.out.println("LocalDate之间相差天数:"+period.getDays());

    }
}

运行结果如下:

localdate=2023-03-20
localTime=00:26:33.145
myTime=00:26:33
localDateTime=2023-03-20T00:26:33.169
myDateTime=2023-03-20 00:26:33
执行plusDays后:2023-03-24T10:30:15
执行minusHours后:2023-03-24T08:30:15
2023
3
5
24
8
2023
15
0
执行with前:2023-03-24T08:30:15
执行with后:2024-05-24T08:30:15
执行with后,当前月份第一天:2024-05-01T08:30:15
执行with后,下个周日:2024-05-05T08:30:15
下一个工作日是:2024-05-06T08:30:15
当前UTC时区的时间戳:2023-03-19T16:26:33.182Z
在UTC时区基础上加8个小时:2023-03-20T00:26:33.182+08:00
toEpochMilli转为毫秒值:1679243193182
ofEpochMilli毫秒值转Instant:2023-03-19T11:21:26.288Z
Duration有几个to开头的方法:1020
Duration有几个get开头的方法:1
Duration也有plus/minus等方法:11020
P2M19D
LocalDate之间相差天数:19

Process finished with exit code 0

三,时区

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;

public class ZoneTest {
    public static void main(String[] args) {
        //获取所有时区
        Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        //availableZoneIds.forEach(System.out::println);

        //创建时不指定时区,默认取系统的时区
        LocalDateTime now = LocalDateTime.now();
        System.out.println("本地(系统默认时区)时间:"+now);

        //创建时指定时区
        LocalDateTime tokyo = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
        System.out.println("Asia/Tokyo时区的时间:"+tokyo);

        //ZonedDateTime,默认格式会带上时区偏移量和时区名称
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        System.out.println("zonedDateTime="+zonedDateTime);
    }
}

运行结果如下:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值