【Java】基于time包的日期时间

用示波器抓一次MIPI D-PHY的波形,手把手教你读懂HS模式和LP模式的切换时序 本文详细解析了MIPI D-PHY信号的双模切换机制,包括高速模式(HS)和低功耗模式(LP)的波形捕获与诊断技巧。通过示波器设置、关键状态分析和实战案例,帮助工程师快速定位信号完整性问题,提升调试效率。 阅读详情

在JDK1.8,Java基于原来的(java.util包)日期时间处理API,进行了重大的升级(java.time包),解决了旧API的种种问题。本文尝试着简单概要地将java.time包中的日期时间进行分类整理,并介绍它的基本用法。

目录

设计思想

方法

time包对比于util包的设计升级

Instant类

Clock时钟

日期时间

时期

时间显示格式

时间格式控制符

解析、格式化时间

时间调整

TemporalAdjuster接口

自定义时间调节器

TemporalQuery接口

util包的时间与time包的时间互转

util包Date转time包LocalDate

Calendar转LocalDateTime

Calendar转ZonedDateTime


背景:

  • 为了解决java.util包中时间日期类的诸多设计不当、多线程不安全的问题
  • 于是引入了java.time包

初识java.time包:

  • JDK1.8引入
  • 基于ISO日历系统,它又是遵循 Gregorian规则(中国公历)

特性:所有类均生成不可变实例(final修饰),它们是线程安全的。并且这些类不提供公共构造函数,也就是说没办法通过new的方式直接创建,需要采用静态工厂方式获取实例。

为什么不应该使用java.util包中的类处理时间:

  • 毫秒值与日期直接转换比较繁琐,其次通过毫秒值来计算时间有大的误差
  • 老版本API线程不安全问题。SimpleDateFormat类是线程不安全的,在多线程的情况下,全局共享一个SimpleDateFormat类中的Calendar对象有可能会出现异常。需要开发者加锁。

Date、Calendar时间处理有误差

Date、Calendar时间处理有误差
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;

/**
 * 程序员小李出生于1995年12月16日,计算在当前这个时间他已经出生了多少天?
 * 算法:
 *  1.利用Date获取当前时间的毫秒值,利用Calendar获取小李出生时间的毫秒值
 *  2.将两个毫秒值做差,再转换成天数
 */
public class Main {

    public static void main(String[] args) {
        Date nowDate = new Date();
        Calendar birthDate = Calendar.getInstance();
        birthDate.set(1995,11,16); //要想设置 12 月份,则需要写11,因为从 0 开始

        long days = (nowDate.getTime() - birthDate.getTime().getTime()) / 1000 / 60 / 60 / 24;
        System.out.println(days); //输出:9152

        // 使用 java8 新版本的API来完成题目要求
        long daysTmp = ChronoUnit.DAYS.between(LocalDate.of(1995, 12, 16), LocalDate.now());
        System.out.println(daysTmp); //输出:9153
    }
}

 

设计思想

通过对java.time包中所有类的观察,我尝试将其中的类进行分类,以便记忆和在不同场景下应用。

日期时间:

  • LocalDate类:
    • 是一个不可变的日期时间对象,表示日期,通常被视为年月日。
    • 例如:年-月-日 yyyy-MM-dd 2020-05-02
  • LocalTime类:
    • 是一个不可变的日期时间对象,代表一个时间,通常被看作是小时-秒,时间表示为纳秒精度。
    • 例如:时:分:秒 HH:mm:ss 17:01:58.954758600
  • LocalDateTime类:
    • 是一个不可变的日期时间对象,代表日期时间,通常被视为年-月-日=时-分-秒。
    • 例如:年-月-日T时:分:秒 2020-05-02T17:01:58.954758600

年月日:

  • Year:获取年份
  • YearMonth:获取年、月
  • MonthDay:获取月、日
  • Month:枚举类。推荐在初始化LocalDate和LocalDateTime对象的时候,月份的参数使用枚举的方式传入,这样更简单易懂而且不易出错
  • DayOfWeek:周的枚举类。

时间间隔:

  • Instant类:
  • 表示当前瞬时时间。
  • 祖鲁时间(格林威治时间/国际标准时间)Instant:2020-05-02T09:01:58.930823200Z
  • Duration类:表示秒或纳秒时间间隔,适合处理较短的时间,需要更高的精确性。
  • Period类:表示一段时间的年、月、日的间隔。

时区:

  • ZonedDateTime类:
    • 带时区的日期时间
    • 是具有时区的日期时间的不可变表示,此类存储所有日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间。
    • 对应ZoneId加LocalDateTime的结合
    • 例如:年-月-日T时:分:秒+08:00[Asia/Shanghai] 表示时区 ZonedDateTime:2020-05-02T17:01:58.955756+08:00[Asia/Shanghai]
  • ZoneId:时区,会根据夏令时调整。
  • TimeZone:
  • ZoneOffest:时区偏移量(比如:+8:00),固定时间的偏移。不会根据夏令时调整,固定不变的
  • OffsetTime:
  • OffsetDateTime:
    • 对应ZoneOffset加LocalDateTime的结合

工具类:

  • DateTimeFormatter:日期时间格式化类
  • ChronoUnit:日期枚举类(在时间加减操作可用到)

方法

以下的方法,几乎time包下的所有可实例化类都能调用。

