不积跬步,无以至千里。不积小流,无以成江海。

Java8 全新的日期与时间 API

主要如下:

  • LocalDate 表示年月日的日期
  • LocalTime 表示时分秒的时间
  • LocalDateTime 则包含以上
  • Instant 获取秒数
    • Instant.now() 创建对象
    • Instant.getEpochSecond() 获取秒数
    • Instant.toEpochMilli() 获取毫秒数

为什么需要 LocalDateTime

  • Date 可读性差,我们经常需要使用 SimpleDateFormat 来格式化,使其按我们常用的方式显示。如果不格式化,则显示如下样式:

    1
    Tue sep 10 09:34:04 CST 2019
  • 当我们使用 SimpleDateFormat 的时候,又会出现其它问题。SimpleDateFormat 是线程不安全的。它的实现代码中使用了 calendar 共享变量,并且没有做线程安全控制。在多线程中使用时,会使 calendar.setTime 方法设置的值不准确。

    • 对于以上问题可以有解决方法:1、每个线程使用时都创建一个 SimpleDateFormat 对象,但这样开销太多。2、对使用 format 与 parse 方法的地方加锁,但导致线程阻塞性能差。3、使用 ThreadLcoal 保证每个线程最多只创建一次 SimpleDateFormat 对象,这种是比较好的方法。
    • 但总的来说,Date在处理时间上比较麻烦,而且其 getYear,getMonth 等方法已经被弃用了

新 API 特性

LocalDate、LocalTime、LocalDateTime、Instant 为不可变对象,在修改它们时会返回一个副本。

格式化

可以使用 DateTimeFormatter 进行格式化,其默认提供了一些格式化方式:

1
2
3
4
5
6
7
8
LocalDate localDate = LocalDate.of(2019,10,20);
//默认格式化方式
String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = localDate.format(DateTimeformatter.ISO_LOCAL_DATE);

//自定义格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String s3 = localDate.format(dateTimeFormatter);

解析时间

1
2
LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE);

另外,DateTimeFormatter 是线程安全的。

在 SpringBoot 中的使用

  • 指定日期序列化为时间戳 返回前端

    1
    2
    3
    4
    5
    6
    7
    	public class LocalDateTimeConverter extends JsonSerializer<LocalDateTime> {

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
    gen.writeNumber(value.toInstant(ZoneOffset.of("+8")).toEpochMilli());
    }
    }

    然后在字段上加了如下注解:

    1
    @JsonSerialize(using=LocalDateTimeConverter.class)
  • 指定日期时间格式化 返回前端

    在字段上加上如下注解:

    1
    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss")
  • 指定前端传入的日期进行格式化

    在字段上加如下注解:

    1
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")