jdk8-时间API

黑马程序员 jdk8时间api学习笔记

概述:java.time

在这里插入图片描述



1. DateTimeAPi使用

常用类概述

  • Instant: 时间线上的瞬时点用于在应用程序中记录事件时间戳。

    • 老版本的Date需要通过该类来转换至新版本的日期。

  • Duration: 以秒和纳秒为单位的时间间隔。具有很高的精确性。

  • Period: 以年、月和日为单位为单位的时间间隔。

  • LocalDate:表示一个日期,通常被视为年-月-日,不包含时间。

  • LocalTime: 表示时间,通常被视为小时-分钟-秒.

  • LocalDateTime: LocalDate + LocalTime

  • ZonedDateTime: LocalDateTime +时区

    • 时区如asia/shanghai

now()

实现code
@Test
public void test_now(){
    Instant instant =  Instant.now();
    LocalDate localDate = LocalDate.now();
    LocalTime localTime = LocalTime.now();
    LocalDateTime localDateTime = LocalDateTime.now();
    ZonedDateTime zonedDateTime = ZonedDateTime.now();

    System.out.println(instant);
    System.out.println(localDate);
    System.out.println(localTime);
    System.out.println(localDateTime);
    System.out.println(zonedDateTime);
}
执行结果
2022-01-13T07:46:08.108Z
2022-01-13
15:46:08.161
2022-01-13T15:46:08.161
2022-01-13T15:46:08.162+08:00[Asia/Shanghai]

Instant.now()的结果是UTC时间,与LocalDateTime相差8个小时。

of()

API
//LocalDate
public static LocalDate of(int year, Month month, int dayOfMonth);
public static LocalDate of(int year, int month, int dayOfMonth);


//LocalTime
public static LocalTime of(int hour, int minute);
public static LocalTime of(int hour, int minute, int second) ;
public static LocalTime of(int hour, int minute, int second, int nanoOfSecond);

//LocalDateTime
//month 可以接收Month,也可以接收int 表示月份数值,从1开始(略)
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute);
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second)
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond);
public static LocalDateTime of(LocalDate date, LocalTime time)

时区

ZoneId
@Test
public void test_zoneId(){
    Set<String> zoneIdSet = ZoneId.getAvailableZoneIds();
    System.out.println(zoneIdSet.size());  //600多个时区

    System.out.println(ZoneId.systemDefault()); // Asia/Shanghai
}
ZonedDateTime
@Test
public void test_set_zoneId(){
    LocalDateTime localDateTime = LocalDateTime.of(2008,8,8,20,0,0);
    System.out.println(localDateTime);
	
    //LocalDateTime添加时区信息--- 上海市  +8区
    ZonedDateTime zonedDateTime1 = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
    System.out.println(zonedDateTime1);

    //同一UTC时刻,东京时间 --- 东京是+9区,所以比上海早1个小时
    ZonedDateTime zonedDateTime2 = zonedDateTime1.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
    System.out.println(zonedDateTime2);
}

执行结果

2008-08-08T20:00
2008-08-08T20:00+08:00[Asia/Shanghai]
2008-08-08T21:00+09:00[Asia/Tokyo]

Month枚举

API
public enum Month implements TemporalAccessor, TemporalAdjuster {
    JANUARY,FEBRUARY,MARCH,
    APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMBER,OCTOBER,NOVEMBER, DECEMBER;
}
应用
@Test
public void test_month(){
    LocalDate localDate = LocalDate.of(2008,Month.AUGUST,8);
    System.out.println(localDate);

    Month month = Month.of(8);
    localDate = LocalDate.of(2008,month,8);
    System.out.println(localDate);
}

执行结果

2008-08-08
2008-08-08

综合练习1

/**
     * 1. 创建当前时间 不带时区
     * 2. 创建当前时间,不包含年月日
     * 3. 创建当前时间 带时区
     * 4. 创建 2021-01-13 12:34:56 月份用枚举
     * 5. 创建 2021-01-13  月份用枚举
     * 6. 创建时间 12:34:56
     */
