JDK8 前后的 Date 日期时间 API

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

JDK8 前后的 Date 日期时间 API

在这里插入图片描述


每博一文案

师父说:人只要活在世界上就会有很多的烦恼痛苦或是快乐取决于逆的内心只要心里拥有温暖灿烂的阳光
那么悲伤又有什么好畏惧的呢?
人生如行路一路艰辛一路风景路上你会遇到很多艰难险阻也许你生活得并不富裕
也许你的工作股不够好也许你总是爱而不得但请你一定不要放弃。
这个世界上有温暖有感动有柔情只要用阳光的心态去面对生活你就能收获一个乐观积极的自己。
用微笑的力量感染周围的人照亮前进道路上位置的黑暗去努力成为他们人生路上的太阳。
世界的模样取决于你凝视它的目光就算再艰难困苦的生活
只要微笑着撑过去了就是胜利。
不要放弃拥抱阳光的权力也不要畏惧内心里的悲伤温暖一定会将冰冷融化光明与期许总是相伴而来。
                                  ——————    一禅心灵庙语

文章目录


在这里插入图片描述

在这里插入图片描述

1. JDK 8 之前: java.util.Date类

有两种表示时间的基本方法。

  • 人类时间:比如年、月、日、时、分和秒。
  • 机器时间:以时间线连续测量时间从一个称为时代的起点开始以纳秒为单位。

Date-Time 包提供了丰富的表示日期和时间的类。Date-Time API 中的某些类用于表示机器时间其他类更适合表示人类时间。

首先确定您需要的日期和时间的哪些方面然后选择满足这些需求的课程或课程。选择基于时间的课程时 首先要确定是否需要表示人类时间或机器时间。然后您可以确定需要表示的时间。你需要一个时区吗? 日期和时间?仅限日期?如果你需要一个日期你需要月日和年或者一个子集?

时间戳: 就是毫秒值某段时间到 1970年1月1日 0 时 0 分 0 秒 0毫秒 的毫秒值。

在这里插入图片描述

在这里插入图片描述


Date的构造器: 只有两个其他的都已经过时了不推荐使用了。

public Date();
public Date(long date);

在这里插入图片描述


举例: 需要注意的是Date有两个一个是 util包下的另一个是 sql数据库包下的这里我们导入的是 util下的。

import java.util.Date;

public class DateTest {
    public static void main(String[] args) {
        Date date = new Date();  // 默认获取的当前系统的时间
        System.out.println(date);

        Date date2 = new Date(0L);  // 设置毫秒值(long类型的)时间戳创建Date对象
        System.out.println(date2);  // 0L 时间戳:表示的是 1970年1月1日 0时0分0秒 0毫秒
    }

}

在这里插入图片描述

java.util.Date类中常用的方法

Date类中大多数的方法都是过时了不推荐使用了。

这里就只有一个比较常用还没有过时的方法

getTime() : 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。就是Date对象表示的时间到 1970 年 1 月 1 日 00:00:00 GMT 的毫秒值又称为 “时间戳”。

在这里插入图片描述

在这里插入图片描述

举例:

import java.util.Date;

public class DateTest {
    public static void main(String[] args) {
        Date date = new Date();  // 默认获取的当前系统的时间
        System.out.println(date);
        System.out.println(date.getTime());  // 获取到当前系统时间到1970年1月1日 0时0分0秒 0毫秒 的毫秒值

        Date date2 = new Date(0L);  // 设置毫秒值(long类型的)时间戳创建Date对象
        System.out.println(date2);  // 0L 时间戳:表示的是 1970年1月1日 0时0分0秒 0毫秒
        System.out.println(date2.getTime());

    }

}

在这里插入图片描述

举例: 需求: 打印时间原点开始一年之后的时间

import java.util.Date;

public class DateTest {
    public static void main(String[] args) {
        Date d2 = new Date(0L);  // 123 默认是 int 类型的,0L 时间戳:表示的是 1970年1月1日 0时0分0秒 0毫秒

        // 2. 获取到Date对象的时间戳(毫秒值)
        long time = d2.getTime();

        // 将这个毫秒值 + 一年的毫秒值
        time += 1000L * 60 * 60 * 24 * 365;   // 不要将 L long类型给忘记了不然类型就不对了。

        // 4. 通过该增加了一年的时间戳(毫秒值)
        d2.setTime(time);
        System.out.println(d2);
    }
}

在这里插入图片描述

1.1 java.sql.Date 类

java.sql.Date 是有关数据库的一个日期时间的类这里就不多介绍了这个不是我们的重点。

在这里插入图片描述

在这里插入图片描述

举例:

如何将包下的 java.util.Date 类型的日期时间 转换为 ————> java.sql.Date 包下的日期时间 ???

思路:

java.util.Date 包下的 与 java.sql.Date 包下 两者之间共同的参数是: 时间戳: 就是毫秒值某段时间到 1970年1月1日 0 时 0 分 0 秒 0毫秒 的毫秒值。 利用这一点。

