Java日期时间类

发布于 2023-08-04  1.65k 次阅读


Java JDK时间类的版本演变:

1)Java 1.0:最早的Java版本引入java.util.Date类作为处理日期时间的基本类。但这个类存在很多问题,如可变性、线程安全性和设计上的限制

2)Java 1.1:为了解决Date类的问题,Java 1.1引入了java.util.Calendar类。Calendar类提供了更多的日期和时间操作方法,并且具有更好的线程安全性。它允许执行日期和时间的计算、格式化和解析等操作

3)Java 1.4:引入了java.text.DateFormat类,用于格式化和解析日期和时间。DateFormat类提供了各种格式化选项,以便根据需要将日期和时间转换为字符串或从字符串解析为日期时间

4)java 1.8:JavaSE 8引入全新的日期和时间API,位于java.time包中。这个新的API提供了一组强大的类,如LocalDate、LocalTime、LocalDateTime、ZonedDateTime等,用于处理日期、时间和时区。它们具有不可变性,线程安全性和更好的设计,它提供了更多的功能和更好的性能

1. Date时间类

  Date类实例表示自1970年1月1日00:00:00 GMT以来的毫秒数,可以使用Date类来获取当前日期和时间,或者指定的日期和时间

1.1 Date构造

Date有参构造主要构建静态时间,无参构造构建动态当前时间

构造方法:

  • Date():无参构造方法,创建一个表示当前日期和时间的Date对象。
  • Date(long milliseconds):使用指定的毫秒数创建一个Date对象。毫秒数是自1970年1月1日00:00:00 GMT以来的时间量。
  • Date(int year, int month, int day):使用指定的年份、月份和日期创建一个Date对象。月份从0开始,即0表示一月,11表示十二月。
  • Date(int year, int month, int day, int hour, int minute):使用指定的年份、月份、日期、小时和分钟创建一个Date对象。
  • Date(int year, int month, int day, int hour, int minute, int second):使用指定的年份、月份、日期、小时、分钟和秒数创建一个Date对象。

例:

public static void main(String[] args) {
     Date date1 = new Date(99,11,11);
     Date date2 = new Date(99,11,11,1,3,34);
     Date date3 = new Date("Jan 08 2021");//字符串有固定格式格式(月份(英文) 日期 年份)
     Date date4 = new Date();
     System.out.println("静态日期(年月日):"+date1);
     System.out.println("静态日期时间(年月日时分秒):"+date2);
     System.out.println("字符串转日期:"+date3);
     System.out.print("当前日期:"+date4);     
}

输出:

静态日期(年月日):Sat Dec 11 00:00:00 CST 1999
静态日期时间(年月日时分秒):Sat Dec 11 01:03:34 CST 1999
字符串转日期:Fri Jan 08 00:00:00 CST 2021
当前日期:Sat Jul 29 23:00:00 CST 2023

格式说明:星期 月份 几号 时间 时区 年份

Sat Jul 29 23:00:00 CST 2023

注意事项:

  • 日期类的设计比较特殊,例如基于0的月份表示法(即0表示一月,11表示十二月)
  • 年份起始基准是1900,假如有参输入年份为2023,输出年份就为3923,所以输入时必须考虑基准年份
  • 日期类没有提供对时区的良好支持。在处理跨时区的日期和时间时,日期类的功能有限
  • Date类是可变的,这意味着您可以直接修改Date对象的值。这种可变性可能导致在多线程环境中出现并发问题,因为多个线程可以同时修改同一个Date对象

1.2 Date的基本方法

基本API:

  1. after(Date when):测试此日期是否在指定日期之后
  2. before(Date when):测试此日期是否在指定日期之前
  3. compareTo(Date anotherDate):比较两个时间日期,如果早于anotherDate则返回负数、等于返回0、晚于anotherDate返回正数
  4. equals(Object obj):比较两个日期是否相等
  5. getDate():获取当前日
  6. getDay():获取星期
  7. getYear():获取年
  8. getMinutes():获取月
  9. getHours():获取时
  10. getMonth():获取分
  11. getSeconds():获取秒
  12. setYear(int year):设置年
  13. setMinutes(int minutes):设置月
  14. setDate(int date):设置日
  15. setHours(int hours):设置时
  16. …………

例:

public static void main(String[] args) {
             
      Date date = new Date();
      /Date对比
      System.out.println("是否在日期之前:"+date.before(new  Date(120,10,1)));
      System.out.println("是否在日期之后:"+date.after(new  Date(120,10,1)));
      System.out.println("日期对比:"+date.compareTo(new  Date(120,10,1)));
      System.out.println("日期是否相等:"+date.equals(new Date()));
             
      //Date获取
      System.out.println("年:"+date.getYear());
      System.out.println("月:"+date.getMinutes());
      System.out.println("日:"+date.getDate());
      System.out.println("星期:"+date.getDay());
      System.out.println("时:"+date.getHours());
      System.out.println("分:"+date.getMonth());
      System.out.println("秒:"+date.getSeconds());

      //Date设置
      date.setYear(122);
      date.setMinutes(11);
      date.setDate(5);
}

输出:

是否在日期之前:false
是否在日期之后:true
日期对比:1
日期是否相等:false
年:123
月:22
日:30
星期:0
时:0
分:6
秒:31

2. Calendar时间类

  Calendar类是Java1.1推出的,1.0时提供了Date类来处理时间日期,而Date类存在一些问题,如:设计不灵活,处理时间和日期计算存在缺陷。为了解决Date存在的问题Java1.1推出了Calendar类来弥补现有Date类的不足

Calendar类的简介:

  • 和Date类一样位于java.util包下
  • Calendar类是一个抽象类,通过getInstance()方法获取其子类实例,所获得子类的实例是GregorianCalendar类对象
  • 通过Calendar类提供的get()方法获得某个时间点的各个时间分量
  • get()方法的参数为整型数据,通常以Calendar类所定义的静态属性作为参数,各时间分量与静态属性都对应

Calendar的特点:

  • 日期和时间操作:Calendar类提供了丰富的方法来处理日期和时间,包括获取年、月、日、小时、分钟、秒等各个部分的值,以及设置这些值。它还支持日期和时间的加减运算,可以方便地进行日期和时间的计算和比较
  • 日期格式化:Calendar类可以将日期和时间格式化为指定的字符串形式,以便于显示和输出。它支持各种常见的日期和时间格式,如年-月-日、月/日/年、小时:分钟:秒等
  • 时区处理:Calendar类可以处理不同时区的日期和时间。它可以根据指定的时区来获取和设置日期和时间的值,以及进行时区的转换。这对于跨时区的应用非常有用
  • 周期性操作:Calendar类支持周期性的操作,如计算某个日期是星期几,计算某个日期所在月份的第几周等。它还可以计算两个日期之间的天数、周数、月数等
  • 国际化支持:Calendar类提供了对不同语言和地区的日期和时间格式的支持。它可以根据不同的语言环境来显示日期和时间,以适应不同的文化习惯

2.1 时间分量获取

Calendar类获取时间日期只通过一个get()方法,通过输入不同Calendar静态属性获取不同时间分量

静态属性和时间分量的关系:

静态属性 对应时间分量
YEAR
MONTH 月份(注:月的值取0-11的,即如果取出的值为0,即为1月份)
DATE
HOUR 获取时,以12小时为周期(注:正午和午夜用0表示,而不是12)
MINUTE 分钟
SECOND 秒钟
MILLISECOND 毫秒(并不是从1970年1月1日00:00:00到当前产生经历的毫秒数),而是Calendar产生的某一秒钟中经历的毫秒
HOUR_OF_DAY 获取时,以24小时为周期的小时
DAY_OF_WEEK 获取星期,返回值范围1-7(1表示星期日以此类推)
DAY_OF_MONTH 一个月中的第几天,从1开始
DAY_OF_YEAR 一年中的第几天
WEEK_OF_MONTH 一个月中第几个星期
WEEK_OF_TEAR 一年中第几个星期

注:Calendar的年表示和Date的年表示有区别,Date是以1900年为基准进行相加表示当前年,Calendar直接输入当前年即可,没有1900这个基准年

例:

public static void main(String[] args) {
             
     //提供Instance()方法获取Calendar类实例
     Calendar calendar = Calendar.getInstance();
             
     //提供get()获取时间分量,通过不同的静态属性获取不同时间分量
     System.out.println("年:"+calendar.get(Calendar.YEAR));//获取年
     System.out.println("月:"+calendar.get(Calendar.MONTH));//获取月
     System.out.println("日:"+calendar.get(Calendar.DATE));//获取日
     System.out.println("日:"+calendar.get(Calendar.DAY_OF_MONTH));//获取日
     System.out.println("12时制:"+calendar.get(Calendar.HOUR));//获取时(12小时制)
     System.out.println("24时制:"+calendar.get(Calendar.HOUR_OF_DAY));//获取时(24小时制)
     System.out.println("分:"+calendar.get(Calendar.MINUTE));//获取分
     System.out.println("秒:"+calendar.get(Calendar.SECOND));//获取秒
     System.out.println("星期:"+calendar.get(Calendar.DAY_OF_WEEK));//获取星期
     System.out.println("毫秒:"+calendar.get(Calendar.MILLISECOND));//获取毫秒
}

输出:

年:2023
月:6
日:30
日:30
12时制:4
24时制:16
分:46
秒:27
星期:1
毫秒:469

2.2 时间计算对比

2.2.1 时间加减

时间计算使用:amount为正数表示相加,为负数表示相减,field为时间分量静态属性

  • add(int field, int amount):根据日历规则,将指定的时间量添加或减去给定的日历字段
  • roll(int field, int amount):将指定的时间量添加或减去给定的日历字段,而不改变较大的字段(如:超过日不会修改月份)
  • roll(int field, boolean up):up为true表示+1,为false表示-1

注:add()和roll()功能作用是一样的,唯一的区别在于add()假如相加之后的日期超过了当月份,会自动推到下一个月,而roll()如果超过了该月份不会推到下一个月份,只会再原基础上加1

例:

public static void main(String[] args) {
             
    //提供Instance()方法获取Calendar类实例
    Calendar calendar = Calendar.getInstance();
             
    calendar.add(Calendar.DATE, 10);//当前日加10天
    calendar.add(Calendar.DATE, -10);//当前日减10天
    calendar.add(Calendar.MONTH, 2);//当前月加2
    calendar.add(Calendar.YEAR, 2);//当前年加2
    calendar.add(Calendar.DAY_OF_WEEK, 1);//星期加1
             
    System.out.print(calendar.get(Calendar.YEAR)+"--"+calendar.get(Calendar.MONTH)+"--"+calendar.get(Calendar.DATE));      
}

输出:

2025--9--1

2.2.2 日期时间对比

时间日期对比和Date异曲同工:

  • after(Object when):测试此日期是否在指定日期之后
  • before(Object when):测试此日期是否在指定日期之前
  • compareTo(Calendar anotherDate):比较两个时间日期,如果早于anotherDate则返回负数、等于返回0、晚于anotherDate返回正数
  • equals(Object obj):比较两个日期是否相等

例:

public static void main(String[] args) {
       
   Calendar calendar = Calendar.getInstance();
   Calendar calendar1 = Calendar.getInstance();
   calendar.set(Calendar.MONTH, 2);
             
   System.out.println(calendar.after(calendar1));
   System.out.println(calendar.before(calendar1));
   System.out.println(calendar.compareTo(calendar1));
   System.out.println(calendar.equals(new Date(2020,11,2)));
}

输出:

false
true
-1
false

2.2.3 时间设置

Calendar类时间设置通过set()方法,通过指定不同静态时间属性设置不同时间分量(静态属性对应表见上文)

例:

public static void main(String[] args) {
             
    Calendar calendar = Calendar.getInstance();
              
    calendar.set(1999, 11, 5);
    calendar.set(Calendar.DATE,12);
    calendar.set(Calendar.MONTH,12);
    System.out.print(calendar.get(Calendar.YEAR)+"--"+calendar.get(Calendar.MONTH)+"--"+calendar.get(Calendar.DATE));
}

输出:

2000--0--12

3. DateFormat格式化

    DateFormat是java1.4推出的时间格式化类,它提供了许多类方法,用于根据默认或给定的区域设置和多个格式化样式获取默认的日期/时间格式化程序。 格式化风格包括FULL , LONG , MEDIUM和SHORT

    DateFormat是一个抽象类,它的实现类只要一个SimpleDateFormat,在操作时主要通过SimpleDateFormat实现各种操作