public  void test_01_all(){
    LocalDateTime now = LocalDateTime.now();
    LocalDate date = LocalDate.now();
    ZonedDateTime zonedDateTime = ZonedDateTime.now();
    LocalDateTime localDateTime = LocalDateTime.of(2021, Month.JANUARY, 13, 12, 34, 56);
    LocalDate localDate = LocalDate.of(2021, Month.JANUARY,13);
    LocalTime localTime = LocalTime.of(12, 34, 56);
}


2. 根据现有实例创建日期和时间对象

修改某个时间或日期该如何操作?

plus() + minus()

minus内部调用plus(-amountToAdd)。不再赘述。

API
//LocalDate
public LocalDate plus(TemporalAmount amountToAdd)
public LocalDate plus(long amountToAdd, TemporalUnit unit)
 
public LocalDate plusYears(long yearsToAdd)
public LocalDate plusMonths(long monthsToAdd)
public LocalDate plusWeeks(long weeksToAdd)
public LocalDate plusDays(long daysToAdd)
    
//LocalTime
public LocalTime plus(TemporalAmount amountToAdd)
public LocalTime plus(long amountToAdd, TemporalUnit unit)
public LocalTime plusHours(long hoursToAdd) 
public LocalTime plusMinutes(long minutesToAdd)
public LocalTime plusSeconds(long secondstoAdd)
public LocalTime plusNanos(long nanosToAdd) 
例: LocalDate
@Test
public void test_plus_day(){
    LocalDate now = LocalDate.now();
    //当前时间 4天后的时间
    LocalDate newDate =  now.plus(4, ChronoUnit.DAYS);
    System.out.println(newDate);

    //当前时间3周后时间
    newDate =  now.plus(Period.ofWeeks(3));
    System.out.println(newDate);

    //当前时间5个月后时间
    newDate =  now.plusMonths(5);
    System.out.println(newDate);


    //当前时间2年后的时间
    newDate =  now.plusYears(2);
    System.out.println(newDate);
}
例: LocalTime
@Test
public void test_plus_time(){
    LocalTime now = LocalTime.now();
    //当前时间 500ns 后
    LocalTime newTime =  now.plus(4, ChronoUnit.NANOS);
    System.out.println(newTime);

    //当前时间 45s后
    newTime =  now.plus(Duration.ofSeconds(45));
    System.out.println(newTime);

    //当前时间 19min 后
    newTime =  now.plusMinutes(19);
    System.out.println(newTime);


    //当前时间 7h 后
    newTime =  now.plusHours(7);
    System.out.println(newTime);
}
TemporalAmount

张某查看自己的车辆保险还有2年3个月8天就过期了,计算到期的时间该如何处理?

@Test
public void test_plus_x(){
    LocalDateTime localDateTime = LocalDateTime.now();
    LocalDateTime newTime = localDateTime.plusYears(2).plusMonths(3).plusDays(8);
    System.out.println(newTime);
}
TemporalAmount类图

在这里插入图片描述

Period 和 Duration都是TemporalAmount的实现, 表示一段时间。

例:TemporalAmount
    /**
     * 张某查看自己的车辆保险还有2年3个月8天就过期了,计算到期的时间该如何处理?
     */
    @Test
    public void test_plus_x(){
        LocalDateTime newTime2 = localDateTime.plus(Period.of(2, 3, 8));
        System.out.println(newTime2);
    }
TemporalUnit
TemporalUnit类图

在这里插入图片描述

ChronoUnit

ChronoUnit是TemporalUnit的具体实现, 是一个枚举类, 有如下枚举类型。
在这里插入图片描述

例:TemporalUnit
    @Test
    public void test_plus_y(){
        //结婚十年称之为锡婚,2020年1月3日14时0分0秒,具有特殊意义,很多年轻人愿意在那天结婚,如果那天结婚了,他们的锡婚在什么时候?
        LocalDateTime localDateTime = LocalDateTime.of(2020,Month.FEBRUARY,3,14,0,0);
        LocalDateTime localDateTime2 = localDateTime.plus(1, ChronoUnit.DECADES);
        System.out.println(localDateTime2);

        // 结婚后半天,需要请亲戚吃饭, 吃饭后的时间是:
        LocalDateTime localDateTime3 = localDateTime2.plus(1, ChronoUnit.HALF_DAYS);
        System.out.println(localDateTime3);
    }

with()

不需要对日期进行加减计算, 而是直接指定具体的值进行修改,可以用with方法。

