java8日期时间工具类

【README】

1)本文总结了java8中日期时间常用工具方法;包括:

  • 日期时间对象格式化为字符串;
  • 日期时间字符串解析为日期时间对象;
  • 日期时间对象转换;
    • 转换过程中,需要注意的是: Instant与Date带时区(易变),而LocalDateTime,LocalDate,LocalTime 不带时区(不可变);
  • 带时区的日期时间 ZonedDateTime 剖析;

2)日期时间工具类定义如下:

java 复制代码
public class BusiDateTimeUtils {

    /** 日期时间格式化器 */
    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /** 日期格式化器 */
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private BusiDateTimeUtils() {
        // do nothing.
    }
// .................... 
}

【1】当前日期时间操作

java 复制代码
/** -------------------- 1. 当前日期时间操作 -------------------- */
    public static String getNowLocalDateTimeStr() {
        return LocalDateTime.now().format(DATETIME_FORMATTER);
    }

    public static String getNowLocalDateStr() {
        return LocalDate.now().format(DATE_FORMATTER);
    }

【1.1】单测案例:

java 复制代码
/** -------------------- 1. 当前日期时间操作 -------------------- */
    @Test
    public void test1() {
        // 获取当前日期时间
        String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
        System.out.println("nowLocalDateTimeStr="+nowLocalDateTimeStr); // 2023-10-05 21:28:09

        // 获取当前日期
        String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
        System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
    }

【2】字符串解析为日期时间对象

java 复制代码
 /** -------------------- 2. 字符串解析为日期时间对象 -------------------- */
    public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
        return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
    }

    public static LocalDate parseLocalDate(String dateStr) {
        return LocalDate.parse(dateStr, DATE_FORMATTER);
    }

【2.1】单测案例

java 复制代码
/** -------------------- 2. 字符串解析为日期时间对象 -------------------- */
    @Test
    public void test2() {
        // 解析当前日期时间
        String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
        System.out.println("nowLocalDateTimeStr="+ nowLocalDateTimeStr); // 2023-10-05 21:29:32
        LocalDateTime parsedLocalDateTime = BusiDateTimeUtils.parseLocalDateTime(nowLocalDateTimeStr);
        System.out.println(parsedLocalDateTime); // 2023-10-05T21:29:32

        // 解析当前日期
        String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
        System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
        LocalDate parsedLocalDate = BusiDateTimeUtils.parseLocalDate(nowLocalDateStr);
        System.out.println(parsedLocalDate); // 2023-10-05
    }

【3】日期时间对象格式化为字符串

java 复制代码
/** -------------------- 3. 日期时间对象格式化为字符串 -------------------- */
    public static String format(LocalDateTime localDateTime) {
        return localDateTime.format(DATETIME_FORMATTER);
    }
    public static String format(LocalDate localDate) {
        return localDate.format(DATE_FORMATTER);
    }

【3.1】单测案例

java 复制代码
/** -------------------- 3. 日期时间对象格式化为字符串 -------------------- */
    @Test
    public void test3() {
        // 格式化当前日期时间对象为字符串
        String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
        System.out.println("nowLocalDateTimeStr="+ nowLocalDateTimeStr); // 2023-10-05 21:35:19

        LocalDateTime parsedLocalDateTime = BusiDateTimeUtils.parseLocalDateTime(nowLocalDateTimeStr);
        String formatedLocalDateTime = BusiDateTimeUtils.format(parsedLocalDateTime);
        System.out.println(formatedLocalDateTime); // 2023-10-05 21:35:19

        // 格式化当前日期对象为字符串
        String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
        System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05

        LocalDate parsedLocalDate = BusiDateTimeUtils.parseLocalDate(nowLocalDateStr);
        String formatedLocalDate = BusiDateTimeUtils.format(parsedLocalDate);
        System.out.println(formatedLocalDate); // 2023-10-05
    }

【4】*LocalDateTime 转为其他日期时间类型(重要)

java 复制代码
/** -------------------- 4. LocalDateTime 转为其他日期时间类型 -------------------- */
    public static LocalDate toLocalDate(LocalDateTime localDateTime) {
        return localDateTime.toLocalDate();
    }

    public static Instant toInstant(LocalDateTime localDateTime) {
        return localDateTime.toInstant(ZoneOffset.UTC);
    }

    public static Date toDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

