Java8时间与日期API(别再使用Date和Calendar了)

API设计原因

在Java面世之初,标准库中就引入了两种用于处理日期和时间的类,但是由于很多问题,很多方法都已经弃用,在3avaSE 8中引入java.time包解决了长久以来存在的诸多弊端,java.time包基于Joda-Time库构件,是一种免费的开源解决方法,多年来一直作为处理]ava日其期和时间的事实标准

Java原本自带的java.util.Date和java.util.calendar类
但是这两个类:

  1. 有线程不安全的风险
  2. 使用繁杂
  3. 官方废弃
  4. 设计烂

故Date类和Calendar早早就被废弃

时间日期常用类概述

  1. Instant类
    Instanit类对时间轴上的单一瞬时点建模,可以用于记录应用程序中的事件时间戳,在之后学习的类型转换中,均可以使用Instant类作为中间类完成转换.
  2. Duration类
    Duration类表示秒或纳秒时间间隔,适合处理较短的时间,需要更高的精确性
  3. Period类
    period类表示一段时间的年、月、日
  4. LocalDate类
    LocalDate是一个不可变的日期时间对象,表示日期,通常被视为年月日
  5. LocalTime类
    LocalTime是一个不可变的日期时间对象,代表一个时间,通常被看作是小时-秒,时间表示为纳秒精度
  6. LocalDateTime类
    LocalDateTime是一个不可变的日期时间对象,代表日期时间,通常被视为年-月-日-时-分-秒
  7. ZonedDateTime类
    ZonedDateTime类具有时区的日期时间的不可变表示,此类储存所有日期时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间
  8. Year类:表示年
  9. YearMonth类:表示年月
  10. MonthDay类:表示月日

创建方法(now)

上述所有类都是线程安全的,并且这些类不提供公共构造函数,即无法用new直接创建而是要使用工厂法实例化
例:

package demo;

import java.time.*;
import java.util.HashMap;

public class TimeDemo1 {
    public static void main(String[] args) {
        Instant now = Instant.now();
        LocalDateTime now1 = LocalDateTime.now();
        LocalTime now2 = LocalTime.now();
        LocalDate now3 = LocalDate.now();
        ZonedDateTime now4 = ZonedDateTime.now();
        Year now5 = Year.now();
        YearMonth now6 = YearMonth.now();
        MonthDay now7 = MonthDay.now();
        
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put(now.getClass().getName(),now.toString());
        hashMap.put(now1.getClass().getName(),now1.toString());
        hashMap.put(now2.getClass().getName(),now2.toString());
        hashMap.put(now3.getClass().getName(),now3.toString());
        hashMap.put(now4.getClass().getName(),now4.toString());
        hashMap.put(now5.getClass().getName(),now5.toString());
        hashMap.put(now6.getClass().getName(),now6.toString());
        hashMap.put(now7.getClass().getName(),now7.toString());

        hashMap.forEach((x,y)->{
           System.out.println(x+":"+y);
       });
    }
}

在这里插入图片描述

生成自定义的日期时间对象(of)

这里注意ZoneDateTime的of()方法最后传入的是一个ZoneId类的地区偏移量,写法如下:
ZonedDateTime.of(2022, 6, 5, 2, 16, 50,10,ZoneId.of(“+8”));

package demo;

import java.time.*;
import java.util.HashMap;

public class TimeDemo2 {
    public static void main(String[] args) {
        LocalDate of = LocalDate.of(2000, 10, 16);
        LocalTime of1 = LocalTime.of(5, 16, 10);
        LocalDateTime of2 = LocalDateTime.of(of, of1);
        Year of3 = Year.of(2018);
        Month of4 = Month.of(5);
        MonthDay of5 = MonthDay.of(8, 16);
        ZonedDateTime of6 = ZonedDateTime.of(2022, 6, 5, 2, 16, 50,10,ZoneId.of("+8"));

        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put(of.getClass().getName(),of.toString());
        hashMap.put(of1.getClass().getName(),of1.toString());
        hashMap.put(of2.getClass().getName(),of2.toString());
        hashMap.put(of3.getClass().getName(),of3.toString());
        hashMap.put(of4.getClass().getName(),of4.toString());
        hashMap.put(of5.getClass().getName(),of5.toString());
        hashMap.put(of6.getClass().getName(),of6.toString());

        hashMap.forEach((x,y)->{
            System.out.println(x+":"+y);
        });
    }
}

在这里插入图片描述

为LocalDateTime添加时区信息