now()方法:

  • 静态工厂方法;
  • 功能:获取当前时间的实例对象,例如:Instant instantNow = Instant.now(); LocalDate dateNow = LocalDate.now(); Year year = Year.now();

of()方法:

  • 静态工厂方法
  • 功能:设定给定的参数对应的日期/时间对象,基本上每个基本类都有of方法用于生成的对应的对象,而且重载形式对边,可以根据不同的参数生成对应的数据。
  • LocalDate date = LocalDate.of(2018, Month.AUGUST, 8);
  • LocalDateTime timeLocalDateTime.of(2018, Month.AUGUST, 8, 8, 0);

with()方法:修改时间

parse()方法:

  • 静态工厂方法
  • 专注解析时间

plus()方法:

  • 对时间进行加法操作
  • 如果参数是负数也能够有minus方法的效果

minus()方法:对时间进行减法操作

format()方法:对时间的显示格式进行转换

to()方法:把当前时间对象转换成另外一个

at()方法:把这个对象与另一个对象组合起来

 

time包对比于util包的设计升级

time包与util包中的Calendar对比

  • 在java.time当中,星期一的值为1,星期日的值为7,而在Calendar当中星期日的值为1。
  • 在java.time中一月份的值为1,Calendar一月份的值为0(多么反人类的设计)

 

  • java.time:包含值对象的基础包
  • java.time.chrono:提供对不同的日历系统的访问
  • java.time.format:格式化和解析时间和日期
  • java.time.temporal:包括底层框架和扩展特性
  • java.time.zone:包含时区支持的类

Instant类

  1. instant:瞬间、立即
  2. java.time.Instant
  3. 可用于时间各种类型之间的转换桥梁

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.now(); //获取当前瞬时的时间
        System.out.println(instant); //输出:2021-02-10T14:04:54.647769800Z
    }
}

Clock时钟

  • Clock是关联上时区的时钟,Clock可以获取时间戳和时区ZoneId,用来代替System.currentTimeMillis()和TimeZone.getDefault()。
  • 它是个抽象类,一共有四个子类(如上图)
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        //系统默认本地时钟:SystemClock
        Clock clock = Clock.systemDefaultZone();
        System.out.println(clock.getZone()); //获取时区信息:Asia/Singapore
        Instant instant = clock.instant();
        System.out.println(instant); //获取日期时间:2021-01-19T01:19:46.595993200Z

        //偏移时钟:OffsetClock
        Clock clock01 = Clock.systemDefaultZone();
        Clock pastClock = clock01.offset(clock01, Duration.ofMillis(-10000));
        System.out.println(pastClock.getZone()); //时区:Asia/Singapore
        System.out.println(clock01.millis() - pastClock.millis());//时间差:当前时间和过去pastClock相差10000毫秒
    }
}

 

日期时间

LocalDate、LocalTime、LocalDateTime:获取所在时区的详细时间

  • LocalDate类:
    • 是一个不可变的日期时间对象,表示日期,通常被视为年月日。
    • 例如:年-月-日 yyyy-MM-dd 2020-05-02
  • LocalTime类:
    • 是一个不可变的日期时间对象,代表一个时间,通常被看作是小时-秒,时间表示为纳秒精度。
    • 例如:时:分:秒 HH:mm:ss 17:01:58.954758600
  • LocalDateTime类:
    • 是一个不可变的日期时间对象,代表日期时间,通常被视为年-月-日=时-分-秒。
    • 例如:年-月-日T时:分:秒 2020-05-02T17:01:58.954758600

实例:为LocalDateTime添加时区信息

import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        // 1、封装 LocalDateTime对象,参数自定义 ->2018年11月11日 8点54分38秒
        LocalDateTime localDateTime = LocalDateTime.of(2018, Month.NOVEMBER, 11, 8, 54, 38);
        // 2、 localDateTime对象现在只是封装了一个时间,并没有时区相关的数据,所以要添加时区信息到对象中,使用 atZone()方法
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
        //上海当前的时间是:2018-11-11T08:54:38+08:00[Asia/Shanghai]
        System.out.println("上海当前的时间是:" + zonedDateTime);

        // 3、更改时区查看其它时区的当前时间,通过 withZoneSameInstant()方法即可
        ZonedDateTime tokyoZonedDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
        //在上海同一时刻,Asia/Tokyo的时间是:2018-11-11T09:54:38+09:00[Asia/Tokyo]
        System.out.println("在上海同一时刻,Asia/Tokyo的时间是:" + tokyoZonedDateTime);
    }
}

时期

Duration操作的时间跨度是时分秒,外加纳秒

Period操作的时间跨度是年月日

period实例:

import java.time.LocalDateTime;
import java.time.Period;