**【说明】**LocalDateTime 转 Instant与Date时,做了一些特殊处理:

  • LocalDateTime没有时区,而Instant有时区 ;为了统一,把Instant的时区设置为0时区(UTC),则LocalDateTime与Instant都没有时区了;
  • LocalDateTime没有时区,Instant有时区,Date有时区:
    • 先把 LocalDateTime转为带时区的日期时间 ZonedDateTime
    • 再把 ZonedDateTime 转 Instant(默认时区为系统时区);
    • 最后把Instant转Date(默认时区为系统时区);

【4.1】单测案例

java 复制代码
/** -------------------- 4. LocalDateTime 转为其他日期时间类型 -------------------- */
    @Test
    public void test4() {
        LocalDateTime nowLocalDateTime = LocalDateTime.now();
        System.out.println("nowLocalDateTimeStr="+BusiDateTimeUtils.format(nowLocalDateTime)); // 2023-10-05 21:37:14

        // LocalDateTime 转 LocalDate
        LocalDate localDate = BusiDateTimeUtils.toLocalDate(nowLocalDateTime);
        LocalDate localDate2 = nowLocalDateTime.toLocalDate(); // 与上一行代码效果一样
        System.out.println("localDate=" + localDate); // 2023-10-05

        // LocalDateTime 转 Instant
        Instant nowInstant = BusiDateTimeUtils.toInstant(nowLocalDateTime);
        System.out.println(nowInstant); // 2023-10-05T21:37:14.677Z

        // LocalDateTime 转 Date
        Date nowDate = BusiDateTimeUtils.toDate(nowLocalDateTime);
        System.out.println(nowDate); // Thu Oct 05 21:37:14 CST 2023 
    }

【5】LocalDate 转为其他日期时间类型

java 复制代码
/** -------------------- 5. LocalDate 转为其他日期时间类型 -------------------- */
    public static LocalDateTime toLocalDateTime(LocalDate localDate) {
        return localDate.atStartOfDay();
    }

    public static Instant toInstant(LocalDate localDate) {
        return localDate.atStartOfDay().toInstant(ZoneOffset.UTC);
    }

    public static Date toDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

**【说明】**LocalDate 转 Instant与Date时,做了一些特殊处理:与 LocalDateTime 转 Instant与Date类似 ,这里不再赘述;参见本文章节【4】;

【5.1】单测案例

java 复制代码
/** -------------------- 5. LocalDate 转为其他日期时间类型 -------------------- */
    @Test
    public void test5() {
        LocalDate nowLocalDate = LocalDate.now();
        System.out.println("nowLocalDateStr="+BusiDateTimeUtils.format(nowLocalDate)); // 2023-10-05

        // LocalDate 转 LocalDateTime
        LocalDateTime localDateTime = BusiDateTimeUtils.toLocalDateTime(nowLocalDate);
        System.out.println("localDateTime=" + localDateTime); // 2023-10-05T00:00

        // LocalDate 转 Instant
        Instant nowInstant = BusiDateTimeUtils.toInstant(nowLocalDate);
        System.out.println(nowInstant); // 2023-10-05T00:00

        // LocalDate 转 Date
        Date nowDate = BusiDateTimeUtils.toDate(nowLocalDate);
        System.out.println(nowDate); //  Thu Oct 05 00:00:00 CST 2023
    }

【6】Instant 转为其他日期时间类型

java 复制代码
/** -------------------- 6. Instant 转为其他日期时间类型 -------------------- */
    public static LocalDateTime toLocalDateTime(Instant instantWithoutZone) {
        return LocalDateTime.ofInstant(instantWithoutZone, ZoneOffset.UTC);
    }

    public static LocalDate toLocalDate(Instant instantWithoutZone) {
        return toLocalDateTime(instantWithoutZone).toLocalDate();
    }

    public static Date toDate(Instant instantWithoutZone) {
        return toDate(toLocalDateTime(instantWithoutZone));
    }

【说明】

注意上述工具方法中入参 Instant变量是不带时区的,也可以理解为时区为UTC(0时区)

