DateTimeFormatter 的使用

一、时间数据的并发处理

java.text.SimpleDateFormat 的实例对象在多线程共享使用的时候会抛出转换异常,可以使用ThreadLocal,但是也会导致其它问题。在JDK8以前,大多是使用Joda-Time作为时间的解决方案。但是,从 Java SE 8 开始,Joda-Time的官方就要求用户迁移到java.time (JSR-310) - 替代该项目的 JDK core部分。

在JDK8中,提供了许多线程安全的时间类,例如:

  • 本地日期和时间:LocalDateTimeLocalDateLocalTime
  • 带时区的日期和时间:ZonedDateTime
  • 时刻:Instant
  • 时区:ZoneIdZoneOffset
  • 时间间隔:Duration
  • 格式化:DateTimeFormatter

其中,DateTimeFormatter是SimpleFormatter的替代方案。

二、ISO 8601

国际标准ISO 8601,是国际标准化组织的日期和时间的表示方法,全称为《数据存储和交换形式·信息交换·日期和时间的表示方法》。目前是2004年12月1日发行的第三版“ISO8601:2004”以替代1998年的第一版“ISO8601:1998”与2000年的第二版“ISO8601:2000”。

常用的表示法

  • 日历日期表示法
    • 年为4位数,月为2位数,月中的日为2位数,例如,日期(2021年12月16日)可表示为2021-12-16,或20211216。
  • 顺序日期表示法
    • 可以将一年内的天的序数用3位数字表示,平年365天,闰年366天。如2021年12月16日可以表示为2021-350或2021350
  • 星期日历表示法
    • 年为4位数,用两位表示年内的第几个星期(星期前要加上一个大写字母W),用一位表示星期内的第几天。如2021年12月16日可以表示为2021-W50-4
  • 日历星期表示法
    • 星期日历表示法类似,只是少了一位数用于表示第几天
  • 日历月表示法
    • 用2位数表示本年内第几个日历月。例如,日期(2021年12月16日)可表示为2021-12
  • 日历年表示法
    • 例如,如2021年可写成:2021
  • 时间表示法
    • 使用冒号":"间隔开小时、分、秒的为扩展格式。小时、分和秒都用2位数表示。如果时间在零时区,并恰好与协调世界时相同,那么还需要在最后添加一个大写的Z。例如15:30:53Z;
    • 其他时区用实际时间加时差表示,当时的UTC+8时间表示为15:30:53+08:00或153053+0800,也可以简化成153053+08.

协调世界时(Coordinated Universal Time)是世界上调节时钟和时间的主要时间标准,它与0度经线的平太阳时相差不超过1秒。如果本地时间比UTC时间快,例如中国大陆[注 1]、香港、澳门、台湾、蒙古国、菲律宾、新加坡、马来西亚、澳大利亚西部的时间比UTC快8小时,就会写作UTC+8,俗称东八区。相反,如果本地时间比UTC时间慢,例如夏威夷的时间比UTC时间慢10小时,就会写作UTC-10,俗称西十区。

三、DateTimeFormatter 的使用

DateTimeFormatter用于打印和解析日期时间对象的格式化程序,而更复杂的格式可以由DateTimeFormatterBuilder进行处理。

预定义变量

为时间对象提供了预设格式,如下所示:

常量 描述 实例
ISO_DATE ISO日期,可带偏移量 2021-12-07 或 2021-12-07+01:00
ISO_DATE_TIME 带 ZoneId 的日期和时间 2021-12-07T09:50:46、2021-12-07T09:50:46+01:00、2021-12-07T09:50:46+01:00[Europe/Paris]
ISO_TIME ISO时间,可带偏移量 15:30、15:30+01:00
ISO_INSTANT 通过 UTC 格式进行格式化或解析的即时ISO日期 2021-12-07T09:50:46Z
ISO_LOCAL_DATE ISO 本地日期 2021-12-07
ISO_LOCAL_DATE_TIME ISO 本地日期和时间 2021-12-07T09:50:46
ISO_LOCAL_TIME ISO 本地时间 09:50:46
ISO_OFFSET_DATE 带偏移量的 ISO 日期 2021-12-07+01:00
ISO_OFFSET_DATE_TIME 带偏移量的 ISO 日期与时间 2021-12-07T09:50:46+01:00
ISO_OFFSET_TIME 带偏移量的 ISO 时间 09:50:46+01:00
ISO_ORDINAL_DATE 用于表示年内的第几天 2021-341
ISO_WEEK_DATE 年和周 2021-W49-2
ISO_ZONED_DATE_TIME 分区日期时间 2021-12-07T09:50:46+01:00[Europe/Paris]

实例

查询日期与时间:

LocalDate d = LocalDate.now(); // 当前日期
LocalTime t = LocalTime.now(); // 当前时间
LocalDateTime dt = LocalDateTime.now(); // 当前日期和时间
复制代码

Date 转换为 LocalDateTime:

public static void main(String[] args) {
    System.out.println(Instant.ofEpochMilli(new Date().getTime())
            .atZone(ZoneId.systemDefault())
            .toLocalDateTime());
}
复制代码

Date 转换为 LocalDate、LocalTime:

public static void main(String[] args) {
    System.out.println(Instant.ofEpochMilli(new Date().getTime())
            .atZone(ZoneId.systemDefault())
            .toLocalDate());
    System.out.println(Instant.ofEpochMilli(new Date().getTime())
            .atZone(ZoneId.systemDefault())
            .toLocalTime()
        );
}
复制代码

LocalDate转换为Date:

public Date convertLocalDateToDate(LocalDate localDate) {
    return java.sql.Date.valueOf(localDate);
}
复制代码

localDateTime转换为Date

public Date convertLocalDateTimeToDate(LocalDateTime localDateTime) {
    return java.sql.Timestamp.valueOf(localDateTime);
}
复制代码

获取当前时间(秒)的时间戳:

public static long getNowSecond() {
    return LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
}
复制代码

四、参考

协调世界时
ISO_8601

猜你喜欢

转载自juejin.im/post/7042184057936936973