//需求:今天程序员小张查看自己的车辆保险记录的时候看到还有2年3月8天就到期了,计算到期的时间是什么时候
public class Main {
    public static void main(String[] args) {
        // 1、封装当前时间  -> now方法
        LocalDateTime now = LocalDateTime.now();
        // 2、在当前时间的基础上进行+2年,+3月,+8天的操作
        // 然后获得一个截止日期对象,这个对象表示的时间就是保险到期的时间。
        LocalDateTime endTime = now.plusYears(2).plusMonths(3).plusDays(8);
        //当前的时间是:2020-05-03T13:52:34.316278400保险到期的时间是:2022-08-11T13:52:34.316278400
        System.out.println("当前的时间是:" + now + "保险到期的时间是:" + endTime);

        // plus(TemporalAmount amountToAdd)
        // 1、首先封装 priod.of()方法传进去参数
        Period period = Period.of(2, 3, 8);
        // 2、通过 now()方法的 plus()方法传进去
        LocalDateTime endTime1 = now.plus(period);
        //当前的时间是:2020-05-03T14:06:16.239460900保险到期的时间是:2022-08-11T14:06:16.239460900
        System.out.println("当前的时间是:" + now + "保险到期的时间是:" + endTime1);
    }
}

 

时间显示格式

把时间的显示格式指定为自己想要的格式,功能就如java.util.SimpleDateFormat类一样。

时间格式控制符

  • G 年代标志符
  • y 年
  • M 月
  • d 日
  • h 时 (12小时制)
  • H 时 (24小时制)
  • m 分
  • s 秒
  • S 毫秒
  • E 星期几
  • D 一年中的第几天
  • F 一月中第几个星期(以每个月1号为第一周,8号为第二周为标准计算)
  • w 一年中第几个星期
  • W 一月中第几个星期(不同于F的计算标准,是以星期为标准计算星期数,例如1号是星期三,是当月的第一周,那么5号为星期日就已经是当月的第二周了)
  • a 上午 / 下午 标记符
  • k 时 (24小时制,其值与H的不同点在于,当数值小于10时,前面不会有0)
  • K 时 (12小时值,其值与h的不同点在于,当数值小于10时,前面不会有0)
  • z 时区

解析、格式化时间

直接调用format方法进行时间格式化,直接调用parse方法进行时间的解析。

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

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

        // localDateTime对象可以直接调用format方法进行格式化
        String s1 = localDateTime.format(DateTimeFormatter.ISO_DATE); //ISO_DATE:2020-05-03
        String s2 = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME); //ISO_DATE_TIME:2020-05-03T17:55:04.1945268

        String s3 = "2066-01-06T17:55:04.1945268";
        // 解析字符串的方式通过LocalDateTime类的静态方法parse传入需要解析的字符串即可
        LocalDateTime parse = LocalDateTime.parse(s3); //如果不指定转换格式,则默认为ISO_LOCAL_DATE_TIME(看源码可得)
        System.out.println(parse);
    }
}

通过DateTimeFormatter的ofLocalizedDate的方法也可以调整格式化的方式。其参数需要FormaStyle枚举类。

FormaStyle枚举类:

  • Full:全显示(年月日+星期)
  • Long:全显示(年月日)
  • Medium:缩略显示(没有年月日汉字)
  • SHORT:精简显示(精简年+月日)
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

public class Main {
    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.now();
        // 通过DateTimeFormatter 的 ofLocalizedDate指定解析格式
        String r1 = localDateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL));
        String r2 = localDateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG));
        String r3 = localDateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
        String r4 = localDateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT));

        //FULL:2020年5月3日星期日
        System.out.println("FULL:" + r1);
        //LONG:2020年5月3日
        System.out.println("LONG:" + r2);
        //MEDIUM:2020年5月3日
        System.out.println("MEDIUM:" + r3);
        //SHORT:2020/5/3
        System.out.println("SHORT:" + r4);
    }
}

按规则进行转换

java.time.format.DateTimeFormatter

  • 此类的功能与SimpleDateFormat类的功能类似,此类也是线程安全的;
  • 在写成时间处理工具类时,可作为静态成员变量,而不用每次都new一个SimpleDateFormat实例;
  • 此类是用来创建日期显示的模板,然后对于日期的格式化和解析还是使用LocalDateTime等类的parse静态方法和format方法,其模板属性格式是和SimpleDateFormat一样的
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class Main {
    //时间日期与String互转
    public static void main(String[] args) throws ParseException {
        /*
            时间format
         */
        //java.util包中对时间的处理
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        String dateStr = simpleDateFormat.format(date);
        System.out.println("SimpleDateFormat: " +dateStr);

        //java.time包中对时间的处理
        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy月MM月dd日 HH时mm分ss秒");
        String dateFormatter = formatter.format(localDateTime);
        System.out.println("DateTimeFormatter: " +dateFormatter);

        /*
            时间parse
         */
        String dateStrParse01 = "2066-06-06 16:16:16";
        SimpleDateFormat sdfParse = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //pattern中的'-',':'要和串中的一致
        Date dateParse = sdfParse.parse(dateStrParse01); //向外抛ParseException异常
        System.out.println("SimpleDateFormat Parse: " +dateParse);//+sdfParse.format(dateParse));

        String dateStrParse02 = "2077-07-07 06:06:06";
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTimeParse = LocalDateTime.parse(dateStrParse02, parser);
        System.out.println("DateTimeFormatter Parse: " +localDateTimeParse);
    }
}

 

时间调整

在很多时候,我们需要对时间进行调整操作。例如,将当前时间调节到下个周的周日,下一个儿童节,上一个儿童节,我们就需要用到时间调节器。

有关时间调节器的API,都在java.time.temporal包中。

TemporalAdjuster接口

TemporalAdjuster功能:

  • 时间调节器,将时间调节到下个周的周日,下一个工作日,或者本月中的某一天,这个时候可以使用调节器TemporalAdjuster来更方便的处理日期。
  • 因为java.time的时间类都是不可变,因此需要调整时间时,可调用该方法实现。