【6.1】单测案例

java 复制代码
/** -------------------- 6. Instant 转为其他日期时间类型 -------------------- */
    @Test
    public void test6() {
        Instant nowInstantWithoutZone = LocalDateTime.now().toInstant(ZoneOffset.UTC);
        System.out.println("nowZonedInstant="+nowInstantWithoutZone); // 2023-10-05T22:00:54.783Z
        System.out.println("Instant.now()=" + Instant.now()); // 2023-10-05T14:00:54.798Z(注意这里晚了8个小时)

        // Instant 转 LocalDateTime
        LocalDateTime localDateTime = BusiDateTimeUtils.toLocalDateTime(nowInstantWithoutZone);
        System.out.println("localDateTime=" + localDateTime); // 2023-10-05T22:00:54.783

        // Instant 转 LocalDate
        LocalDate localDate = BusiDateTimeUtils.toLocalDate(nowInstantWithoutZone);
        System.out.println("localDate=" + localDate); // 2023-10-05

        // Instant 转 Date
        Date date = BusiDateTimeUtils.toDate(nowInstantWithoutZone);
        System.out.println("date=" + date); // date=Thu Oct 05 22:00:54 CST 2023 
    }

【7】总结

【7.1】带时区的日期时间 ZonedDateTime 剖析

java 复制代码
/** -------------------- 7. 带时区的日期时间 -------------------- */
    @Test
    public void test7() {
        LocalDateTime nowLocalDateTime = LocalDateTime.now();
        System.out.println("nowLocalDateTime=" + nowLocalDateTime); // 2023-10-05T22:19:10.812 

        // 转为带时区的日期时间(系统时区)
        System.out.println("ZoneId.systemDefault()=" + ZoneId.systemDefault()); // Asia/Shanghai
        ZonedDateTime zonedDateTime = nowLocalDateTime.atZone(ZoneId.systemDefault());
        System.out.println("zonedDateTime.toInstant()(系统时区)="+zonedDateTime.toInstant()); // 2023-10-05T14:19:10.812Z(晚8个小时)

        // 转为带时区的日期时间(0时区)
        zonedDateTime = nowLocalDateTime.atZone(ZoneOffset.UTC);
        System.out.println("zonedDateTime.toInstant()(0时区)="+zonedDateTime.toInstant()); // 2023-10-05T22:19:10.812Z
    }

【说明】

  • 1)系统时区解析后的Instant,晚8个小时;
    • 原因: LocalDateTime 本身没有时区,根据系统时区(东8区 )把LocalDateTime 转为 ZonedDateTime后,把ZonedDateTime转为Instant时,jdk认为 LocalDateTime 的时区为东8区的时间,转Instant默认使用0时区;因为东8区比0时区快8个小时,所以减去了8个小时
  • 2)0时区解析后的Instant,转换正确;
    • 原因:LocalDateTime 本身没有时区,根据0时区把LocalDateTime 转为 ZonedDateTime后,把ZonedDateTime转为Instant时,jdk认为 LocalDateTime 的时区为0时区的时间,转Instant默认使用0时区,两者使用的时区一致,所以转换正确;

【7.2】日期时间工具类

java 复制代码
/**
 * @Description 日期时间工具类
 * @author xiao tang
 * @version 1.0.0
 * @createTime 2023年10月05日
 */
public class BusiDateTimeUtils {

    /** 日期时间格式化器 */
    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /** 日期格式化器 */
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private BusiDateTimeUtils() {
        // do nothing.
    }

    /** -------------------- 1. 当前日期时间操作 -------------------- */
    public static String getNowLocalDateTimeStr() {
        return LocalDateTime.now().format(DATETIME_FORMATTER);
    }

    public static String getNowLocalDateStr() {
        return LocalDate.now().format(DATE_FORMATTER);
    }