构造方法:

  1. SimpleDateFormat(): 创建一个默认格式的SimpleDateFormat对象。默认格式是根据系统默认的本地化设置决定的,通常是与日期和时间格式相关的本地化设置
  2. SimpleDateFormat(String pattern): 创建一个指定日期时间模式的SimpleDateFormat对象。你需要传递一个字符串参数pattern,其中包含特定的模式符号来定义日期和时间的格式。例如:
    1. "yyyy-MM-dd":表示年-月-日的格式,如"2023-07-30"
    2. "HH:mm:ss":表示时:分:秒的格式,如"15:30:45"。
  1. SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols): 这个构造方法与上一个类似,但允许你传递自定义的DateFormatSymbols对象。DateFormatSymbols用于提供特定于语言环境的日期时间元素(如月份名称、星期几名称等)
  2. SimpleDateFormat(String pattern, Locale locale): 这个构造方法允许你指定本地化设置,以便根据特定的语言环境格式化日期和时间。你可以传递一个Locale对象,例如Locale.US表示美国的本地化设置
方法:
  1. format(Date date): 将给定的Date对象格式化为字符串,使用SimpleDateFormat对象的日期时间模式。返回一个表示格式化后日期时间的字符串
  2. parse(String source): 将给定的字符串解析为Date对象,使用SimpleDateFormat对象的日期时间模式。如果解析失败,将抛出ParseException异常
  3. applyPattern(String pattern): 设置SimpleDateFormat对象的日期时间模式
  4. applyLocalizedPattern(String pattern): 使用与本地化相关的日期时间模式设置SimpleDateFormat对象
标识 日期或时间组件 介绍 例子
G 时代指示符 标识 AD
y 1996; 96
Y 星期年 2009; 09
M 年份中的月份(上下文相关) July; Jul; 07
L 年份中的月份(独立形式) July; Jul; 07
w 一年中的一周 27
W 每月的周 2
D 一年中的一天 189
d 月中的一天 10
F 每月中的星期几 2
E 周中的日期名称 标识 Tuesday; Tue
u 周数(1 = 星期一,...,7 = 星期日) 1
a 上午/下午标记 标识 PM
H 一天中的小时 (0-23) 0
k 一天中的小时 (1-24) 24
K 上午/下午的小时数 (0-11) 0
h 上午/下午的小时数 (1-12) 12
m 分钟数(小时) 30
s 秒分 55
S 毫秒 978
z 时区 一般时区 Pacific Standard Time; PST; GMT-08:00
Z 时区 RFC 822 时区 -0800
X 时区 ISO 8601 时区 -08; -0800; -08:00

例:

public static void main(String[] args) throws ParseException {
             
             //格式化日期类为字符串
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
             Date date = new Date();
             String formattedDate = sdf.format(date);
             System.out.println("格式化后的字符串: " + formattedDate);
             
             //格式化字符串为日期类
             SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
             String dateString = "2023-07-30";
             Date parsedDate = sdf1.parse(dateString);
             System.out.println("格式化后的日期类:  " + parsedDate);

             //不在构造指定格式,通过applyPattern手动指定
             SimpleDateFormat sdf2 = new SimpleDateFormat();
             sdf2.applyPattern("yyyy/MM/dd");
             Date date2 = new Date();
             String formattedDate2 = sdf2.format(date2);
             System.out.println("手动指定格式: " + formattedDate2);
       }

输出:

格式化后的字符串: 2023-07-30
格式化后的日期类:  Sun Jul 30 00:00:00 CST 2023
手动指定格式: 2023/07/30

4. 新时间日期类

4.1 产生背景

Java 8引入了新的时间日期类,即java.time包,以解决在旧的java.util.Date和java.util.Calendar中存在的一些问题

传统Date类和Calendar类存在的问题:

1)设计缺陷

    Date类同时表示日期和时间,并没有区分成专门的日期和时间,Date基准年是1900年,Calendar虽然更改了这一缺陷,当日期设置都是从0开始,在进行日期add计算时,当一个日数超过当前最大日会计入到下一个月和设置错误日期时并不会报异常,影响异常排查

2)线程安全性问题

    Calendar类在多线程环境下使用是存在线程安全问题,需要进行额外的同步处理增加了编程的复杂性

3)不兼容性

    由于历史原因(产生很早),Date类在处理日期和时间时与国际标准(ISO 8601)存在差异,这使得日期和时间的处理不够直观,容易出错