创建 java.util.Date 包下的日期类型获取其中的时间戳 作为参数创建 java.sql.Date 包下的 日期时间。

public class DateTest {
    public static void main(String[] args) {
        java.sql.Date date = new java.sql.Date(new java.util.Date().getTime());
        // new java.util.Date().getTime() 获取到当前系统时间的时间戳:到 1970年1月1日 0 时 0 分 0 秒 0毫秒 的毫秒值。 
        System.out.println(date);

    }
}

在这里插入图片描述

错误演示:

public class DateTest {
    public static void main(String[] args) {
        java.util.Date utilDate = new java.util.Date();
        java.sql.Date sqlDate = new java.sql.Date(0L);

        // 报: java.lang.ClassCastException 类转换异常
        sqlDate = (java.sql.Date) utilDate;  // 报异常: 将一个不是多态(实例的)的父类对象强制转换为子类对象是报异常的
    }
}

在这里插入图片描述

将 父类 java.util.Date 强制转换为子类 java.sql.Date 会报类型转换异常,如果可以将父类类型 强制转换为子类类型(不是多态)的话那子类中该有的成员变量/方法都会没有的不合理.

可以将 java.sql.Date 转换为 —> java.util.Date 类因为 java.sql.Date 是 extends 继承了 java.util.Date 类的 多态

public class DateTest {
    public static void main(String[] args) {
        java.util.Date utilDate = new java.util.Date();
        java.sql.Date sqlDate = new java.sql.Date(0L);
        utilDate = sqlDate;
        System.out.println(utilDate);

        // 也可以一体化
        java.util.Date date = new java.sql.Date(0L);  // 注意参数是 long类型整数默认是 int 类型
        System.out.println(date);


    }
}

在这里插入图片描述

2. JDK 8 之前 : java.text.SimpleDateFormat类 (字符串<–>日期时间) 日期格式设定

Date类的API不易于国际化大部分被废弃了java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化解析日期的具体类。

  • 它允许进行格式化:日期类型 ——> String 字符串类型、解析:字符串类型 ——> 日期类型

在这里插入图片描述

SimpleDateFormat 构造器:

public SimpleDateFormat(); // 用默认的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。注:此构造方法可能不支持所有语言环境。要覆盖所有地区请使用 DateFormat 类中的工厂方法
public SimpleDateFormat(String pattern); // 用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。注:此构造方法可能不支持所有语言环境。要覆盖所有语言环境请使用 DateFormat 类中的工厂方法    