    /** -------------------- 2. 字符串解析为日期时间对象 -------------------- */
    public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
        return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
    }

    public static LocalDate parseLocalDate(String dateStr) {
        return LocalDate.parse(dateStr, DATE_FORMATTER);
    }

    /** -------------------- 3. 日期时间对象格式化为字符串 -------------------- */
    public static String format(LocalDateTime localDateTime) {
        return localDateTime.format(DATETIME_FORMATTER);
    }
    public static String format(LocalDate localDate) {
        return localDate.format(DATE_FORMATTER);
    }

    /** -------------------- 4. LocalDateTime 转为其他日期时间类型 -------------------- */
    public static LocalDate toLocalDate(LocalDateTime localDateTime) {
        return localDateTime.toLocalDate();
    }

    public static Instant toInstant(LocalDateTime localDateTime) {
        return localDateTime.toInstant(ZoneOffset.UTC);
    }

    public static Date toDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /** -------------------- 5. LocalDate 转为其他日期时间类型 -------------------- */
    public static LocalDateTime toLocalDateTime(LocalDate localDate) {
        return localDate.atStartOfDay();
    }

    public static Instant toInstant(LocalDate localDate) {
        return localDate.atStartOfDay().toInstant(ZoneOffset.UTC);
    }

    public static Date toDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    /** -------------------- 6. Instant 转为其他日期时间类型 -------------------- */
    public static LocalDateTime toLocalDateTime(Instant instantWithoutZone) {
        return LocalDateTime.ofInstant(instantWithoutZone, ZoneOffset.UTC);
    }

    public static LocalDate toLocalDate(Instant instantWithoutZone) {
        return toLocalDateTime(instantWithoutZone).toLocalDate();
    }

    public static Date toDate(Instant instantWithoutZone) {
        return toDate(toLocalDateTime(instantWithoutZone));
    }
}

【7.3】日期时间工具类单测案例

java 复制代码
/**
 * @Description 日期时间工具类单测案例 
 * @author xiao tang
 * @version 1.0.0
 * @createTime 2023年10月05日
 */
public class BusiDateTimeUtilsTest {

    /** -------------------- 1. 当前日期时间操作 -------------------- */
    @Test
    public void test1() {
        // 获取当前日期时间
        String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
        System.out.println("nowLocalDateTimeStr="+nowLocalDateTimeStr); // 2023-10-05 21:28:09

        // 获取当前日期
        String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
        System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
    }

    /** -------------------- 2. 字符串解析为日期时间对象 -------------------- */
    @Test
    public void test2() {
        // 解析当前日期时间
        String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
        System.out.println("nowLocalDateTimeStr="+ nowLocalDateTimeStr); // 2023-10-05 21:29:32
        LocalDateTime parsedLocalDateTime = BusiDateTimeUtils.parseLocalDateTime(nowLocalDateTimeStr);
        System.out.println(parsedLocalDateTime); // 2023-10-05T21:29:32

        // 解析当前日期
        String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
        System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
        LocalDate parsedLocalDate = BusiDateTimeUtils.parseLocalDate(nowLocalDateStr);
        System.out.println(parsedLocalDate); // 2023-10-05
    }

    /** -------------------- 3. 日期时间对象格式化为字符串 -------------------- */
    @Test
    public void test3() {
        // 格式化当前日期时间对象为字符串
        String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
        System.out.println("nowLocalDateTimeStr="+ nowLocalDateTimeStr); // 2023-10-05 21:35:19

        LocalDateTime parsedLocalDateTime = BusiDateTimeUtils.parseLocalDateTime(nowLocalDateTimeStr);
        String formatedLocalDateTime = BusiDateTimeUtils.format(parsedLocalDateTime);
        System.out.println(formatedLocalDateTime); // 2023-10-05 21:35:19

        // 格式化当前日期对象为字符串
        String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
        System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05

        LocalDate parsedLocalDate = BusiDateTimeUtils.parseLocalDate(nowLocalDateStr);
        String formatedLocalDate = BusiDateTimeUtils.format(parsedLocalDate);
        System.out.println(formatedLocalDate); // 2023-10-05
    }