Java1.8新时间类的优势:

  1. 不可变性:新时间类是不可变的,一旦创建一个时间对象,他的值就不能改变。这种不可变性确保了时间对象的线程安全性
  2. 清晰的API设计:新时间类的API设计更加清晰,它区分了日期和时间(LocalDate,LocalTime,LocalDateTime),方法命名和代码可读性清晰
  3. 易于计算与操作:新时间类提供了许多便捷的方法来执行日期和时间的设计与操作,当知道错误时间和计算超过当前日期阈值时会报异常
  4. 新的时区支持:新时间类提供了对时区的良好支持。它们能够更好地处理不同时区之间的转换和计算,而不像旧有的API在时区处理上存在一些问题
  5. 适应函数式编程: 新时间类的设计支持Java 8的函数式编程特性(如Lambda表达式和Stream API)

Java1.8新时间系统的组成部分:java.time包

  • LocalDate(日期)
  • LocalTime(时间)
  • LocalDateTime(日期时间)
  • ZoneOffset(时差)
  • ZoneId(时区)
  • format(格式化)

4.2 LocalDate日期类

4.2.1 常用静态方法

LoaclDate的常用静态方法:

  1. now():获取当前日期
  2. now(ZoneID zoneid):指定时区获取当前日期
  3. of(int year, int month, int dayOfMonth):指定日期生成日期类
  4. of(int year, Month month, int dayOfMonth):指定日期生成日期类,Month使用的是枚举类有12个枚举对象表示1个月份
  5. parse(CharSequence text):将一个CharSequence的字符串转化为Localdate对象
  6. parse(CharSequence text, DateTimeFormatter formatter):将一个CharSequence的字符串按照DateTimeFormatter格式转化为Localdate对象

例:

public static void main(String[] args) {
             //生成当前时间
             LocalDate localdate1 = LocalDate.now();
             System.out.println(localdate1);
             
             //指定时间
             LocalDate localdate2 = LocalDate.of(2000, 11, 05);//月份使用数值
             LocalDate localdate3 = LocalDate.of(2000, Month.JUNE, 05);//月份使用枚举类
             System.out.println(localdate2);
             System.out.println(localdate3);
             
             //CharSequence字符
             CharSequence strdate1 = "2000-11-05";
             LocalDate localdate4 = LocalDate.parse(strdate1);
             System.out.println(localdate4);
             
             //格式化CharSequence字符
             CharSequence strdate2 = "2000/11/05";
             DateTimeFormatter dateTimeFormatter =  DateTimeFormatter.ofPattern("yyyy/MM/dd");
             LocalDate localdate5 =  LocalDate.parse(strdate2,dateTimeFormatter);
             System.out.println(localdate5);
       }

输出:

2023-08-02
2000-11-05
2000-06-05
2000-11-05
2000-11-05

4.2.2 日期分量获取

 方法:

  1. getDayOfMonth():获取月份
  2. getYear():获取年份
  3. getMonth():获取月份,返回值为Month枚举对象
  4. getDayOfWeek():获取星期字段
  5. getDayOfYear():获取日
  6. get(TemporalField field):获取日期分量的同用方法,通过ChronoField枚举常量直接获取

例:

public static void main(String[] args) {
             
             LocalDate localdate = LocalDate.now();
             
             //获取年
             System.out.println("年:"+localdate.getYear());
             
             //获取月份
             System.out.println("月(枚举):"+localdate.getMonth());
             System.out.println("月(正常):"+localdate.getMonthValue());
             //获取日
             System.out.println("日:"+localdate.getDayOfMonth());
             
             //获取星期
             System.out.println("星期:"+localdate.getDayOfWeek());
             
             //通用方式获取
             System.out.println("年:"+localdate.get(ChronoField.YEAR));
             System.out.println("月:"+localdate.get(ChronoField.MONTH_OF_YEAR));
             System.out.println("日:"+localdate.get(ChronoField.DAY_OF_MONTH));
             System.out.println("星期:"+localdate.get(ChronoField.DAY_OF_WEEK));
       }

输出:

年:2023
月(枚举):AUGUST
月(正常):8
日:3
星期:THURSDAY
年:2023
月:8
日:3
星期:4

4.2.3 日期设置

新日期时间类为了线程安全,每次修改日期都会返回一个新的日期对象而不会修改原对象

修改日期时间的方法:

  • withYear():修改年
  • withMonth():修改月份
  • withDayOfMonth():修改日
  • with(TemporalAdjuster adjuster):通用修改方法,通过指定ChronoField枚举时间分量