这里我们一般使用 public SimpleDateFormat(String pattern); 这个构造器创建 SimpDateFormat 对象其中的 pattern 参数表示 日期时间的格式(即是我们字符串表示日期时间的格式也是我们显示 Date 类型的格式这两者之间的格式必须一致不然会报异常。

如下是对应的格式

在这里插入图片描述

在这里插入图片描述

我们先来认识以下几个 格式和解析的方法

  • public StringBuffer format(Date date) 表示 将给定的 Date 格式化为日期/时间字符串并将结果添加到给定的 StringBuffer。StringBuffer 可以转换为 String 类型
  • public Date parse(String source) 表示解析字符串的文本生成 Date。注意会抛出 NullPointerException - 如果 source为 null。

举例: 格式化: 将给定 Date 转换为 ——> String 字符串类型

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

public class DateTest {
    public static void main(String[] args) {
        Date date = new Date();  // 默认是当前系统时间
        // 指定日期格式创建 SimpleDateFormat 对象
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd hh:mm:ss");
        // 将 Date 转换为 String 类型
        String str = simpleDateFormat.format(date);
        System.out.println(str);
        // 或者
        // 指定日期格式创建 SimpleDateFormat 对象
        SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("YYYY年MM月dd日 hh时mm分ss秒");
        // 将 Date 转换为 String 类型
        String str2 = simpleDateFormat2.format(date);
        System.out.println(str2);
    }
}

在这里插入图片描述


举例: 解析: 将String 类型 ——> Date 类型 :注意String 类型的格式要和创建SimpleDateFormat 对象的格式要一致不然包异常

public class DateTest {
    public static void main(String[] args) {
        String str = "2023-1-20 21:00:01";
        String str2 = "2023年1月20日 22时06分00秒";
        Date date = null;
        Date date2 = null;

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd hh:mm:ss");
        SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("YYYY年MM月dd日 hh时mm分ss秒");

        try {
            date = simpleDateFormat.parse(str);
            date2 = simpleDateFormat2.parse(str2);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        System.out.println(date);
        System.out.println(date2);


    }
}

在这里插入图片描述

**如果字符串日期的格式 与 SimpleDateFormat 设定的格式不一致报异常: **

在这里插入图片描述


3. JDK 8 之前 : java.util.Calendar(日历)

Calendar 是一个抽象类主用用于完成日期字段之间相互操作的功能。

在这里插入图片描述

在这里插入图片描述


** abstract 抽象类是无法 new 的所以如何创建对象 ???**

在这里插入图片描述

  • 使用 Calendar.getInstance() 静态方法抽象类中的静态方法不能被继承不能被重写仅仅只能其抽象类自己使用通过 类名.方法名() 直接调用。像不像单例模式。
    在这里插入图片描述

在这里插入图片描述

  • 调用它的子类 GregorianCalendar的构造器 多态性

在这里插入图片描述


Calendar 底层原理: 会根据系统的不同时区来获取不同的日历对象默认表示当前系统时间。

在这里插入图片描述

其中会把时间中的 纪元年月日时分秒星期 等等的都放到一个数组当中。

细节:

  • 月份:范围: 0~11 如果获取出来的 0 那么实际上就是我们中国的 1 月。
  • 星期:在老外的眼里:星期日是一周中的第 1 天1(星期日)2(星期一)3(星期二)4(星期三)5(星期四)6(星期五)7(星期六)

常用的方法如下:

  • public int get(int field)

在这里插入图片描述

通过对应的常量获取到对应的数组下标中记录的信息

在这里插入图片描述

举例:

import java.util.Calendar;

public class CalendarTest {
    public static void main(String[] args) {
        // 调用 Calendar.getInstance() 类方法(静态方法)/创建 Calendar 对象
        Calendar calendar = Calendar.getInstance();  // 默认是当前系统的时间
        int month = calendar.get(Calendar.MONTH);  // 获取到Calendar 对象中的月份
        int year = calendar.get(Calendar.YEAR);   // 获取到Calendar 对象中的年
        int date = calendar.get(Calendar.DATE);   // 获取到Calendar 对象中的天数

        System.out.println(month);
        System.out.println(year);
        System.out.println(date);

    }
}

在这里插入图片描述

  • public void set(int field, int value) 表示修改 Calendar 对象中的日历中的某个字段信息如:年月日

在这里插入图片描述

  • public abstract void add(int field, int amount) 表示:根据日历的规则为给定的日历字段添加或减去指定的时间量。如:年月日

在这里插入图片描述

举例:

import java.util.Calendar;

public class CalendarTest {
    public static void main(String[] args) {
        // Calendar.getInstance() 类方法(静态方法)/创建 Calendar 对象
        Calendar calendar = Calendar.getInstance();  // 默认是当前系统的时间。
        System.out.println(calendar);
        System.out.println(calendar.get(Calendar.YEAR));  // 获取 Calendar 对象的年份
        calendar.set(Calendar.YEAR, 2000);  // 修改 Calendar 对象的年份
        System.out.println(calendar.get(Calendar.YEAR));
        calendar.add(Calendar.YEAR, 1);     // 添加 1 年
        System.out.println(calendar.get(Calendar.YEAR));  // 获取Calendar 对象的年份
        calendar.add(Calendar.YEAR, -2);    // 减少 2 年
        System.out.println(calendar.get(Calendar.YEAR));  // 获取Calendar 对象的年份

    }
}

在这里插入图片描述

4. JDK 8 中的 :LocalDate、LocalTime、LocalDateTime

日期时间在计算机实际记录的是一个毫秒值 :long 类型的时间戳 仅仅只是适用于计算机解读。

但是却不利于人类阅读。

就比如: 如果我们跟别人说:“我们在88988902399323”见面别晚了了那么就很难让人明白了。

我们希望时昼夜和四季有关这样就利于我们人类自身阅读了但是这样事情就变的复杂了因为: JDK1.0 中包含了一个 java.util.Date 类但是它的大多数方法已经在JDK 1.1 引入了 Caledar 类之后被弃用了。而 Calendar 并不比 Date 好多少。

它们面临的问题是:

JDK8之前的 与 JDK8之后的区别

  • **可变性:**像日期和时间这样的类应该是不可变的
  • **偏移性:**Date 中的年份是从 1970 开始的而月份也是老外的 0 开始
  • 格式化: 只对Date 有用Calendar 则不行此外它们也不是线程安全的不能处理闰秒

第三次引入的API是成功的并且 Java 8中引入的 java.time API 已经纠正了过去的缺陷将来很长一段时间内它都会为我们服务。

Java 8 吸收了 Joda-Time 的精华以一个新的开始为 Java 创建优秀的 API。 新的java.time中包含了所有关于本地日期(LocalDate、本地时间(LocalTime、本地日期时间(LocalDateTime、时区(ZonedDateTime

和持续时间(Duration的类。历史悠久的 Date 类新增了 toInstant() 方法 用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简 化了日期时间和本地化的管理。

新时间日期API

java.time – 包含值对象的基础包

java.time.chrono – 提供对不同的日历系统的访问

java.time.format – 格式化和解析时间和日期

java.time.temporal – 包括底层框架和扩展特性

java.time.zone – 包含时区支持的类

说明:大多数开发者只会用到基础包和format包也可能会用到temporal包。因此尽管有68个新的公开类型大多数开发者大概将只会用到其中的三分之一。

所以这里我们认识一些常用的就可以了。

LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类它们的实例是不可变的对象分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。

ISO-8601:日历系统是国际标准化组织制定的现代公民的日期和时间的表示 法也就是公历

它们提供了简单的本地日期或时间并不包含当前的时间信息也不包含与时区相关的信息。

  • LocalDate 代表IOS格式(yyyy-MM-dd的日期(年月日 没有时分秒,可以存储 生日、纪念日等日期。

在这里插入图片描述

  • LocalTime 表示一个时间(时分秒 而不是日期也就是没有 年月日。

在这里插入图片描述

  • LocalDateTime 是用来表示日期(年月日)和时间(时分秒)的这是一个最常用的类之一。是 LocalDate LocalTime。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


4.1 LocalDateLocalTimeLocalDateTime 常用的方法

LocalDate ,LocatTimeLocalDateTime 这三者的常用的方法基本上相似的所以这里我们就放在一起讲解了。

4.1.1 now() 类方法

首先创建对象调用其中的方法。但是 LocalDate , LocalTimeLocalDateTime 这三者是没有构造器的。

而是调用其中的 now() 静态方法创建对应的对象。

public static LocalDate now();       // 默认创建当前系统日期(年月日)的 LocalDate对象
public static LocalTime now();       // 默认创建当前系统时间(时分秒)的 LocalTime对象
public static LocalDateTime now();   // 默认创建当前系统日期时间(年月日时分秒) LocalDateTime 对象

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


举例:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class JDK8Date {
    public static void main(String[] args) {
        LocalDate localDate = LocalDate.now();  // 静态方法获取到当前系统日期(年月日) localDate对象
        System.out.println(localDate);
        LocalTime localTime = LocalTime.now();  // 静态方法获取到当前系统时间(时分秒) localTime对象
        System.out.println(localTime);
        LocalDateTime localDateTime = LocalDateTime.now();  // 静态方法获取当前系统日期时间 LocalDateTime 对象
        System.out.println(localDateTime);

    }
}

在这里插入图片描述


4.1.2 of( ) 类方法

LocalTimeLocalDateLocalDateTime 类的 of 方法:

public static LocalTime of(int hour,int minute,int second);  // 设置指定的时分秒 创建 LocalTime对象
public static LocalDate of(int year,int month,int dayOfMonth);  // 设置指定的 年月日 创建 LocalDate对象
public static LocalDateTime of(int year,int month,int dayOfMonth,int hour,int minute,int second);  // 设置指定的年月日时分秒 创建 LocalDateTime 对象

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


举例:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class JDK8Date {
    public static void main(String[] args) {
        LocalTime localTime = LocalTime.of(15,20,36);
        LocalDate localDate = LocalDate.of(2023,1,20);
        LocalDateTime localDateTime = LocalDateTime.of(2023,1,20,15,20,36);

        System.out.println(localTime);
        System.out.println(localDate);
        System.out.println(localDateTime);
    }
}

在这里插入图片描述


4.1.3 getxxx( ) 对象方法

LocalTimeLocalDateLocalDateTime 类的 getXXX() 方法: 获取对应对象中的年月日时分秒星期几

public DayOfWeek getDayOfWeek();
public int getYear();  // 获取年
public Month getMonth()// 获取月份
public int getHour();     // 获取小时
public int getMinute();   // 获取分钟

举例:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class JDK8Date {
    public static void main(String[] args) {
        LocalDate localDate = LocalDate.now();  // 静态方法获取到当前系统日期(年月日) localDate对象
        System.out.println(localDate.getDayOfYear());  // 获取年份

        LocalTime localTime = LocalTime.now();  // 静态方法获取到当前系统时间(时分秒) localTime对象
        System.out.println(localTime.getHour());   // 获取小时

        LocalDateTime localDateTime = LocalDateTime.now();  // 静态方法获取当前系统日期时间 LocalDateTime 对象
        System.out.println(localDateTime.getDayOfWeek());         // 获取星期
    }
}

在这里插入图片描述


4.1.4 with() 修改 withDayOfMonth()/withDayOfYear()/withMonth()/withYear()

LocalTimeLocalDateLocalDateTime 类的 WithXXX() 方法: 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象

public LocalTime withHour(int hour); // 返回这个LocalTime的副本对象并更改日期值不可变
public LocalDate withYear(int year); // 返回此日期的副本并更改年份。 如果一年中的日期无效它将被更改为该月的最后一个有效日期。
public LocalDateTime withMonth(int month);  // 返回此年份更改的LocalDateTime的副本。 时间不影响计算结果将相同。 如果一年中的日期无效它将被更改为该月的最后一个有效日期。 

举例:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class JDK8Date {
    public static void main(String[] args) {
        LocalDate localDate = LocalDate.now();  // 静态方法获取到当前系统日期(年月日) localDate对象
        System.out.println(localDate);
        LocalDate localDate2 = localDate.withYear(2020);   // 修改年份,不可变返回一个新的LocalDate对象
        System.out.println(localDate2);

        LocalTime localTime = LocalTime.now();  // 静态方法获取到当前系统时间(时分秒) localTime对象
        System.out.println(localTime);
        LocalTime localTime2 = localTime.withHour(20);   // 修改小时不可变返回一个新的LocalTime对象
        System.out.println(localTime2);

        LocalDateTime localDateTime = LocalDateTime.now();  // 静态方法获取当前系统日期时间 LocalDateTime 对象
        System.out.println(localDateTime);
        LocalDateTime localDateTime2 = localDateTime.withMonth(6);  // 修改月份不可变返回一个新的LocalDateTime对象
        System.out.println(localDateTime2);


    }
}

在这里插入图片描述


4.1.5 plusXXX() 和 / minuXXX()

  • plusDays(), plusWeeks(), plusMonths(), plusYears()plusHours(): 向当前对象添加几天、几周、几个月、几年、几小时
  • minusMonths() minusWeeks()minusDays()minusYears()minusHours() :从当前对象减去几月、几周、几天、几年、几小时

举例:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class JDK8Date {
    public static void main(String[] args) {
        // 不可变性: 不是从原本的对象上修改的而是返回一个新键修改的对象
        LocalDate localDate = LocalDate.now();  // 静态方法获取到当前系统日期(年月日) localDate对象
        System.out.println(localDate);
        LocalDate localDate2 = localDate.plusYears(1);   // 增加 1 年份,不可变返回一个新的LocalDate对象
        System.out.println(localDate2);
        LocalDate localDate3 = localDate.minusYears(1);   // 减去 1 年份,不可变返回一个新的LocalDate对象
        System.out.println(localDate3);

        LocalTime localTime = LocalTime.now();  // 静态方法获取到当前系统时间(时分秒) localTime对象
        System.out.println(localTime);
        LocalTime localTime2 = localTime.plusHours(20);   // 增加 20 小时不可变返回一个新的LocalTime对象
        System.out.println(localTime2);
        LocalTime localTime3 = localTime.minusHours(20);   // 减少 20 小时不可变返回一个新的LocalTime对象
        System.out.println(localTime3);


        LocalDateTime localDateTime = LocalDateTime.now();  // 静态方法获取当前系统日期时间 LocalDateTime 对象
        System.out.println(localDateTime);
        LocalDateTime localDateTime2 = localDateTime.plusMonths(6);  // 增加 6 月份不可变返回一个新的LocalDateTime对象
        System.out.println(localDateTime2);
        LocalDateTime localDateTime3 = localDateTime.minusMonths(6);  // 减少 6 月份不可变返回一个新的LocalDateTime对象
        System.out.println(localDateTime3);

    }
}

在这里插入图片描述


5. JDK 8 中的 : java.time.format.DateTimeFormatter

java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:

  • 预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME

  • 本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)

  • 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

在这里插入图片描述

在这里插入图片描述


常用的方法:

  • public static DateTimeFormatter ofPattern(String pattern) :静态方法返回一个指定字符串格式/日期时间格式的 DatTimeFormatter 一般是使用该方法创建 DateTimeFormatter 对象的。

在这里插入图片描述

  • public String format(TemporalAccessor temporal) : 将对应格式的日期时间 ——> 转换为 字符串类型
  • public TemporalAccessor parse(CharSequence text) : 将对应格式的字符串的格式 ——> 转换为 日期时间类型。
  • 注意: 字符串的格式 与 日期时间类型的格式是要保持一致的不然报异常 java.time.format.DateTimeParseException

**预定义的标准格式。如:**ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME 进行格式化和解析

举例:

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

public class JDKDateTimeFormatter {
    public static void main(String[] args) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME;
        // 格式化: 将日期 --> 字符串类型
        LocalDateTime localDateTime = LocalDateTime.now();  // 当前系统的时间
        String str = dateTimeFormatter.format(localDateTime);  // 将日期 --> 字符串类型
        System.out.println(str);

        // 解析: 将字符串  --> 日期时间类型
        String str2 = "2019-02-18T15:42:18.797";   // 注意格式:日期时间的格式 要 和字符串的格式 一致不然报异常
        TemporalAccessor temporalAccessor = dateTimeFormatter.parse(str2);
        System.out.println(temporalAccessor);
    }
}

在这里插入图片描述


第二种格式就不介绍了我们这里直接介绍第三种方式自定义的方式这种方式才是我们开发中经常用的方式。

自定义格式

举例:

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

public class JDKDateTimeFormatter {
    public static void main(String[] args) {
        // 重点: 方式三: 自定义的格式如: ofPattern("yyy-MM-dd hh:mm:ss")
        // 将日期 ---> 字符串
        // 创建自定义格式的 DateTimeFormatter 对象的实例
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        String s = formatter.format(LocalDateTime.now()); // LocalDateTime.now()默认是当前系统时间的LocalDateTime对象
        System.out.println(s);
        

        // 将字符串 ————> 日期
        TemporalAccessor parse = formatter.parse("2019-09-07 02:09:09");  // 注意格式需要对应起来,
        System.out.println(parse);
    }
}

在这里插入图片描述


6. Instant 类的使用

Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。

  • 在处理时间和日期的时候我们通常会想到年,月,日,时,分,秒。然而这只是 时间的一个模型是面向人类的。第二种通用模型是面向机器的或者说是连续的。在此模型中时间线中的一个点表示为一个很大的数这有利于计算机处理。在UNIX中这个数从1970年开始以秒为的单位;同样的在Java中 也是从1970年开始但以毫秒为单位。

  • java.time包通过值类型Instant提供机器视图不提供处理人类意义上的时间 单位。Instant表示时间线上的一点而不需要任何上下文信息例如时区。 概念上讲它只是简单的表示自1970年1月1日0时0分0秒(UTC开始的秒 数。因为java.time包是基于纳秒计算的所以Instant的精度可以达到纳秒级。

  • (1 ns = 10 ^ -9 s) 1秒 = 1000毫秒 =106微秒=109纳秒

时间戳:是指格林威治时间 1970 年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。

在这里插入图片描述

在这里插入图片描述

Instant 没有构造器通过 now() 静态方法 创建 Instant 对象

public static Instant now();  // 默认返回的当前系统的日期时间的 Instant 对象

在这里插入图片描述

举例:

import java.time.Instant;

public class InstantTest {
    public static void main(String[] args) {
        // 通过 Instant.now() 创建 Instant 对象
        Instant instant = Instant.now();  // 默认是当前系统的日期时间
        System.out.println(instant);

    }
}

在这里插入图片描述


Instant 常用的方法

  • public static Instant ofEpochMilli(long epochMilli) :表示静态方法返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类的对象

在这里插入图片描述

  • public long toEpochMilli() : 表示 返回1970-01-01 00:00:00到当前时间的毫秒数即为时间戳

在这里插入图片描述

举例:

import java.time.Instant;

public class InstantTest {
    public static void main(String[] args) {
        Instant instant = Instant.ofEpochMilli(1000);
        System.out.println(instant);

        // 获取当前时间到 1970年1月1日0时0分0秒
        Instant instant2 = Instant.now();
        long toEpochMilli = instant2.toEpochMilli();
        System.out.println(toEpochMilli);  // 获取到对应 Instant 对象中的时间戳,毫秒值


    }
}

在这里插入图片描述


7. JDK 8 中的 :处理日期时间的工具类: ChronoUnit DurationPeriod

  • Duraiton: 在测量机器时间的情况下Duration 最合适例如使用 Instant 对象的代码。Duration 对象以秒或纳秒度量 不使用基于 Date 的结构如年、月和日尽管类提供了转换为天数、小时和分钟的方法。 Duration 用于计算两个 “时间” 间隔(秒纳秒)

在这里插入图片描述

举例:

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class DurationPeriodChrono {
    public static void main(String[] args) {
        // 创建当前系统时间的 LocalDateTime 对象
        LocalDateTime today = LocalDateTime.now();
        System.out.println(today);

        // 创建指定时间的 LocalDateTime 对象
        LocalDateTime birthDate = LocalDateTime.of(2000, 1, 1, 0, 00, 00);
        System.out.println(birthDate);

        // 创建Duration 计算两个“时间” 间隔的工具对象。
        Duration duration = Duration.between(birthDate, today); // 第二个参数 - 第一个参数
        System.out.println("相差的时间间隔对象: " + duration);

        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());  // 两个时间差的纳秒数
    }
}

在这里插入图片描述

ChronoUnit : 大多基于 temporal 对象都提供了一个无参数的 now() 方法它提供了使用系统时钟和默认时区的当前日期和时间。 这些基于时间的对象还提供了一个单参数 now (clock) 方法 允许您传入另一个时钟。ChronoUnit 用于计算两个 “日期” 间隔

在这里插入图片描述

举例:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class DurationPeriodChrono {
    public static void main(String[] args) {
        // 获取当前系统日期时间的 LocalDateTime 对象
        LocalDateTime today = LocalDateTime.now();
        System.out.println(today);

        // 创建自定义日期时间的 LocalDateTime对象
        LocalDateTime birthDate = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
        System.out.println(birthDate);

        System.out.println("相差的年数: " + ChronoUnit.YEARS.between(birthDate, today));
        System.out.println("相差的月数: " + ChronoUnit.MONTHS.between(birthDate, today));
        System.out.println("相差的周数: " + ChronoUnit.WEEKS.between(birthDate, today));
        System.out.println("相差的天数: " + ChronoUnit.DAYS.between(birthDate, today));
        System.out.println("相差的时数: " + ChronoUnit.HOURS.between(birthDate, today));
        System.out.println("相差的分钟数: " + ChronoUnit.MINUTES.between(birthDate, today));
        System.out.println("相差的秒数: " + ChronoUnit.SECONDS.between(birthDate, today));
        System.out.println("相差的毫秒数: " + ChronoUnit.MILLIS.between(birthDate, today));
        System.out.println("相差的纳秒数: " + ChronoUnit.NANOS.between(birthDate, today));
        System.out.println("相差的微秒数: " + ChronoUnit.MICROS.between(birthDate, today));
        System.out.println("相差的半天数: " + ChronoUnit.NANOS.between(birthDate, today));
        System.out.println("相差的十年数: " + ChronoUnit.DECADES.between(birthDate, today));
        System.out.println("相差的世纪(百年)数: " + ChronoUnit.CENTURIES.between(birthDate, today));
        System.out.println("相差的千年数: " + ChronoUnit.MILLENNIA.between(birthDate, today));
        System.out.println("相差的纪元数: " + ChronoUnit.ERAS.between(birthDate, today));
    }
}

在这里插入图片描述


Period: 要用基于日期的值(年、月、日来定义大量的时间使用周期类。周期类提供了各种 get 方法 例如 getMonths getDaysgetYears这样您就可以从周期中提取出时间的数量。时间由三个单位组成:月、日、年。为了显示在一个单位时间内测量的时间量比如天数你可以使用 ChronoUnit.between 的方法。 Period 用于计算两个 “日期” 间隔(年月日)

举例:

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

public class DurationPeriodChrono {
    public static void main(String[] args) {
        // 当前系统的年月日中 的LocalDate 对象
        LocalDate today = LocalDate.now();
        System.out.println(today);

        // 生日的年月日
        LocalDate birthDate = LocalDate.of(2000, 1, 1);
        System.out.println(birthDate);

        // Period 用于计算两个 "日期" 间隔的工具类
        Period period = Period.between(birthDate, today);  // 第二个参数 - 第一个参数
        System.out.println("相差的时间间隔对象: " + period);
        System.out.println(period.getYears());  // 相差的年
        System.out.println(period.getMonths());  // 相差的月
        System.out.println(period.getDays());  // 相差的天数

        System.out.println(period.toTotalMonths());  // 相差的总月数
    }
}

在这里插入图片描述

8. 其他的API

  • ZoneId 该类中包含了所有的时区信息一个时区的ID如 Europe/Paris
static Set<String> getAvailableZoneIds(); // 获取java中支持的所有时区
static ZoneId systemDefault();            // 获取系统默认时区
static ZonId of(String zoneId);           // 获取一个指定时区
import java.time.ZoneId;
import java.util.Set;

public class ZoneldAndZonedDateTimeTest {
    public static void main(String[] args) {
        // 1.获取到所有的时区名称
        Set<String> zoneIds = ZoneId.getAvailableZoneIds();
        System.out.println(zoneIds);  //  America/Cuiaba
        System.out.println(zoneIds.size());   // 共有 599 个时区


        // 2. 获取到当前系统的默认时区
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId); // Asia/Shanghai 注意了没有北京的只有上海的
    }
}

在这里插入图片描述

  • ZonedDateTime一个在ISO-8601日历系统时区的日期时间如 2007-12- 03T10:15:30+01:00 Europe/Paris。 其中每个时区都对应着ID地区ID都为“{区域}/{城市}”的格式例如:Asia/Shanghai等

细节:jdk8 新增的时间对象都是不可变的如果我们修改了减少了增加了时间那么调用者是不会发生该改变的而是生产一个新的时间。

带时区的 ZoneDateTimestatic ZonedDateTime now()         // 获取当前时间的ZonedDateTime对象
static ZonedDateTime ofxxx(....)   // 获取指定时间的ZoneDateTime对象
static ZonedDateTime withXxx(时间)  // 修改时间系别的方法
static ZonedDateTime minusXxx(时间) // 减少时间系别的方法
static ZonedDateTime plusXxx(时间)  // 增加时间系别的方法

举例:

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

public class ZoneldAndZonedDateTimeTest {
    public static void main(String[] args) {
        // 1. 获取当前系统时间的对象(带时区)
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);

        // 2. 获取指定时间对象(带时区的)
        ZonedDateTime zonedDateTime2 = ZonedDateTime.of(2023, 10, 1,
                11, 12, 12, 0, ZoneId.of("Asia/Shanghai"));

        System.out.println(zonedDateTime2);

        // 通过Instant + 时区的方式指定获取时间对象
        Instant instant = Instant.ofEpochMilli(0L);
        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
        ZonedDateTime time = ZonedDateTime.ofInstant(instant, zoneId);
        System.out.println(time);


        // 3.withxxx 修改时间系别的方法
        ZonedDateTime time2 = time.withYear(2000);
        System.out.println(time2);


        // 减少时间
        ZonedDateTime time3 = time.minusYears(1);
        System.out.println(time3);

        // 增加时间
        ZonedDateTime time4 = time.plusYears(1);
        System.out.println(time4);
    }
}

在这里插入图片描述

  • Clock: 使用时区提供对当前即时、日期和时间的访问的时钟。持续时间:Duration用于计算两个“时间”间隔

  • 日期间隔:Period用于计算两个“日期”间隔

  • TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整 到“下一个工作日”等操作。

  • TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。

9. 关于日期时间的算法题

  • 比较两个 Date 对象哪个时间在前哪个时间在后Date 类型是不可以之间比较的我们需要比较的是 Date 各自的时间戳。
import java.util.Date;
import java.util.Random;

public class DateExam {
    public static void main(String[] args) {
        Random random = new Random();

        // random.nextLong()生产 long范围内的随机值Math.abs()绝对值
        Date date1 = new Date(Math.abs(random.nextLong()));
        Date date2 = new Date(Math.abs(random.nextLong()));

        if(date1.getTime() > date2.getTime()) {
            System.out.println("date2时间在前");
        } else if(date1.getTime() < date2.getTime()) {
            System.out.println("date1时间在前");
        } else {
            System.out.println("date1 == date2 的时间");
        }
    }
}

在这里插入图片描述

  • 需求:
    • 秒杀活动 2023 年 11月 11日 0:0:0 (毫秒值)开始时间: 2023年 11 月 11日 0:10:0 (毫秒值)小贾下单开付款的时间为: 2023年11月11日 0:01:00小皮下单开付款的时间为: 2023年11月11日 0:11:0用代码说明这两位同学有没有参加上秒杀活动
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateExam {
    public static void main(String[] args) {
        // 1. 定义字符串表示三个时间段
        String startStr = "2023年11月11日 0:0:0";
        String endStr = "2023年11月11日 0:0:0";
        String orderStr = "2023年11月11日 0:01:0";

        // 2. 将上述三个字符串转换为 Date 类型
        // 注意字符串的格式与 SimpleDateFormat()所传参数的格式要一致不然报异常
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
        Date startDate = null;
        Date endDate = null;
        Date orderDate = null;

        try {
            startDate = simpleDateFormat.parse(startStr);
            endDate = simpleDateFormat.parse(endStr);
            orderDate = simpleDateFormat.parse(orderStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        // 3.得到三个设置的Date 对象的毫秒值时间戳
        long startDateTime = startDate.getTime();
        long endDateTime = endDate.getTime();
        long orderDateTime = orderDate.getTime();

        // 4. 判断
        if (orderDateTime >= startDateTime && orderDateTime <= endDateTime) {
            System.out.println("参加了秒杀活动成功");
        } else {
            System.out.println("参加秒杀活动失败");
        }

    }
}

在这里插入图片描述


10. 总结:

  • java.util.Date 包下的 转换为 java.sql.Date 包下的方式java.sql.Date 可以强制转换为 java.util.Date包下的日期时间类型因为 java.sql.Date extends 继承了 java.util.Date 包父类(多态性 )。但是 java.sql.Date 不可以 强制转换为 java.util.Date 包下的因为 java.sql.Date不是器多态的性的实例对象。而是通过两者之间的 时间戳 转换。

  • JDK 8 之前的:格式: String字符串类型 ——> Date 日期时间类型解析:Date日期时间类型 ——> String 字符串类型

  • JDK 8 之后的: 格式: String字符串类型 ——> Date 日期时间类型解析:Date日期时间类型 ——> String 字符串类型

  • String < ———> Date日期时间类型:注意两者之间的格式必须保持一致不然报异常。

  • java.time 包中包含很多类你的程序可以用来表示时间和日期。这是一个非常丰富的 API。基于 ISO 日期的关键入口点如下:

  • Instant 提供了时间轴的机器视图。
  • LocalDate, LocalTime, and LocalDateTime 提供了日期和时间的人类视图不包含时区。
  • ZoneId, ZoneRules, and ZoneOffset 描述了时区、时区规则和时区偏移。
  • ZonedDateTime 表示日期和时间与时区;OffsetDateTime和OffsetTime 类分别表示日期和时间或者时间。这些类考虑了时区偏移量。
  • Duration 测量日、时、分、秒、毫秒、纳秒的时间量
  • Period 测量年、月、日的时间量
  • 其他非 ISO 日历系统可以使用 java.time.chrono 包来表示。虽然 非ISO日期转换页面 提供了有关将基于 ISO 的日期转换为其他日历系统的信息但此包不在本教程的讨论范围内 。

11. 最后:

限于自身水平其中存在的错误希望大家给予指教韩信点兵——多多益善谢谢大家江湖再见后会有期


在这里插入图片描述

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6