    /** -------------------- 4. LocalDateTime 转为其他日期时间类型 -------------------- */
    @Test
    public void test4() {
        LocalDateTime nowLocalDateTime = LocalDateTime.now();
        System.out.println("nowLocalDateTimeStr="+BusiDateTimeUtils.format(nowLocalDateTime)); // 2023-10-05 21:37:14

        // LocalDateTime 转 LocalDate
        LocalDate localDate = BusiDateTimeUtils.toLocalDate(nowLocalDateTime);
        LocalDate localDate2 = nowLocalDateTime.toLocalDate(); // 与上一行代码效果一样
        System.out.println("localDate=" + localDate); // 2023-10-05

        // LocalDateTime 转 Instant
        Instant nowInstant = BusiDateTimeUtils.toInstant(nowLocalDateTime);
        System.out.println(nowInstant); // 2023-10-05T21:37:14.677Z

        // LocalDateTime 转 Date
        Date nowDate = BusiDateTimeUtils.toDate(nowLocalDateTime);
        System.out.println(nowDate); // Thu Oct 05 21:37:14 CST 2023
    }

    /** -------------------- 5. LocalDate 转为其他日期时间类型 -------------------- */
    @Test
    public void test5() {
        LocalDate nowLocalDate = LocalDate.now();
        System.out.println("nowLocalDateStr="+BusiDateTimeUtils.format(nowLocalDate)); // 2023-10-05

        // LocalDate 转 LocalDateTime
        LocalDateTime localDateTime = BusiDateTimeUtils.toLocalDateTime(nowLocalDate);
        System.out.println("localDateTime=" + localDateTime); // 2023-10-05T00:00

        // LocalDate 转 Instant
        Instant nowInstant = BusiDateTimeUtils.toInstant(nowLocalDate);
        System.out.println(nowInstant); // 2023-10-05T00:00

        // LocalDate 转 Date
        Date nowDate = BusiDateTimeUtils.toDate(nowLocalDate);
        System.out.println(nowDate); //  Thu Oct 05 00:00:00 CST 2023
    }

    /** -------------------- 6. Instant 转为其他日期时间类型 -------------------- */
    @Test
    public void test6() {
        Instant nowInstantWithoutZone = LocalDateTime.now().toInstant(ZoneOffset.UTC);
        System.out.println("nowZonedInstant="+nowInstantWithoutZone); // 2023-10-05T22:00:54.783Z
        System.out.println("Instant.now()=" + Instant.now()); // 2023-10-05T14:00:54.798Z(注意这里晚了8个小时)

        // Instant 转 LocalDateTime
        LocalDateTime localDateTime = BusiDateTimeUtils.toLocalDateTime(nowInstantWithoutZone);
        System.out.println("localDateTime=" + localDateTime); // 2023-10-05T22:00:54.783

        // Instant 转 LocalDate
        LocalDate localDate = BusiDateTimeUtils.toLocalDate(nowInstantWithoutZone);
        System.out.println("localDate=" + localDate); // 2023-10-05

        // Instant 转 Date
        Date date = BusiDateTimeUtils.toDate(nowInstantWithoutZone);
        System.out.println("date=" + date); // date=Thu Oct 05 22:00:54 CST 2023
    }
}
相关推荐
未知陨落3 分钟前
数据结构——二叉搜索树
开发语言·数据结构·c++·二叉搜索树
大波V54 分钟前
设计模式-参考的雷丰阳老师直播课
java·开发语言·设计模式
计算机-秋大田10 分钟前
基于微信小程序的平安驾校预约平台的设计与实现(源码+LW++远程调试+代码讲解等)
java·spring boot·微信小程序·小程序·vue·课程设计
无敌最俊朗@18 分钟前
unity3d————接口基础知识点
开发语言·c#
《源码好优多》22 分钟前
基于Java Springboot旅游信息推荐系统
java·spring boot·旅游
岁月无声code24 分钟前
Spring Boot 牛刀小试 org.springframework.boot:spring-boot-maven-plugin:找不到类错误
java·spring boot·github
不爱学习的YY酱36 分钟前
【计网不挂科】计算机网络第二章< 物理层 >习题库(含答案)
java·数据库·计算机网络
一丝晨光44 分钟前
gcc 1.c和g++ 1.c编译阶段有什么区别?如何知道g++编译默认会定义_GNU_SOURCE?
c语言·开发语言·c++·gnu·clang·gcc·g++
南城花随雪。1 小时前
Spring框架之装饰者模式 (Decorator Pattern)
java·开发语言·装饰器模式
编程、小哥哥1 小时前
设计模式之装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
java·设计模式·装饰器模式