设计思想:

  • 通过with方法传入TemporalAdjuster接口的实现类对象,就可以进行修改。
  • 实现类对象是由TemporalAdjusters类的静态方法来提供
  • 注意TemporalAdjusters类并不是TemporalAdjuster接口的实现类,只不过TemporalAdjusters类中的静态方法实现了TemporalAdjuster接口,并将实现的对象返回了而已。
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

public class Main {
    //TemporalAdjusters枚举类用法实例
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        //返回当前月份的第一天的日期
        System.out.println(now.with(TemporalAdjusters.firstDayOfMonth()));
        //返回当前月份的最后一天
        System.out.println(now.with(TemporalAdjusters.lastDayOfMonth()));
        //返回下一个月的第一天的日期
        System.out.println(now.with(TemporalAdjusters.firstDayOfNextMonth()));
    }
}

自定义时间调节器

要自定义日期时间的更改逻辑,可以通过实现TemporalAdjuster类接口的方式来完成。

步骤:

  • 创建类实现TemporalAdjuster接口
  • 实现TemporalAdjuster中的 adjusterInto()方法,传入一个日期时间对象,完成逻辑之后返回日期事件对象。
  • 通过with方法传入自定义调节器对象完成更改。
需求:假如员工一个月中领取工资,发薪日是每个月的15日,如果发薪日是周六、周末,则调整为周五。
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;

public class Main {
    public static void main(String[] args) {
        // 封装 LocalDate 对象为2018年12月1日
        LocalDate payDay = LocalDate.of(2018, Month.DECEMBER, 15);
        // 计算 payDay 的真实发薪日是什么时候
        LocalDate realPayDay = LocalDate.from(new PayDayAdjuster().adjustInto(payDay));
        //预计的发薪日是:2018-12-15
        System.out.println("预计的发薪日是:" + payDay);
        //真实的发薪日是:2018-12-14
        System.out.println("真实的发薪日是:" + realPayDay);
    }
}

/**
 * 自定义调整器
 * 传入一个日期时间对象,判断是不是15号,如果不是就修改为15号,如果是周六或者是周日,则改为周五
 */
class PayDayAdjuster implements TemporalAdjuster {
    @Override
    public Temporal adjustInto(Temporal temporal) {
        // Temporal 是time包下所有日期事件类对象的顶级父接口,实际上可以理解为传入的是 LocalDate或者 LocalTime对象
        // 1、需要将 temporal 转换为 LocalDate 对象
        LocalDate payDay = LocalDate.from(temporal);
        // 2、判断当前封装的时间中的日期是不是当月15号,如果不是就修改为15
        int day;
        if(payDay.getDayOfMonth() != 15) {
            day = 15;
        }else {
            day = payDay.getDayOfMonth();
        }
        // 将 payDay中的值改为15
        LocalDate realPayDay = payDay.withDayOfMonth(day);
        // 3、判断 readPayDay 对象中封装的星期数是不是周六或者是周日,如果是就改为上一周周五
        if (realPayDay.getDayOfWeek() == DayOfWeek.SUNDAY ||
                realPayDay.getDayOfWeek() == DayOfWeek.SATURDAY) {
            // 如果发薪日是周末则修改为上一个周五
            realPayDay = realPayDay.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
        }
        return realPayDay;
    }
}

TemporalQuery接口

计划日期距离某一天特定天数差距多少天,可以自定义类实现TemporalQuery接口并且作为参数传到query方法中。

需求:计算当前时间距离下一个劳动节还有多少天?
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQuery;

public class Main {
    public static void main(String[] args) {
        // 计算距离下一个劳动节还有多少天
        LocalDate now = LocalDate.now();
        // 调用now的query方法,然后将我们自己的实现类UtilDayQueryImpl作为参数传入
        Long day = now.query(new UtilDayQueryImpl());
        //2020-05-03
        System.out.println(now);
        //363
        System.out.println(day);
    }
}

//计算当前时间距离下一个劳动节还有多少天?
class UtilDayQueryImpl implements TemporalQuery<Long> {
    @Override
    public Long queryFrom(TemporalAccessor temporal) {
        // 1、TemporalAccessor是LocalDateTime的顶级父接口,相当于LocalDate就是这个接口,将Temporal转换为
        // LocalDate 进行使用
        LocalDate now = LocalDate.from(temporal);
        // 2、封装当年劳动节时间
        LocalDate laborDay = LocalDate.of(now.getYear(), Month.MAY, 1);
        // 3、判断当前时间是否已经超过了当年的劳动节
        if (now.isAfter(laborDay)) {
            laborDay = laborDay.plusYears(1);
        }
        // 4、通过ChronoUnit的between来计算两个时间电的差额
        long days = ChronoUnit.DAYS.between(now, laborDay);
        return days;
    }
}
计算任意时间距离圣诞节、儿童节、劳动节相差多少天
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQuery;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        // 1、封装任意日期
        LocalDate date = LocalDate.of(2020, 5, 30);
        // 2、调用date 对象的query方法查询距离三个节日的差额
        Map<String, Long> query = date.query(new CalculatorHappyDay());
        // 3、打印结果
        System.out.println(query.get("ChristmasDay"));
        System.out.println(query.get("ChildrensDay"));
        System.out.println(query.get("LaborDay"));
    }
}