注:和Calendar和Date不一样,但修改的日期错误时LocalDate会报异常

例:

public static void main(String[] args) {
             
             LocalDate localdate = LocalDate.now();
             
             //修改年月日
             LocalDate localdate1 = localdate.withYear(2000);
             LocalDate localdate2 = localdate.withMonth(6);
             LocalDate localdate3 = localdate.withDayOfMonth(6);
             
             //使用with常量修改年月日
             LocalDate localdate4 = localdate.with(ChronoField.YEAR,2001);
             LocalDate localdate5 =  localdate.with(ChronoField.MONTH_OF_YEAR,6);
             LocalDate localdate6 = localdate.with(ChronoField.DAY_OF_MONTH,6);
             System.out.println(localdate1+"\t"+localdate2+"\t"+localdate3);
             System.out.println(localdate4+"\t"+localdate5+"\t"+localdate6);
       }

输出:

2000-08-03   2023-06-03   2023-08-06
2001-08-03   2023-06-03   2023-08-06

4.2.4 日期计算

日期计算使用minus和plus方法,minus输入正数时表示减,输入负数时表示加,plus输入正数时表示加,输入负数时表示减

方法:

  • minusYears():对年进行减计算
  • minusMonths():对月进行减计算
  • minusDays():对日进行减计算
  • minusWeeks():对星期进行减计算
  • minus(long amountToSubtract,TemporalUnit unit):指定ChronoUnit常量(日期分量)进行计算
  • plusYears():对年进行加计算
  • plusMonths():对月进行加计算
  • plusDays():对日进行加计算
  • plusWeeks():对星期进行加计算
  • until(Temporal endExclusive, TemporalUnit unit):计算与指定日期的差值

例:

public static void main(String[] args) {
             
             LocalDate localdate = LocalDate.now();
             
             //日加减
             LocalDate localdate1 = localdate.minusDays(-2);
             LocalDate localdate2 = localdate.minusDays(2);
             System.out.println(localdate1+"\t"+localdate2);
             
             //年加减
             LocalDate localdate3 = localdate.minusYears(-2);
             LocalDate localdate4 = localdate.minusYears(2);
             System.out.println(localdate3+"\t"+localdate4);
             
             //年加减
             LocalDate localdate5 = localdate.minusMonths(-2);
             LocalDate localdate6 = localdate.minusMonths(2);
             System.out.println(localdate5+"\t"+localdate6);
             
             //年加减
             LocalDate localdate7 = localdate.minus(-2,ChronoUnit.YEARS);
             LocalDate localdate8 = localdate.minus(2,ChronoUnit.YEARS);
             System.out.println(localdate7+"\t"+localdate8);
    
             //计算差值
             LocalDate localdate9 = LocalDate.of(2020, 11, 11);
             Long l = localdate.until(localdate9, ChronoUnit.DAYS);
             System.out.println("计算差日分量值"+l);
       }

输出:

2023-08-05   2023-08-01
2025-08-03   2021-08-03
2023-10-03   2023-06-03
2025-08-03   2021-08-03
计算差日分量值-995

4.2.5 日期判断

日期判断除了支持原有Date和Calendar的判断方法外还提供其他有用的方法

方法:

  • isAfter():检测日期是否在指定日期之后
  • isBefore():检测日期是否在指定日期之前
  • isEqual():日期是否在指定日期相等
  • isLeapYear():检测年份是否是闰年
  • lengthOfMonth():返回此月份的长度(天数)
  • lengthOfYear():返回此年份的长度(天数)
  • range():指定字段的有效范围

例:

public static void main(String[] args) {
             
             LocalDate localdate = LocalDate.now();
             
             LocalDate localdate1 = LocalDate.of(2020, 11, 11);
             
             System.out.println("是否在指定日期之后:"+localdate.isAfter(localdate1));
             System.out.println("是否在指定日期之前:"+localdate.isBefore(localdate1));
             System.out.println("是否和指定日期相等:"+localdate.isEqual(localdate1));
             System.out.println("是否为闰年:"+localdate.isLeapYear());
             System.out.println("该月的长度:"+localdate.lengthOfMonth());
             System.out.println("该年的长度:"+localdate.lengthOfYear());
             System.out.println("该字段的有效范围:"+localdate.range(ChronoField.DAY_OF_MONTH));
       }