其实就是我们上面提到的ZoneId!

两种简单常用的方法

  1. 使用of自定义时区
  2. 使用systemDefault()设置当前时区
package demo;

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

public class TimeDemo5 {
    public static void main(String[] args) {
        //设置时间
        LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 1, 0, 1, 1);
        //设置地区
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        System.out.println(zonedDateTime);
    }
}

ZoneId类

用于获取时区信息,其中的getAvailableZoneIds()方法可以获取600个可用时区

package demo;

import java.time.ZoneId;
import java.util.Set;

public class TimeDemo3 {
    public static void main(String[] args) {
        Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(System.out::println);
    }
}

在这里插入图片描述

获取系统时区
package demo;

import java.time.ZoneId;

public class TimeDemo4 {
    public static void main(String[] args) {
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId);
    }
}

在这里插入图片描述

获取其他时区的时间

package demo;

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

public class TimeDemo5 {
    public static void main(String[] args) {
        //设置时间
        LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 1, 0, 1, 1);
        //设置地区
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        System.out.println(zonedDateTime);
		//设置时区获取,也可以设置地点
        ZonedDateTime zonedDateTime1 = zonedDateTime.withZoneSameInstant(ZoneId.of("+9"));
        System.out.println(zonedDateTime1+""+zonedDateTime1.getZone());

    }
}

在这里插入图片描述

关于Month枚举

在初始化LocalDate和LocalDateTime对象时使用月份枚举传入,这样更不易出错!更简单!!

在这里插入图片描述

package demo;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;

public class TimeDemo6 {
    public static void main(String[] args) {
        LocalDate of = LocalDate.of(2020, Month.JANUARY, 15);
        System.out.println(of);
        //验证
        Month of1 = Month.of(8);
        System.out.println(of1);
    }
}

在这里插入图片描述

根据现有时间进行时间推断(plus,minus)

可选方法:(minus:- , plus: +)

  1. plusDays(1);
  2. plusMonths(1);
  3. plusWeeks(1);
  4. plusYears(1);
  5. plusNanos() : 在涉及纳秒级别的类中有
    当然minus也一样
package demo;

import java.time.LocalDate;
import java.time.Month;
import java.time.MonthDay;
import java.time.Year;

public class TimeDemo7 {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        LocalDate localDate = now.plusDays(10);
        LocalDate localDate1 = now.minusDays(6);
        System.out.println("今天:"+now);
        System.out.println("十天后:"+localDate);
        System.out.println("六天前:"+localDate1);
    }
}

在这里插入图片描述

采用period对plus方法设置自定义一段时间

如下:获取2年1个月16天后的时间

plus的另一个重载则是以ChronoUnit枚举方式对事件进行计算
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package demo;

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

public class TimeDemo8 {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        //采用period
        Period of = Period.of(2, 1, 16);
        LocalDate plus = now.plus(of);
        System.out.println(plus);
    }
}

在这里插入图片描述

直接修改日期(with)

对时间直接进行修改,其中with()类似plus()

其中with(TemporalAdjuster adjuster)下有多个实现类,如下:
在这里插入图片描述

package demo;

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

public class TimeDemo9 {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        LocalDate localDate = now.withDayOfMonth(16);
        LocalDate localDate1 = now.withMonth(5);
        LocalDate localDate2 = now.withYear(2021);
        LocalDate of = LocalDate.of(2000, 10, 13);
        LocalDate with = now.with(of);
        System.out.println(now);
        System.out.println(localDate);
        System.out.println(localDate1);
        System.out.println(localDate2);
        System.out.println(with);
    }
}


在这里插入图片描述

调节器

TemporalAdjusters实例

其中有很多方法如下:

  1. firstDayOfMonth():本月第一天
  2. lastDayOfMonth():本月最后一天
  3. firstDayOfNextMonth():下个月第一天
  4. firstDayOfYear():本年第一天
  5. lastDayOfYear():本年最后一天
  6. firstDayOfNextYear():下一年第一天
  7. firstInMonth(DayOfWeek dayOfWeek):第一个月的第N天
package demo;

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

public class TimeDemo10 {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        //本月最后一天
        LocalDate with = now.with(TemporalAdjusters.lastDayOfMonth());
        System.out.println(with);
    }
}

在这里插入图片描述

DayOfWeek

本类是个枚举,封装了周一到周日
那么在哪里可以用到呢?
其实就在上面的TemporalAdjusters中搭配previous和next方法使用