/**
 * 类型:计算任意时间距离圣诞节、儿童节、劳动节相差多少天
 * 说明:TemporalQuery的泛型类型表明要返回的类型
 *      String表示节日类型;Long表示多少天
 */
class CalculatorHappyDay implements TemporalQuery<Map<String, Long>> {
    @Override
    public Map<String, Long> queryFrom(TemporalAccessor temporalAccessor) {
        // 1、将传入的参数转换为LocalDate对象
        LocalDate date = LocalDate.from(temporalAccessor);
        // 2、封装当年的圣诞节/儿童节/劳动节的日期时间对象
        LocalDate d1 = LocalDate.of(date.getYear(), Month.DECEMBER, 25);
        LocalDate d2 = LocalDate.of(date.getYear(), Month.JUNE, 1);
        LocalDate d3 = LocalDate.of(date.getYear(), Month.MAY, 1);
        // 3、判断date是否已经超过了d1/d2/d3
        if (date.isAfter(d1)) {
            d1 = d1.plusYears(1);
        }
        if (date.isAfter(d2)) {
            d2 = d2.plusYears(1);
        }
        if (date.isAfter(d3)) {
            d3 = d3.plusYears(1);
        }

        //计算差值
        Map<String, Long> result = new HashMap<>();
        result.put("ChristmasDay", ChronoUnit.DAYS.between(date,d1));
        result.put("ChildrensDay", ChronoUnit.DAYS.between(date,d2));
        result.put("LaborDay", ChronoUnit.DAYS.between(date,d3));
        return result;
    }
}

其中:

java.time.temporal.ChronoUnit

  1. 时间度量单位,枚举类,继承TemporalUnit。
  2. 它表示的是一个时间间隔用什么单位度量,比如两天的时间间隔可以用48个小时代替表示。
  3. 一般用于某时间单位的设置,加减操作

java.time.temporal.ChronoField

  1. 继承TemporalField,枚举类。
  2. 和ChronoUnit功能类似,基于TemporalUnit实现,一般用于获取不同时间域的值

 

util包的时间与time包的时间互转

旧API转time包下的API

  • Date.toInstant()
  • Date.from(Instant)
  • Calendar.toInstant()

time包与JDBC

  • date -> LocalDate
  • time -> LocalTime
  • timestamp -> LocalDateTime

util包Date转time包LocalDate

转换方案:

  1. 使用Instant类作为中介:util包中的Date类,Calendar类在java1.8都提供了一个新的方法,叫做toInstant(),可以将当前对象转换为Instant对象,通过给Instant添加时区信息之后就可以转换为LocalDate对象。
  2. 使用java.sql.Date和java.sql.TimeStamp类提供的方法进行转换。其中Date类提供toLocalDate()方法,TimeStamp类提供toLocalDateTime()方法。

toInstant()方法

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        // 初始化Date()对象
        Date d = new Date();
        // 1、将Date()对象转换成Instant对象
        Instant i = d.toInstant();
        // 2、Date类包含日期和时间信息,但是不提高时区信息,和Instant一样,通过Instant的anZone()来进行添加时区信息
        ZonedDateTime zonedDateTime = i.atZone(ZoneId.systemDefault());
        // 3、通过LocalDate方法转换
        LocalDate date = zonedDateTime.toLocalDate();
        // 转换之前Sun May 03 17:21:18 CST 2020
        System.out.println("转换之前" + d);
        // 转换之后2020-05-03
        System.out.println("转换之后" + date);
    }
}

java.sql.Date和java.sql.TimeStamp类转换

import java.sql.Date;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;

public class Main {
    public static void main(String[] args) {
        // 初始化 Date对象
        Date d = new Date();
        /*
         * java.sql.Date类提供了转换为LocalDate的方法,那么可以将java.util.Date先转换为java.sql.Date
         * 通过java.sql.Date提供的方式转换为LocalDate.
         * java.sql.Date类构造的时候需要毫秒值, -> java.Util.Date类中提供了一个获取毫秒值的方法, getTime()
         * */
        java.sql.Date date = new java.sql.Date(d.getTime());
        LocalDate localDate = date.toLocalDate();
        // 转换前的java.util.Date对象是:Sun May 03 17:39:46 CST 2020
        System.out.println("转换前的java.util.Date对象是:" + d);
        // 转换前的java.sql.Date对象是:2020-05-03
        System.out.println("转换前的java.sql.Date对象是:" + date);
        // 转换前的java.time.LocalDate对象是:2020-05-03
        System.out.println("转换前的java.time.LocalDate对象是:" + localDate);
    }
    public static void transfer() {
        /*
         * sql.Date转LocalDate
         */
        // 初始化 java.sql.Date 对象
        Date d = new Date(System.currentTimeMillis());
        // java.sql.Date 自带了转换成LocalDate 的方法, toLocalDate.
        LocalDate date = d.toLocalDate();
        // 转换前的java.sql.Date对象是:2020-05-03
        System.out.println("转换前的java.sql.Date对象是:" + d);
        // 转换后的java.time.LocalDate对象是:2020-05-03
        System.out.println("转换后的java.time.LocalDate对象是:" + date);

        /*
         * sql.TimeStamp转LocalDateTime
         */
        // 初始化java.sql.Timestamp对象,  世界戳对象
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        // java.sql.Timestamp 中也自带了转换成LocalDate 的方法  toLocalDate
        LocalDateTime localDateTime = timestamp.toLocalDateTime();
        // 转换之前的java.sql.Timestamp对象是:2020-05-03 17:25:29.057
        System.out.println("转换之前的java.sql.Timestamp对象是:" + timestamp);
        // 转换之后的java.time.LocalDateTime对象是:2020-05-03T17:25:29.057
        System.out.println("转换之后的java.time.LocalDateTime对象是:" + localDateTime);
    }
}