API
//LocalDateTime
public LocalDateTime withYear(int year)
public LocalDateTime withMonth(int month)
public LocalDateTime withDayOfMonth(int dayOfMonth) 
public LocalDateTime withDayOfYear(int dayOfYear)
public LocalDateTime withHour(int hour) 
public LocalDateTime withMinute(int minute) 
public LocalDateTime withSecond(int second)
public LocalDateTime withNano(int nanoOfSecond)
    
public LocalDateTime with(TemporalAdjuster adjuster) 
public LocalDateTime with(TemporalField field, long newValue)
例:
    @Test
    public void test_with_1(){
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime localDateTime1 = localDateTime.withDayOfMonth(1);
        //当月的第一天
        System.out.println(localDateTime1);

        //当日 凌晨1点,同一时刻 
        localDateTime1 = localDateTime.withHour(1);
        System.out.println(localDateTime1);
    }
TemporalField
类图

在这里插入图片描述

ChronoField

它是一个枚举类, 实现了TemporalField接口。

在这里插入图片描述

例:TemporalField
    @Test
    public void test_with_y(){
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime localDateTime1 = localDateTime.with(ChronoField.DAY_OF_MONTH, 1);
        //当月的第一天
        System.out.println(localDateTime1);
    }
with综合练习
    /**
     * 使用3中方式 计算2019年7月19日14时38分34秒后的 3年7个月18天后是什么时候?
     */
    @Test
    public void test_with_all(){
        LocalDateTime startTime = LocalDateTime.of(LocalDate.of(2019, 7, 19), LocalTime.of(14, 38, 34));
        System.out.println(startTime);

        LocalDateTime localDateTime1 = startTime.plus(Period.of(3, 7, 18));
        System.out.println(localDateTime1); // 2023-03-09T14:38:34

        localDateTime1 = startTime.withYear(2019 + 3).plusMonths( 7).plusDays( 18);
        System.out.println(localDateTime1);
    }

3. 调节器TemporalAdjuster与查询TemporalQuery

TemporalAdjuster

在做一些复杂的操作, 比如将日期调整到下周日,下一个工作日,或者本月中的某一天,这个时候需要用调节器TemporalAdjuster来更方便处理日期。

接口定义

TemporalAdjuster是一个函数式接口。

@FunctionalInterface
public interface TemporalAdjuster {
    //Temporal 是所有日期类的 父接口。
    Temporal adjustInto(Temporal temporal);
}
TemporalAdjusters工具类

jdk提供了一个TemporalAdjusters工具类, 定义常用的调节器。

    @Test
    public void test_adjusters_01(){
        LocalDate now = LocalDate.now();
        //当月的第一天
        LocalDate day = now.with(TemporalAdjusters.firstDayOfMonth());
        System.out.println(day);

        //下个月的第一天
        day = now.with(TemporalAdjusters.firstDayOfNextMonth());
        System.out.println(day);

        //下一年的第一天
        day = now.with(TemporalAdjusters.firstDayOfNextYear());
        System.out.println(day);

        //本年的第一天
        day = now.with(TemporalAdjusters.firstDayOfYear());
        System.out.println(day);

        // 本月的最后一天
        day = now.with(TemporalAdjusters.lastDayOfMonth());
        System.out.println(day);

        // 本年的最后一天
        day = now.with(TemporalAdjusters.lastDayOfYear());
        System.out.println(day);
    }
DayOfWeek使用
    @Test
    public void test_adjusters_02(){
        LocalDate now = LocalDate.now();

        //下一个周日
        LocalDate day = now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
        System.out.println(day);

        //上一个周三
         day = now.with(TemporalAdjusters.previous(DayOfWeek.WEDNESDAY));
        System.out.println(day);
    }
自定义TemporalAdjuster
 /**
     * 每个月5号发工资,如果5号是周末,则调整至前一个周五发。
     */
    class PayDayTemporalAdjuster implements TemporalAdjuster{
        @Override
        public Temporal adjustInto(Temporal temporal) {
            //1. 转换为日期对象
            LocalDate payDay = LocalDate.from(temporal);

            //2. 判断日期是否为5号,如果不是则将日期改为15号
            LocalDate realPayDay = payDay;
            if(payDay.getDayOfMonth() != 5) {
                realPayDay =  payDay.withDayOfMonth(5);
            }

            //3. 如果是周末,则修改至上一个周五
            if(realPayDay.getDayOfWeek() == DayOfWeek.SATURDAY ||  realPayDay.getDayOfWeek() == DayOfWeek.SUNDAY){
                realPayDay = realPayDay.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
            }

            return realPayDay;
        }
    }