注意:这里previous虽然说是上周但是实际得出的是本周

package demo;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

public class TimeDemo11 {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        //上一个周1
        LocalDate with = now.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
        //下一个周五
        LocalDate with1 = now.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
        System.out.println(with);
        System.out.println(with1);
    }
}

在这里插入图片描述

自定义TemporalAdjuster调节器

从源码中看出,TemporalAdjuster是个函数式接口,仅有:

Temporal adjustInto(Temporal temporal);

由这个接口可以看出Temporal是所有日期时间类的总接口之一
并且我们可以使用from方法进行转换
在这里插入图片描述

需求: 获取当前日期,判断是否是周末,不是则输出工作日,是则休息日

package demo;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.MonthDay;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;

public class SelfDefineTimeAdjuster implements TemporalAdjuster {

    @Override
    public Temporal adjustInto(Temporal temporal) {
        //获取当前日期,判断是否是周末,不是则输出工作日,是则休息日
        LocalDate now = LocalDate.from(temporal);
//        LocalDate now = LocalDate.now();
        DayOfWeek from = DayOfWeek.from(now);
        if (from.getValue() <= 5) {
            System.out.println("工作日");
        } else {
            System.out.println("休息日");
        }
        return null;
    }

    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        SelfDefineTimeAdjuster self = new SelfDefineTimeAdjuster();
        self.adjustInto(now);

    }

}

在这里插入图片描述

日期查询TemporalQuery

TemporalQuery接口同样是个函数式接口,下设R queryFrom(TemporalAccessor temporal);方法

其中TemporalAccessor是Temporal的父接口在这里插入图片描述

实例

package demo;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQuery;

public class SelfTimeQuery implements TemporalQuery<Long> {
    @Override
    public Long queryFrom(TemporalAccessor temporal) {
        //查询国庆节是否到了,返回差值
        LocalDate now = LocalDate.from(temporal);
        LocalDate festival = LocalDate.of(now.getYear(), 10, 1);
        //使用ChronoUnit进行计算
        long between = ChronoUnit.DAYS.between(now, festival);
        return between;
    }

    public static void main(String[] args) {
        SelfTimeQuery selfTimeQuery = new SelfTimeQuery();
        LocalDate now = LocalDate.now();
        Long aLong = selfTimeQuery.queryFrom(now);
        System.out.println(aLong);
    }
}

在这里插入图片描述

时间转换

java.util.Date转LocalDate方法一

我们常使用Instant类和ZoneDateTime类帮助进行转换

package demo;

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

public class TimeDemo13 {
    public static void main(String[] args) {
        Date date = new Date();
        Instant instant = date.toInstant();
        //使用instant类中的atZone添加时区信息
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
        //通过ZoneDateTime的toLocalDate进行转化
        LocalDate localDate = zonedDateTime.toLocalDate();
        System.out.println(localDate.getClass().getName());
        System.out.println(localDate);
    }
}

在这里插入图片描述

java.util.Date转LocalDate方法二

第二种方法就是应用java.sql.Date类帮助 java.util.Date进行转化 ,应用getTime()方法直接转为毫秒值让sql.Date接收

java.sql.Date转换LocalDate

可以使用其自带的.toLocalDate()方法进行直接转换

package demo;

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

public class TimeDemo14 {
    public static void main(String[] args) {
        Date date = new Date(System.currentTimeMillis());
        LocalDate localDate = date.toLocalDate();
        System.out.println(localDate);
        System.out.println(localDate.getClass().getName());
    }
}

java.sql.Timestamp时间戳转换LocalDate

其实Timestamp无法直接转化LocalDate而是可以直接转化为LocalDateTime使用其toLocalDateTime()方法即可
借助LocalDateTime帮助进行再转化就可以转换为LocalDate

package demo;

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

public class TimeDemo15 {
    public static void main(String[] args) {
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        LocalDateTime localDateTime = timestamp.toLocalDateTime();
        LocalDate localDate = localDateTime.toLocalDate();
        System.out.println(localDate);
    }
}

在这里插入图片描述

Calendar转换ZonedDateTime

通过ZonedDateTime.ofInstant()方法进行转化
步骤:

  1. 获取时区
  2. 获取ZoneId
  3. 获取instant
  4. 传入ZoneId和instant到ofInstant()方法
package demo;

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

public class TimeDemo16 {