Calendar转LocalDateTime

Calendar对象可以获取到年月日时分秒的信息,这些信息可以作为LocalDateTime构造方法的参数

import java.time.LocalDateTime;
import java.util.Calendar;

public class Main {
    public static void main(String[] args) {
        // 1、初始化Calendar对象
        Calendar calendar = Calendar.getInstance();
        // 2、通过get获取Calendar对象中封装的数据
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        // 3、将以上获取的六个参数作为LocalDateTime的of方法的参数传递,封装的月份是从0开始的,所以month要加1
        LocalDateTime localDateTime = LocalDateTime.of(year, month + 1, day, hour, minute, second);
        System.out.println(localDateTime);
    }
}

Calendar转ZonedDateTime

Calendar对象字Java1.1开始提供了一个方法获取时区对象的方法,getTimeZone(),要将Calendar对象转换为ZonedDateTime需要先获取到时区对象。从Java1.8开始TimeZone类提供了一个方法可以获取到ZonedId。获取到ZonedId之后就可以初始化ZOnedDateTime对象了,ZonedDateTime类有一个ofInstant()方法,可以将一个Instant对象和ZonedId对象作为参数传入构造一个ZonedDateTime对象。

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        // 1、初始化一个Calendar对象
        Calendar calendar = Calendar.getInstance();
        // 2、Calendar对象自java1.1以后开始提供了一个方法用于获取时区对象getTimeZone()方法,要将Calendar转换为
        // ZoneedDateTime对象需要先获取到时区对象
        TimeZone timeZone = calendar.getTimeZone();
        // 3、从java1.8开始TimeZone类提供了一个方法可以获取到ZoneId -> 拿拿ZoneId对象来构建ZonedDateTime
        ZoneId zoneId = timeZone.toZoneId();
        // 4、zonedDateTime类有一个ofInstant方法。可以将Instant对象和ZoneId对象封装为一个ZonedDateTime
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(calendar.toInstant(), zoneId);
        // 转换之前的Calendar对象是:java.util.GregorianCalendar[time=1588499141905,areFieldsSet=true,areAll
        // FieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",.......
        System.out.println("转换之前的Calendar对象是:" + calendar);
        // 转换之后的ZonedDateTime对象是:2020-05-03T17:45:41.905+08:00[Asia/Shanghai]
        System.out.println("转换之后的ZonedDateTime对象是:" + zonedDateTime);
    }
}

 

总结:

  • 本文基于JDK1.8,概略地介绍了java.time包下的API组织结构。
  • 日期时间:LocalDate, LocalTime, LocalDateTime
  • 年月日(枚举类):Year, YearMonth, MonthDay, Month, DayOfWeek
  • 时间间隔:Instant, Duration, Period
  • 时区:ZonedDateTime, ZoneId, TimeZone, ZoneOffest, OffsetTime, OffsetDateTime
  • 时间显示格式:parse, format, ofLocalizedDate, ofPattern方法
  • 时间调节器
  • util时间和time时间的相互转换

参考资料:

  • 黑马程序员:https://www.bilibili.com/video/BV1aZ4y1j78G
  • Java Core II

 

电路设计仿真软件:Mentor Graphics_(1).MentorGraphics电路设计仿真软件概述 菜单栏:包含文件、编辑、视图、工具等菜单。工具栏:提供常用的工具按钮,如打开、保存、仿真等。原理图编辑区:用于绘制电路原理图。元件库:包含各种电路元件,支持拖拽操作。属性面板:显示选中元件的属性,可以进行参数设置。仿真控制区:用于设置仿真参数和控制仿真过程。输出窗口:显示仿真结果和日志信息。打开模型编辑器:点击“工具”菜单,选择“模型编辑器”。选择模型类型:在模型编辑器中选择模型类型,如SPICE模型。输入模型参数:根据需要输入模型的参数,如电阻值、电容值等。保存模型。 阅读详情

相关推荐

FPGA领域四大顶级会议全景解读:从架构到应用的技术风向标

本文全景解读FPGA领域四大顶级会议(FPGA、FCCM、FPL、FPT),剖析其各自定位与技术风向。FPGA会议聚焦架构与工具创新,FCCM专攻硬件加速与定制计算,FPL覆盖从理论到应用的广泛领域,FPT则重点关注亚太市场与前沿应用。跟踪这些会议是把握FPGA技术演进、寻找创新灵感和应用方案的高效途径。

weixin_29274969的博客 335

Java的日期与时间之java.time.ZonedDateTime简介说明

Java的日期与时间之java.time.ZonedDateTime简介说明

qq_25073223的博客 1489

避坑指南:Ubuntu 22.04上源码编译Autoware.universe(Humble版)的完整流程与常见错误修复