综合练习
  @Test
    public void test_adjusters_03(){
        LocalDate now = LocalDate.now();
        System.out.println(now); //2022-01-15
        LocalDate realPayDay = LocalDate.from(new PayDayTemporalAdjuster().adjustInto(now));

        System.out.println(realPayDay); // 2022-01-05

    }

TemporalQuery

如果要计算 距离某一个特定日期chauffeur多少天,可以用TemporalQuery来实现。

接口定义
@FunctionalInterface
public interface TemporalQuery<R> {
    // LocalDate implements Temporal ;
    //Temporal extendsTemporalQuery
    R queryFrom(TemporalAccessor temporal);
}
距离下一个劳动节还有多少天
自定义TemporalQuery
    class LaborDayQueryImpl implements TemporalQuery<Long> {
        @Override
        public Long queryFrom(TemporalAccessor temporal) {
            LocalDate localDate = LocalDate.from(temporal);
            LocalDate laborDay = LocalDate.from(temporal).withMonth(5).withDayOfMonth(1); //当年的劳动节

            //若当前日期超过 5.1, 则将年份+1
            if (localDate.isAfter(laborDay)) {
                laborDay = laborDay.plusYears(1);
            }
            long days = ChronoUnit.DAYS.between(localDate, laborDay);
            return days;
        }
    }
例:
    @Test
    public void test_query_01() {
        LocalDate now = LocalDate.now();
        long days = now.query(new LaborDayQueryImpl());
        System.out.println(now +"距离下一个劳动节还有" +days);

        now = now.withMonth(5);
        days = now.query(new LaborDayQueryImpl());
        System.out.println(now +"距离下一个劳动节还有" +days);

    }

打印结果

2022-01-15距离下一个劳动节还有106
2022-05-15距离下一个劳动节还有351
综合练习
  /**
     * 计算距离下一个 圣诞节/儿童节/劳动节各相差多少天
     */
    class ThreeQueryImpl implements TemporalQuery<Long[]> {

        @Override
        public Long[] queryFrom(TemporalAccessor temporal) {
            LocalDate date = LocalDate.from(temporal);
            // 计算当前的 圣诞,儿童,劳动节
            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);

            if(date.isAfter(d1)){
                d1 = d1.plusYears(1);
                d2 = d2.plusYears(1);
                d3 = d3.plusYears(1);
            }else if(date.isAfter(d2)){
                d2 = d2.plusYears(1);
                d3 = d3.plusYears(1);
            }else if(date.isAfter(d3)){
                d3 = d3.plusYears(1);
            }

            return new Long[]{ChronoUnit.DAYS.between(date, d1),ChronoUnit.DAYS.between(date, d2),ChronoUnit.DAYS.between(date, d3)};
        }
    }

    @Test
    public void test_query_02() {
        LocalDate now = LocalDate.now();
        Long[] days = now.query(new ThreeQueryImpl());

        System.out.println("距离圣诞节:"+days[0]);
        System.out.println("距离儿童节:"+days[1]);
        System.out.println("距离劳动节:"+days[2]);
    }


4. java.util.Date与java.time.LocalDate的转换

对于老项目的改造,需要将Date或者Calendar转换为LocalDate.

通过Instant类转换

    @Test
    public void test_convert_01() {
        Date d = new Date();

        //1. 将Date转换为Instant对象
       Instant i = d.toInstant();

       //2. 添加时区信息
        ZonedDateTime zonedDateTime =  i.atZone(ZoneId.systemDefault());

        //3.转换
        LocalDate localDate = zonedDateTime.toLocalDate();

        System.out.println("before:"+ d);
        System.out.println("after:"+ localDate);
    }

执行效果

before:Sat Jan 15 14:11:24 CST 2022
after:2022-01-15

java.sql.Date与java.sql.TimeStamp