输出:

是否在指定日期之后:true
是否在指定日期之前:false
是否和指定日期相等:false
是否为闰年:false
该月的长度:31
该年的长度:365
该字段的有效范围:1 - 31

4.3 LocalTime时间类

LocalTime的特点:

  • 不含日期信息: LocalTime只表示时间,不包含日期和时区信息
  • 不可变性: LocalTime是不可变的(immutable)类,一旦创建,其值不能被修改。所有的操作都会返回一个新的LocalTime实例
  • 精确到纳秒: LocalTime可以精确到纳秒级别,即可以表示9位数字的时间,格式为hh:mm:ss.SSSSSSSSS
  • 解析和格式化: LocalTime支持日期时间字符串的解析和格式化。可以使用DateTimeFormatter类来自定义格式
  • 获取时间信息: 可以通过getHour()、getMinute()、getSecond()等方法获取时间的小时、分钟、秒等信息
  • 比较和计算: LocalTime提供了各种方法进行时间的比较和计算,比如isBefore()、isAfter()、plusHours()、minusMinutes()等
  • 工厂方法: LocalTime提供了静态工厂方法,如now()用于获取当前时间,of()用于创建指定的时间实例
  • 时区信息: LocalTime是不带时区信息的类。如果需要处理带时区的时间,可以使用ZonedDateTime类

4.3.1 LocalTime创建

方法:

  • now():获取当前时间
  • of(int hour,int minute):通过指定小时和分钟创建时间
  • of(int hour,int minute,int second):通过指定小时、分钟、秒创建时间
  • of(int hour,int minute,int second,int nanoOfSecond):通过指定小时、分钟、秒、纳秒创建时间
  • ofSecondOfDay(long secondOfDay):指定一天中的第多少秒获取那个时间
  • NOON:获取中午时间
  • MIDNIGHT:获取午夜
  • MAX:获取一天最大时间
  • MIN:获取一天最小时间

例:

public static void main(String[] args) {
             //创建当前时间
             LocalTime localtime1 = LocalTime.now();
             System.out.println("当前时间:"+localtime1);
             
             //指定时间
             LocalTime localtime2 = LocalTime.of(15 , 5, 52);
             LocalTime localtime3 = LocalTime.of(15 , 5, 52,1000);
             System.out.println("指定时间(时分秒):"+localtime2);
             System.out.println("指定时间(时分秒纳秒):"+localtime3);
             
             //获取中午时间
             LocalTime localtime4 = LocalTime.NOON;
             LocalTime localtime5 = LocalTime.MIDNIGHT;
             LocalTime localtime6 = LocalTime.MAX;
             LocalTime localtime7 = LocalTime.MIN;
             System.out.println("获取中午:"+localtime2);
             System.out.println("获取午夜:"+localtime5);
             System.out.println("获取最大时间点:"+localtime6);
             System.out.println("获取最小时间点:"+localtime7);
       }

输出:

当前时间:22:31:09.341
指定时间(时分秒):15:05:52
指定时间(时分秒纳秒):15:05:52.000001
获取中午:15:05:52
获取午夜:00:00
获取最大时间点:23:59:59.999999999
获取最大时间点:00:00

4.3.2 时间分量获取

方法:

  • get():同样获取方法,通过指定时间分量常量获取对于时间
  • getHour():获取小时
  • getMinute():获取分钟
  • getSecond():获取秒
  • getNano():获取纳秒
  • toNanoOfDay():获取时间在一天中所处的纳秒数
  • toSecondOfDay():获取时间在一天中所处的秒数

例:

public static void main(String[] args) {
            
            LocalTime localtime = LocalTime.now();
            
            //通过指定常量获取时间分量
            System.out.println("(常量)获取小时:"+localtime.get(ChronoField.HOUR_OF_DAY));//获取小时
            System.out.println("(常量)获取分钟:"+localtime.get(ChronoField.MINUTE_OF_HOUR));//获取小时中的分钟
            System.out.println("(常量)获取秒:"+localtime.get(ChronoField.SECOND_OF_MINUTE));//当前分钟的秒
            System.out.println("(常量)获取毫秒:"+localtime.get(ChronoField.MILLI_OF_SECOND));//当前秒的毫秒
            System.out.println("(常量)获取当天第几分钟:"+localtime.get(ChronoField.MINUTE_OF_DAY));//当前天的第几分钟
            System.out.println("(常量)获取当天第几秒:"+localtime.get(ChronoField.SECOND_OF_DAY));//当前天的第几秒
            System.out.println("(常量)获取当天第几毫秒:"+localtime.get(ChronoField.MILLI_OF_DAY));//当前天的第几毫秒
            
            //通过方法时间分量
            System.out.println("获取小时:"+localtime.getHour());
            System.out.println("获取分钟:"+localtime.getMinute());
            System.out.println("获取秒:"+localtime.getSecond());
            System.out.println("获取纳秒:"+localtime.getNano());
      }

