23.Java 时间日期扩展(新时间日期、新时间日期格式化与解析、时间戳、计算时间日期差、时间矫正器、时区)

一、旧时间日期问题

  1. 在 java.util 和 java.sql 包下都有时间日期类

    • java.util.Date 类包含时间和日期

    • java.sql.Date 类值包含日期

  2. java.util.Date 类线程不安全,Date 对象可变

  3. 时间日期格式化类在 java.text 包下

  4. 时区处理困难,并不支持国际化,没有时区支持

java 复制代码
package com.my.olddate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class OldDateTest {
    public static void main(String[] args) {

        // 设计不合理
        Date date = new Date(2022, 7, 30);
        System.out.println(date); // Wed Aug 30 00:00:00 CST 3922

        System.out.println("--------------------");

        // 存在线程安全问题
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < 50; i++) {
            new Thread(() -> {
                try {
                    System.out.println(simpleDateFormat.parse("2022-07-30"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

二、新时间日期概述

1、基本介绍
  • JDK 8 增加了一套全新的时间日期 API,这套 API 设计合理,线程安全

  • 新时间日期 API 位于 java.time 包下

2、关键类介绍
说明
LocalDate 日期,年月日
LocalTime 时间,时分秒
LocalDateTime 日期时间,年月日时分秒
DateTimeFormatter 日期时间格式化类
Instant 时间戳,时间瞬间
Duration 计算时间差
Period 计算日期差
ZonedDateTime 包含时区的时间
  • Java 中使用的是 ISO 8601 日期和时间的表示方法,是世界民用历法,即公历,平年有 365 天,闰年有 366 天

三、新时间日期操作

1、新时间日期创建
  • 创建指定日期
java 复制代码
LocalDate date1 = LocalDate.of(2022, 6, 30);
System.out.println(date1);
  • 创建当前日期
java 复制代码
LocalDate date2 = LocalDate.now();
System.out.println(date2);
  • 创建指定时间
java 复制代码
LocalTime time1 = LocalTime.of(15, 30, 30, 123);
System.out.println(time1);
  • 创建当前时间
java 复制代码
LocalTime time2 = LocalTime.now();
System.out.println(time2);
  • 创建指定日期时间
java 复制代码
LocalDateTime localDateTime1 = LocalDateTime.of(2022, 6, 30, 15, 30, 30, 123);
System.out.println(localDateTime1);
  • 创建当前日期时间
java 复制代码
LocalDateTime localDateTime2 = LocalDateTime.now();
System.out.println(localDateTime2);
2、新时间日期信息获取
  • LocalDate 对象信息获取
java 复制代码
LocalDate localDate = LocalDate.now();

System.out.println("年:" + localDate.getDayOfYear());
System.out.println("月:" + localDate.getMonth().getValue() + "  " + localDate.getMonth());
System.out.println("日:" + localDate.getDayOfMonth());
System.out.println("星期:" + localDate.getDayOfWeek().getValue() + "  " + localDate.getDayOfWeek());
  • LocalTime 对象信息获取
java 复制代码
LocalTime localTime = LocalTime.now();

System.out.println("时:" + localTime.getHour());
System.out.println("分:" + localTime.getMinute());
System.out.println("秒:" + localTime.getSecond());
System.out.println("纳秒:" + localTime.getNano());
  • LocalDateTime 对象信息获取
java 复制代码
LocalDateTime localDateTime = LocalDateTime.now();

System.out.println("年:" + localDateTime.getDayOfYear());
System.out.println("月:" + localDateTime.getMonth().getValue() + "  " + localDateTime.getMonth());
System.out.println("日:" + localDateTime.getDayOfMonth());
System.out.println("星期:" + localDateTime.getDayOfWeek().getValue() + "  " + localDateTime.getDayOfWeek());
System.out.println("时:" + localDateTime.getHour());
System.out.println("分:" + localDateTime.getMinute());
System.out.println("秒:" + localDateTime.getSecond());
System.out.println("纳秒" + localDateTime.getNano());
3、新时间日期修改
  • 通过设置时间日期进行修改
java 复制代码
LocalDateTime now = LocalDateTime.now();

System.out.println("当前日期时间:" + now);
System.out.println("修改年:" + now.withYear(2000));
System.out.println("修改月:" + now.withMonth(10));
System.out.println("修改日:" + now.withDayOfMonth(25));
System.out.println("修改时:" + now.withHour(20));
System.out.println("修改分:" + now.withMinute(10));
System.out.println("修改秒:" + now.withSecond(30));
System.out.println("修改纳秒:" + now.withNano(123456));
  • 通过加减时间日期进行修改
java 复制代码
LocalDateTime now = LocalDateTime.now();

System.out.println("五年后:" + now.plusYears(5));
System.out.println("五个月后:" + now.plusMonths(5));
System.out.println("五天后:" + now.plusDays(5));
System.out.println("五小时后:" + now.plusHours(5));
System.out.println("五分钟后:" + now.plusMinutes(5));
System.out.println("五秒后:" + now.plusSeconds(5));
System.out.println("五纳秒后:" + now.plusNanos(5));

System.out.println("--------------------");

System.out.println("五年前:" + now.minusYears(5));
System.out.println("五个月前:" + now.minusMonths(5));
System.out.println("五天前:" + now.minusDays(5));
System.out.println("五小时前:" + now.minusHours(5));
System.out.println("五分钟前:" + now.minusMinutes(5));
System.out.println("五秒前:" + now.minusSeconds(5));
System.out.println("五纳秒前:" + now.minusNanos(5));
4、新时间日期线程安全问题
  • 新时间日期类每次修改都会创建新的对象,原来的对象是不会被修改的,不会存在线程安去问题
java 复制代码
package com.my.newdate;

import java.time.LocalDateTime;

public class NewDateSafeTest {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime localDateTime = now.plusYears(5);

        System.out.println(now + "  " + now.hashCode());
        System.out.println(localDateTime + "  " + localDateTime.hashCode());
    }
}
5、新时间日期比较
java 复制代码
package com.my.newdate;

import java.time.LocalDateTime;

public class NewDateCompareTest {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 1, 15, 30, 30);

        System.out.println(now.isAfter(localDateTime));
        System.out.println(now.isBefore(localDateTime));
        System.out.println(now.isEqual(localDateTime));
    }
}

四、新时间日期格式化与解析

  • 使用 java.time.format.DateTimeFormatter 进行格式化和解析操作
1、新时间日期格式化
  • 使用系统默认格式进行格式化
java 复制代码
LocalDateTime now = LocalDateTime.now();

DateTimeFormatter basicIsoDate = DateTimeFormatter.BASIC_ISO_DATE;

String format = now.format(basicIsoDate);
System.out.println(format);
  • 使用指定格式进行格式化
java 复制代码
LocalDateTime now = LocalDateTime.now();

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

String format = now.format(dateTimeFormatter);
System.out.println(format);
2、新时间日期解析
java 复制代码
package com.my.newdate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class NewDateParseTest {
    public static void main(String[] args) {
        String str2 = "2022-07-30 17:36:44";

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        LocalDateTime localDateTime2 = LocalDateTime.parse(str2, dateTimeFormatter);
        System.out.println(localDateTime2);
    }
}

五、时间戳

1、基本介绍
  • Instant 类,时间戳,可以获取从 1970-01-01 00:00:00 起的秒数
2、基本使用
  • 获取时间戳
java 复制代码
Instant now = Instant.now();
System.out.println(now);
  • 获取秒数
java 复制代码
Instant now = Instant.now();

System.out.println(now.getEpochSecond());
  • 获取纳秒数
java 复制代码
Instant now = Instant.now();

System.out.println(now.toEpochMilli());
  • 通过秒数获取时间戳
java 复制代码
Instant instant = Instant.ofEpochSecond(1659176030L);
System.out.println(instant);
  • 通过纳秒数获取时间戳
java 复制代码
Instant instant2 = Instant.ofEpochMilli(1659176030725L);
System.out.println(instant2);
  • 耗时统计
java 复制代码
Instant start = Instant.now();
Thread.sleep(5);
Instant end = Instant.now();
System.out.println("耗时(纳秒):" + (end.toEpochMilli() - start.toEpochMilli()));

六、计算时间日期差

  • Duration 和 Period 类,用来计算时间日期差
1、计算时间差
java 复制代码
package com.my.newdate;

import java.time.Duration;
import java.time.LocalTime;

public class DurationTest {
    public static void main(String[] args) {
        LocalTime now = LocalTime.now();
        LocalTime time = LocalTime.of(10, 1, 1);
        Duration duration = Duration.between(time, now);

        System.out.println("天数差:" + duration.toDays());
        System.out.println("小时数差:" + duration.toHours());
        System.out.println("分钟数差:" + duration.toMinutes());
        System.out.println("秒数差:" + duration.toMillis());
        System.out.println("纳秒数差:" + duration.toNanos());
    }
}
2、计算日期差
java 复制代码
package com.my.newdate;

import java.time.LocalDate;
import java.time.Period;

public class PeriodTest {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        LocalDate date = LocalDate.of(2020, 1, 1);
        Period period = Period.between(date, now);

        System.out.println("年份差:" + period.getYears());
        System.out.println("月份差:" + period.getMonths());
        System.out.println("日份差:" + period.getDays());
    }
}

七、时间矫正器

1、TemporalAdjuster
(1)基本介绍
  • TemporalAdjuster 是一个函数式接口,adjustInto 方法需要传入一个 Temporal 接口,Temporal 接口的实现类有LocalDate、LocalTime、LocalDateTime 等
java 复制代码
@FunctionalInterface
public interface TemporalAdjuster {
    Temporal adjustInto(Temporal temporal);
}
(2)基本使用
java 复制代码
package com.my.newdate;

import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjuster;

public class TemporalAdjusterTest {
    public static void main(String[] args) {

        // 将当前日期调整为下个月的第一天
        LocalDateTime now = LocalDateTime.now();

        TemporalAdjuster temporalAdjuster = (temporal) -> {
            LocalDateTime localDateTime = (LocalDateTime) temporal;
            LocalDateTime nextLocalDateTime = localDateTime.plusMonths(1).withDayOfMonth(1);
            return nextLocalDateTime;
        };

        LocalDateTime nextLocalDateTime = now.with(temporalAdjuster);
        System.out.println(nextLocalDateTime);
    }
}
2、TemporalAdjusters
(1)基本介绍
  • TemporalAdjusterTests 类有大量静态方法提供 TemporalAdjusterTest 接口的实现
(2)基本使用
java 复制代码
package com.my.newdate;

import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;

public class TemporalAdjustersTest {
    public static void main(String[] args) {

        // 将当前日期调整为明年的第一天
        LocalDateTime now = LocalDateTime.now();
        
        LocalDateTime nextLocalDateTime = now.with(TemporalAdjusters.firstDayOfNextYear());
        System.out.println(nextLocalDateTime);
    }
}

八、时区

1、基本介绍
  • JDK 8 增加了对时区的支持

  • LocalDate、LocalTime 和 LocalDateTime 类是不支持时区的

  • 支持时区类:ZonedDate、ZonedTime 和 ZonedDateTime 类

2、基本使用
  • 获取所有时区 ID
java 复制代码
ZoneId.getAvailableZoneIds().forEach(System.out::println);
  • 获取标准时间,对比当前时间,我国使用东八区,比标准时间早 8 个小时
java 复制代码
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);

// 获取标准时间
ZonedDateTime zonedDateTime = ZonedDateTime.now(Clock.systemUTC());
System.out.println(zonedDateTime);
  • 使用计算机默认时区,获取当前时间
java 复制代码
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime);
  • 获取指定时区的时间
java 复制代码
ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("America/Bogota"));
System.out.println(zonedDateTime2);
相关推荐
黄霑和金庸我都喜欢3 分钟前
桌面开发 的设计模式(Design Patterns)核心知识
开发语言·后端·golang
晚雾也有归处5 分钟前
结构体(C语言)
c语言·开发语言·数据结构·算法
qq_4335545414 分钟前
C++面向对象编程:纯虚函数、抽象类、虚析构、纯虚析构
开发语言·c++·算法
Q_19284999061 小时前
基于Spring Boot的便民医疗服务小程序
spring boot·后端·小程序
佛系小嘟嘟2 小时前
Android Jetpack Compose开发小组件【入门篇】
android·开发语言·android jetpack·小组件
开心工作室_kaic2 小时前
springboot548二手物品交易boot代码(论文+源码)_kaic
前端·数据库·vue.js·后端·html5
Java知识日历3 小时前
【内含例子代码】Spring框架的设计模式应用(第二集)
java·开发语言·后端·spring·设计模式
尘浮生5 小时前
Java项目实战II基于微信小程序的家庭大厨(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven
Java知识技术分享6 小时前
spring boot通过文件配置yaml里面的属性
java·spring boot·后端