java.sql.Date
    @Test
    public void test_sqldate_01() {
        //构造java.sql.Date
        java.sql.Date d = new java.sql.Date(System.currentTimeMillis());

        //直接转换
        LocalDate localDate = d.toLocalDate();
        System.out.println("before:"+ d);
        System.out.println("after:"+ localDate);
    }
java.sql.TimeStamp
    @Test
    public void test_timestamp_01() {
        java.sql.Timestamp t = new java.sql.Timestamp(System.currentTimeMillis());

        LocalDateTime localDate = t.toLocalDateTime();
        System.out.println("before:"+ t);
        System.out.println("after:"+ localDate);
    }
另一种转换方式
    @Test
    public void test_xx_01() {
        Date d = new Date();
        //1. 转换为 java.sql.Date
        java.sql.Date d2 = new java.sql.Date(d.getTime());
        System.out.println(d);
        System.out.println(d2);
        
        //2. java.sql.Date 转换
        LocalDate localDate = d2.toLocalDate();
        System.out.println(localDate);
    }

java.util.Calendar转换

Calendar转换为LocalDateTime1
    @Test
    public void test_calendar_02() {
        //1.初始化calendar
        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar.getTime());

        //2. 获取时区
        TimeZone timeZone = calendar.getTimeZone();
        ZoneId zoneId = timeZone.toZoneId();

        //3.转换
        Instant instant = calendar.toInstant();
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, zoneId);

        System.out.println(zonedDateTime);

        LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
        System.out.println(localDateTime);
    }
Calendar转换为LocalDateTime2
    @Test
    public void test_calendar_02() {
        //1.初始化calendar
        Calendar calendar = Calendar.getInstance();
        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);

        //calendar  month 从0开始.这里需要+1
        LocalDateTime localDateTime = LocalDateTime.of(year, month+1, day, hour, minute, second);
        System.out.println(localDateTime);
    }

5.日期的解析与格式化:DateTimeFormatter

parse+format

    @Test
    public void test01(){
        LocalDateTime now = LocalDateTime.now();
        //date -> str
        String s1 = now.format(DateTimeFormatter.ISO_DATE_TIME);
        String s2 = now.format(DateTimeFormatter.ISO_TIME);

        System.out.println(s1);
        System.out.println(s2);

        //str  -> date
        LocalDateTime t1 = LocalDateTime.parse(s1,DateTimeFormatter.ISO_DATE_TIME);
        System.out.println(t1);
    }

ofLocalizedDate()

    @Test
    public void test02() {
        LocalDateTime now = LocalDateTime.now();

        //ofLocalizedDate
        String s1 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL));
        String s2 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG));
        String s3 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
        String s4 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT));

        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);
    }

打印结果

2022年1月15日 星期六
2022年1月15日
2022-1-15
22-1-15

自定义格式化器

    @Test
    public void test03() {
        LocalDateTime now = LocalDateTime.now();
        String s1 = now.format(DateTimeFormatter.ofPattern("yyyy年/MM月/dd日 --- HH:mm分:ss秒:SSS"));
        System.out.println(s1);
    }

执行结果

2022年/01月/15日 --- 14:38分:02秒:452


其他

多知道一点GMT,UTC

https://zhuanlan.zhihu.com/p/135951778

什么是GMT

GMT(Greenwich Mean Time), 格林威治平时(也称格林威治时间)。它规定太阳每天经过位于英国伦敦郊区的皇家格林威治天文台的时间为中午12点。

1884年10月在美国华盛顿召开了一个国际子午线会议,该会议将格林威治子午线设定为本初子午线,并将格林威治平时 (GMT, Greenwich Mean Time) 作为世界时间标准(UT, Universal Time)。由此也确定了全球24小时自然时区的划分,所有时区都以和 GMT 之间的偏移量做为参考。

什么是UTC

UTC(Coodinated Universal Time),协调世界时,又称世界统一时间、世界标准时间、国际协调时间。

UTC 是现在全球通用的时间标准,全球各地都同意将各自的时间进行同步协调。UTC 时间是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以秒为单位的国际原子时所综合精算而成。

在军事中,协调世界时会使用“Z”来表示。又由于Z在无线电联络中使用“Zulu”作代称,协调世界时也会被称为"Zulu time"

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值