本文详细介绍了在Ubuntu 22.04上源码编译Autoware.universe(Humble版)的完整流程与常见错误修复方法。从环境准备、依赖安装到编译优化,提供了实用的避坑指南和解决方案,帮助开发者高效完成安装并避免常见问题。特别针对源码安装过程中的疑难杂症给出了具体修复建议。

weixin_33712987的博客 382

ZonedDateTime类

ZonedDateTime类 我们之前在文章《听说你还在用Date类表示时间?》中提到过**“LocalDateTime无法与时间戳进行转换,因为LocalDateTime没有时区,无法确定某一时刻”**。其实LocalDateTime和ZonedDateTime很相似,区别只是LocalDateTime总是表示本地日期和时间,而ZonedDateTime要表示一个带时区的日期和时间。 我们可以简单地把ZonedDateTime理解成LocalDateTime加ZoneId。ZoneId是java.time

Window_mouse的博客 2万+

OpenCV图像拼接实战:用SIFT+透视变换打造无缝全景图(附完整代码)

本文详细介绍了使用OpenCV和SIFT算法实现图像拼接的全过程,包括特征匹配、透视变换和高级融合技术。通过实战代码演示,帮助开发者掌握无缝全景图生成的核心技术,适用于旅行摄影、无人机航拍等多种场景。

eee77的博客 997

Windows 10/11 安装 HYSPLIT 气象模型全攻略(附必备工具包下载清单)

本文提供了一份详尽的Windows 10/11系统下HYSPLIT气象模型安装与配置全攻略。指南涵盖了从核心认知、必备工具包(Tcl/Tk、ImageMagick)下载,到分步安装、环境变量设置及首次运行验证的完整流程,旨在帮助研究者和学生高效部署这一用于大气轨迹模拟与污染物扩散分析的专业工具。

weixin_28335283的博客 608

深入了解Java8新特性-日期时间API之ZonedDateTime类

ZonedDateTime是Java 8中引入的一个不可变且线程安全的数据类型,用于表示带有时区的日期和时间。与LocalDateTime相比,ZonedDateTime可以存储时区信息,并能够处理模糊的本地日期时间。ZonedDateTime可以表示从本地时间线LocalDateTime到即时时间线Instant之间的日期和时间。两个时间线之间的差异是UTC /格林威治的偏移量,由ZoneOffset表示。在两个时间线之间转换涉及使用从ZoneId访问的ZoneId计算偏移量。 ZonedDateTim

凡夫编程 4569

相机图像质量研究(22)常见问题总结:CMOS期间对成像的影响--光学串扰

光学串扰是一个比较难以理解的光学现象,实际影响往往不大。一、光学串扰产生的原因通常是入射角度太大,光线在不同通道之间产生了混叠二、光学串扰产生的现象光学串扰容易导致迷宫纹。总结本节讲了光学串扰产生的原因,现象。

xiaoshixiu的专栏 1573

【Java 基础篇】Java 日期类详解

本文介绍了 Java 日期类的概念、用法和常见操作。我们了解了Date类及其问题,并介绍了 Java 8 中引入的java.time包,其中包括LocalDateLocalTime和等类,用于处理日期、时间、时区等相关操作。此外,我们还介绍了如何使用类进行日期和时间的格式化和解析操作。通过合理地使用日期类和相关操作,我们可以更加方便地处理和操作日期、时间和时区信息。希望本文对你理解和使用 Java 日期类有所帮助。如果你对日期类还有更多疑问,可以查阅 Java 官方文档或参考相关书籍进行深入学习。

繁依Fanyi的博客 3887

ESP32学习笔记03-日志打印

日志分为5个等级。

Car12 1415

配置 SAP Web Dispatcher 的实战指南:打通 SAP Fiori、SAP Gateway 与前端系统的关键一跳

SAP Web Dispatcher 在 Fiori 架构中扮演关键角色,作为统一入口处理 HTTPS 请求、实现安全代理和流量分发。它将分散在不同系统的访问路径统一收口,解决浏览器同源策略限制,集中管理 HTTPS 终止和客户端信息传递。典型配置中,Web Dispatcher 监听 443 端口,根据路径将 OData 请求转发至 Gateway 系统,静态资源请求送至前端服务器。SSL 相关配置(如 PSE 文件)确保安全通信,而路由规则(wdisp/system_xx)决定请求转发目标。实施时需注意

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 102

【Java基础5】面向对象(下)日期类 抽象类与抽象方法

面向对象(下)日期类 概念题 1.面向对象的三大特性是什么?请分别梳理它们的知识点。 封装、继承、多态 封装: 1、提高程序的安全性、保护数据 2、隐藏代码的实现细节 3、统一接口 4、系统的可维护性增加了 get 获得这个数据 set 给这个数据设置值 ————————快捷键:alt + insert 继承: public class A extends B 重写:需要有继承关系,子类重写父类的方法! 重写只和非

低调的骏马 746

【异常】Hermes Agent调用z.ai接口失败(余额不足)API call failed (attempt 1/3): RateLimitError [HTTP 429]

补充说明:同步尝试解析接口对应网页时,出现“网页解析失败,可能是不支持的网页类型,请检查网页或稍后重试”提示,该提示不影响核心报错排查,仅作为辅助信息。

奶爸的编程之路,也就一周冷个三天 1194