    public static void main(String[] args) {
        Calendar instance = Calendar.getInstance();
        //获取时区
        TimeZone timeZone = instance.getTimeZone();
        //获取ZoneId
        ZoneId zoneId = timeZone.toZoneId();
        //获取instant
        Instant instant = instance.toInstant();
        //转换
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, zoneId);
        System.out.println(zonedDateTime.getClass().getName());
        System.out.println(zonedDateTime);
    }
}

在这里插入图片描述

Calendar直接转化LocalDateTime

package demo;

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

public class TimeDemo17 {
    //注意month要加1
    public static void main(String[] args) {
        Calendar instance = Calendar.getInstance();
        int year = instance.get(Calendar.YEAR);
        int month = instance.get(Calendar.MONTH) + 1;
        int day = instance.get(Calendar.DAY_OF_MONTH);
        int hour = instance.get(Calendar.HOUR);
        int min = instance.get(Calendar.MINUTE);
        int sec = instance.get(Calendar.SECOND);
        LocalDateTime of = LocalDateTime.of(year, month, day, hour, min, sec);
        System.out.println(of);
    }
}

在这里插入图片描述

日期解析与格式化DateTimeFormatter

SimpleDateFormat类是线程不安全的,所以Java8出现了新的格式化类
DateTimeFormatter
并且其不需要创建转换器对象而是直接使用后parse和format方法

format格式化

package demo;

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

public class TimeDemo18 {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        String format = now.format(DateTimeFormatter.ISO_DATE);
        String format1 = now.format(DateTimeFormatter.ISO_DATE_TIME);
        String format2 = now.format(DateTimeFormatter.ISO_LOCAL_TIME);
        System.out.println(format);
        System.out.println(format1);
        System.out.println(format2);
    }
}

在这里插入图片描述

parse解析

package demo;

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

public class TimeDemo18 {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        String format = now.format(DateTimeFormatter.ISO_DATE);
        String format1 = now.format(DateTimeFormatter.ISO_DATE_TIME);
        String format2 = now.format(DateTimeFormatter.ISO_LOCAL_TIME);
        System.out.println(format);
        System.out.println(format1);
        System.out.println(format2);
        System.out.println("===================");
        LocalDateTime parse = LocalDateTime.parse(format1);
        LocalDate parse1 = LocalDate.parse(format);

        System.out.println(parse);
        System.out.println(parse1);
    }
}

在这里插入图片描述

ofLocalizedDate格式化时区常用显示格式

该方法DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)参数为FormatStyle枚举类包含四个属性:

  1. FULL
  2. LONG
  3. MEDIUM
  4. SHORT
    在这里插入图片描述

实例如下:

package demo;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.HashMap;

public class TimeDemo19 {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        String format = now.format(DateTimeFormatter.ISO_DATE);
        String format2 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
        String format1 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL));
        String format3 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG));
        String format4 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT));

        HashMap<String, String> data = new HashMap<>();
        data.put("FormatStyle.FULL",format1);
        data.put("FormatStyle.MEDIUM",format2);
        data.put("FormatStyle.LONG",format3);
        data.put("FormatStyle.SHORT",format4);
        System.out.println(format);
        data.forEach((x,y)->{
            System.out.println(x+":"+y);
        });

    }
}

在这里插入图片描述

自定义格式化

使用DateTimeFormatter.ofPattern方法进行自定义格式化方式

package demo;

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

public class SelfTimeFormat {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        //使用DateTimeFormatter.ofPattern方法进行自定义格式化方式
        String format = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd -> HH:mm:ss"));
        System.out.println(format);
    }
}

在这里插入图片描述

格式化参考表

格式化字符:

字母日期或时间元素类型
GEra 标识符Text
yYear
M年中的月份Month
w年中的周数Number
W月中的周数Number
D年中的天数Number
d月份中的天数Number
F月份中的星期Number
E星期中的天数Text
aAM,PM标记Text
H一天中的小时数(0~23)Number
hAM,PM中的小时数(1~12)Number
k一天中的小时数(1~24)Number
KAM,PM中的小时数 (0~11)Number
m小时中的分钟数Number
s分钟中的秒数Number
S毫秒数Number
z时区General time zone
Z时区RFC 822 time zone

常用时间格式:

日期时间对应的格式
2021/01/01yyyy/MM/dd
2021.01.01yyyy.MM.dd
2021-01-01 01:01:01yyyy-MM-dd HH:mm:ss
2021年01月01日 01时01分01秒 星期一yyyy年MM月dd日 HH时mm分ss秒 EEEE
下午3时ah时
今年已过去了1天今年已过去了D天
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值