输出:

(常量)获取小时:23
(常量)获取分钟:20
(常量)获取秒:36
(常量)获取毫秒:167
(常量)获取当天第几分钟:1400
(常量)获取当天第几秒:84036
(常量)获取当天第几毫秒:84036167
获取小时:23
获取分钟:20
获取秒:36
获取纳秒:167000000

4.3.3 说明

后续的时间判断、时间计算、时间修改和LocalDate都是一样的:
  • 时间判断:
    • isAfter():是否在指定时间之后
    • isBefore():是否在指定时间之前
    • compareTo():时间比较
    • equals():时间是否相等
  • 时间计算:
    • minus():减法计算
    • puls():加分计算
  • 时间修改:
    • with():指定时间常量对对应的时间分量进行修改
    • withHour():对时进行修改
    • withMonute():对分进行修改
    • withSecond():对秒进行修改
    • withNano():对纳秒进行修改
  • 其他:
    • atDate(LocalDate date):与LocalDate组合成LocalDateTime时间日期类

4.4 LocalDateTime日期时间类

LocalDateTime本质上就是将LocalDate和LocalTime结合在一起表示,在API中LocalDateTime和LocalDate、LocalTime其实都是大同小异

4.4.1 LoaclDateTime创建

方法:

  • now():获取当前时间日期对象
  • of(int year, int month, int dayOfMonth, int hour, int minute):通过年月日时分秒创建时间日期类
  • of(int year, int month, int dayOfMonth, int hour, int minute, int second):通过年月日时分秒创建时间日期类
  • of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond):通过年月日时分秒纳秒创建时间日期类
  • of(int year, Month month, int dayOfMonth, int hour, int minute):通过年月日时分秒创建时间日期类,月份使用Month枚举类
  • of(LocalDate date, LocalTime time):通过LocalDate和LocalTime组合成时间日期对象
  • MAX:可表示的最大日期时间
  • MIN:可表示的最小日期时间

例:

public static void main(String[] args) {
             
             LocalDateTime localDateTime = LocalDateTime.now();
             
             System.out.println("当前日期时间:"+localDateTime);
             
             //日期和时间拼接
             LocalDateTime localDateTime1 = LocalDateTime.of(LocalDate.now(),  LocalTime.now());
             System.out.println("日期和时间整合:"+localDateTime1);
             
             //指定日期和时间
             LocalDateTime localDateTime2 =  LocalDateTime.of(2000,11,05,12,52,5);
             System.out.println("指定日期时间(年月日时分秒):"+localDateTime2);
             
             //最大日期时间
             LocalDateTime localDateTime3 = LocalDateTime.MAX;
             System.out.println("最大日期时间:"+localDateTime3);
             LocalDateTime localDateTime4 = LocalDateTime.MIN;
             System.out.println("最小日期时间:"+localDateTime4);
             
       }

输出:

当前日期时间:2023-08-05T00:24:54.817
日期和时间整合:2023-08-05T00:24:54.818
指定日期时间(年月日时分秒):2000-11-05T12:52:05
最大日期时间:+999999999-12-31T23:59:59.999999999
最小日期时间:-999999999-01-01T00:00

4.4.2说明

其他获取、计算、修改、判断和LocalDate和LocalTime差不多:

  • 获取:
    • toLocalDate():获取LocalDate部分
    • toLocalTime():获取LocalTime部分
    • 其他分量获取和LocalDate与LocalTime一样
  • 计算:使用minus进行减,plus进行加
    • minus():指定常量进行减操作
    • plus():指定常量进行加操作
    • ……
  • 修改:with等方法
  • 判断和上面两个一样

路漫漫其修远兮,吾将上下而求索