6 日期字符串转日期_Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类...

  因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API。Stephen向JCP提交了一个规范,他本人作为规范的领导人,该规范就是JSR 310,在Java8中实现并发布。1.Java8日期、时间API包介绍java.time包:这是新的Java日期/时间API的基础包,所有的主要...

weixin_39614637的博客 87

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

java6 发布时间_Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类

因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API。Stephen向JCP提交了一个规范,他本人作为规范的领导人,该规范就是JSR 310,在Java8中实现并发布。1.Java8日期、时间API包介绍java.time包:这是新的Java日期/时间API的基础包,所有的主要基础...

weixin_35249165的博客 212

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

java 包结构 枚举类_Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类...

  因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API。Stephen向JCP提交了一个规范,他本人作为规范的领导人,该规范就是JSR 310,在Java8中实现并发布。1.Java8日期、时间API包介绍java.time包:这是新的Java日期/时间API的基础包,所有的主要...

weixin_39887183的博客 109

java8 time包获取指定日期时间

我们都知道,java8新增的time包中使用 LocalDateTime.of() 方法能方便的生成指定时间。 但是有时候需要获取生活中的一些指定日期时间,如获取固定的每月几日或者每周周几,这样的场景;of()方法就捉襟见肘了。 不要着急,LocalDateTime还提供了一个 with() 方法,能够方便的达到以上目的。 先看举例: 需求:获取当前周四日期和当月6号日期 public static void main(String[] args) { DateTimeFormatter

qq_36599564的博客 2144

Java中日期时间如何表示?Java.util.Date类和Java8引入新的Java.time包有何区别?

​ 早期,用来处理日期和时间的类。但是在,它提供了更强大、更易用的日期和时间处理功能。我们先从Date类开始学习起,要想使用Date类下的方法,那么我们就需要初始化Date对象.

Stevedash的博客 302

2.Java中关于日期时间API的使用整合 - java.time包

如果要用到关于日期时间API的话,这些文章应该能解决部分使用问题了。 单纯想到汉斯季默作曲的Time了,然后封面就搞了这个(乐

codeLearnerEternally的博客 1365

Java 时间处理:轻松掌握 java.time 包

在 Java 开发中,日期和时间处理一直是令人头疼的问题。传统的 `Date`​ 和 `Calendar`​ 类不仅复杂,还充满了线程安全和时区处理的坑。Java 8 引入的 `java.time`​ 包彻底改变了这一局面,带来了现代化、直观且功能强大的日期时间 API。

qq_17153885的博客 1415

Java 通俗讲解日期时间类【java.util包以及java.time包】

文章目录Date类构造器:DateFormat类构造方法:格式规则常用方法format方法parse方法Calendar类获取方式常用方法get/set方法add方法getTime方法 Date类 java.util.Date类,表示特定的瞬间,精确到毫秒 构造器: public Date():分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)。 public Date(long date):分配Date对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即1970年

十一仓 1513

Java 日期时间——《跟老吕学Java》

Java的日期时间API经历了从和到java.time包的演进,提供了更加直观、易用、灵活的日期时间处理方式。在Java 8及以后的版本中,你应该优先使用java.time包中的类来处理日期和时间。这些类不仅功能强大,而且设计良好,易于使用和理解。无论是获取当前日期时间、创建指定日期时间、进行日期时间的加减和比较,还是处理时区和格式化日期时间,java.time包都能提供你所需的所有功能。

Python老吕的博客 972

时间日期类JAVA包含地区属性_Java日期时间API系列16-----Jdk8中java.time包中的新的日期时间API类,java日期计算3,日期中年月日时分秒的属性值修改等...

通过Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析,可以看出java8设计非常好,实现接口Temporal, TemporalAdjuster, ChronoLocalDate等,有非常丰富的方法。例如:LocalDateTime:的部分方法: 包含了年月日,时分秒的属性值修改。Date中如果要进行属性值修改,必须使用Ca...

weixin_39714565的博客 116

Java8 日期时间

Java8 日期时间Java8 日期时间历史问题类Java日期/时间API包参考 Java8 日期时间 历史问题 类 类名 定义 说明 LocalDate 日期 只提供了简单的日期,并不含当天的时间信息 LocalTime 时间 只提供了简单的时间,并不含当天的日期信息 LocalDateTime 日期时间 提供日期和时间,不包含时区 Instant 时间戳 表示一个日...

DamonM的专栏 321

Java 8 日期时间 API

Java 8 日期时间 API

qq_25073223的博客 235

java.time包时间类浅谈

Java 17在时间处理方面没有引入全新的接口,但它通过优化现有类、改进编译器和垃圾收集器等方式,为时间处理提供了更好的性能和易用性。开发者可以继续使用Java 8及后续版本中引入的java.time包中的类来处理日期和时间。

代数的博客 1373

JAVA - java.time 包的常用日期时间类LocalDateTime LocalDate LocalTime 代码示例

第一代日期类 Date 第二点Calendar 缺少相应日期格式化、对象是可变的、有偏移量不好理解 第三代LocalDateTime LocalDate LocalTime import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; public class LocalDateDemo01 { public sta..

xdkiller的专栏 549
上一篇: 【Java】基于util包的日期时间
下一篇: 【Git】Git是目前世界上最先进的分布式版本控制系统(没有之一)
ALGO阿狗
博客等级 码龄9年 64粉丝 149原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值