本篇主要介绍Java 8中新引入的全新的一套时间API。
Java 8之前的Date类的缺陷
- java.util包和java.sql包中都有一个Date类,区别是util包中的Date类存储的是年月日时分秒;而sql包中的Date只存储年月日。这本身就是一个不好的设计。
- Java8以前的一系列日期时间类数量较多且功能有重复,设计冗余。
- java.util.Date类有多个问题:首先它是可变类,意味着有线程安全问题;其次它没有提供国际化,没有时区支持;Date的格式化自己不能完成,需要依赖SimpleDateFormat类。
由于以上问题的存在,Java 8提供了一套全新的时间API,这些API都在java.time包中,本篇文章中我们仅介绍常用的几个类的API。
新日期API
LocalDate
LocalDate是不可变的日期对象,不包含具体时间和时区信息。以下是该类的常用方法,第一个方法创建了LocalDate对象,以后的方法都是用的该对象。
- public static LocalDate now():根据当前日期创建LocalDate对象
LocalDate date = LocalDate.now();
System.out.println("今天的日期是"+date.toString());
//返回结果
今天的日期是2020-09-18
- public int getDayOfMonth():返回月份中的第几天。
System.out.println("今天是这个月的第"+date.getDayOfMonth()+"天");
//返回结果
今天是这个月的第18天
- public int getDayOfYear():返回今天是这一年的第多少天。
System.out.println("今天是今年的第"+date.getDayOfYear()+"天");
//返回结果
今天是今年的第262天
- public Month getMonth():返回当前月份的英文大写表示。
System.out.println("这个月是"+date.getMonth());
//返回结果
这个月是SEPTEMBER
- public int getMonthValue():返回当前月份是该年的第多少个月。
System.out.println("这个月是今年的第"+date.getMonthValue()+"个月");
//返回结果
这个月是今年的第9个月
- public int getDayOfWeek():返回周几的英文大写表示。
System.out.println("今天是"+date.getDayOfWeek());
//返回结果
今天是FRIDAY
- public int getYear():返回年份。
System.out.println("今年是第"+date.getYear()+"年");
//返回结果
今年是第2020年
- public boolean isAfter(ChronoLocalDate other):检查当前日期是否晚于给定日期。
System.out.println("当前日期是否晚于给定日期:"+date.isAfter(LocalDate.of(2020,9,19)));
//返回结果
当前日期是否晚于给定日期:false
- public boolean isBefore(ChronoLocalDate other):检查当前日期是否早于给定日期。
System.out.println("当前日期是否早于给定日期:"+date.isBefore(LocalDate.of(2020,9,19)));
//返回结果
当前日期是否早于给定日期:true
- public boolean isEqual(ChronoLocalDate other):检查当前日期是否与给定日期相同。
System.out.println("当前日期是否早于给定日期:"+date.isEqual(LocalDate.of(2020,9,19)));
//返回结果
当前日期是否早于给定日期:false
- public boolean isLeapYear(long prolepticYear):检查当前年份是否是闰年。
System.out.println("当前年份是否是闰年:"+date.isLeapYear());
//返回结果
当前年份是否是闰年:true
- public int lengthOfMonth():返回当前月份的天数。
System.out.println("当前月份有"+date.lengthOfMonth()+"天");
//返回结果
当前月份有30天
- public int lengthOfYear():返回当前年份的天数。
System.out.println("当前年份有"+date.lengthOfYear()+"天");
//返回结果
当前年份有366天
- public String format(DateTimeFormatter formatter):按照给定的格式进行格式化并返回格式化后的日期字符串,入参为DateTimeFormatter的属性。
System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE));
//返回结果
20200918
- public LocalDate minus(long amountToSubtract, TemporalUnit unit):将当前日期减去给定单位的相应数量的时间并返回副本,第一个参数为单位数量,第二个参数为单位(ChronoUnit类的属性,此处不能为时分秒)。
System.out.println("当前日期的十天前的日期为:"+date.minus(10, ChronoUnit.DAYS));
//返回结果
当前日期的十天前的日期为:2020-09-08
- public LocalDate minusDays(long daysToSubtract):将当前日期减去指定的天数并返回副本。
System.out.println("当前日期的十天前的日期为:"+date.minusDays(10));
//返回结果
当前日期的十天前的日期为:2020-09-08
- public static LocalDate now(ZoneId zone):从指定时区的系统始终获取当前日期。
LocalDate zoneDate = LocalDate.now(ZoneId.of("America/Anchorage"));
System.out.println("从指定时区的系统始终获取当前日期:"+zoneDate.toString());
//返回结果
从指定时区的系统始终获取当前日期:2020-09-18
- public static LocalDate of(int year, Month month, int dayOfMonth):根据给定的年月日创建LocalDate对象。
LocalDate ofDate = LocalDate.of(2020,4,12);
System.out.println(ofDate.toString());
//输出结果
2020-04-12
- public static LocalDate ofYearDay(int year, int dayOfYear):根据给定的年和天数创建LocalDate对象。
LocalDate ofYearDate = LocalDate.ofYearDay(2020,263);
System.out.println(ofYearDate.toString());
//输出结果
2020-09-19
- public static LocalDate parse(CharSequence text):根据字符串创建LocalDate对象。
LocalDate parseDate = LocalDate.parse("2020-03-12");
System.out.println(parseDate.toString());
//输出结果
2020-03-12
- public LocalDate plus(long amountToAdd, TemporalUnit unit):将当前日期加上给定单位的相应数量的时间并返回副本,第一个参数为单位数量,第二个参数为单位(ChronoUnit类的属性,此处不能为时分秒)。
System.out.println("当前日期过十天后的日期为:"+date.plus(10,ChronoUnit.DAYS));
//输出结果
当前日期过十天后的日期为:2020-09-29
- public int get(TemporalField field):根据传参获取日期对应的值,传参是ChronoField的属性。
System.out.println("当前日期的年份为:"+date.get(ChronoField.YEAR));
System.out.println("当前日期为这个月的第"+date.get(ChronoField.DAY_OF_MONTH)+"天");
System.out.println("当前日期是这周的第"+date.get(ChronoField.DAY_OF_WEEK)+"天");
//输出结果
当前日期的年份为:2020
当前日期为这个月的第19天
当前日期是这周的6
- public LocalDate with(TemporalField field, long newValue):根据参数修改对应的值并返回副本,参数为ChronoField的属性,此处只能为DAYS,MONTHS,YEARS。
LocalDate anoDate = date.with(ChronoField.YEAR,2000);
System.out.println(anoDate.toString());
//输出结果
2000-09-19
LocalDateTime
LocalDateTime是不可变的日期时间对象,包含日期和时间,但不包含时区信息。LocalDateTime许多方法与LocalDate名称相同且用法相同,此处不再赘述,仅介绍独有方法。
- public int getHour():获得时间中的小时数。类似方法还有getMonth(),getMinute()等。
LocalDateTime dateTime = LocalDateTime.now();
System.out.println("当前时间为:"+dateTime.format(DateTimeFormatter.ISO_DATE_TIME));
System.out.println("当前小时为:"+dateTime.getHour());
//输出结果
当前时间为:2020-09-19T20:29:29.465
当前小时为:20
- public int get(TemporalField field):根据参数获取日期时间中的值,参数为ChronoField的属性。
System.out.println("当前分钟数为"+dateTime.get(ChronoField.MINUTE_OF_HOUR));
//输出结果
当前分钟数为35
- public LocalDate toLocalDate():获取此LocalDateTime的日期部分并创建LocalDate对象返回。
System.out.println("当前日期时间的日期部分为:"+dateTime.toLocalDate().toString());
//输出结果
当前日期时间的日期部分为:2020-09-19
- public LocalTime toLocalTime():获取此LocalDateTime的时间部分并创建LocalTime对象返回。
System.out.println("当前日期时间的时间部分为:"+dateTime.toLocalTime().toString());
//输出结果
当前日期时间的时间部分为:20:40:19.735
LocalTime
LocalTime是不可变的时间对象,不包含日期和时区信息。LocalTime的许多方法与LocalDate名称相同且用法相同,此处不再赘述,仅介绍其独有方法。
- public LocalDateTime atDate(LocalDate date):此LocalTime对象与给定的LocalDate对象组合返回一个LocalDateTime对象。
LocalTime time = LocalTime.now();
System.out.println("当前时间为:"+time.toString());
LocalDateTime ldt = time.atDate(LocalDate.now());
System.out.println("当前日期时间为:"+ldt.toString());
//输出结果
当前时间为:20:47:12.399
当前日期时间为:2020-09-19T20:47:12.399
Duration
Duration是不可变的时间差对象,它仅可以计算LocalTime或LocalDateTime对象的时间差。其使用方法如下:
LocalTime time1 = LocalTime.now();
LocalTime time2 = LocalTime.of(21,10,00);
Duration durationTime = Duration.between(time1,time2);
System.out.println("两个LocalTime对象的时间差为:"+durationTime.toString());
LocalDateTime ldt1 = LocalDateTime.now();
LocalDateTime ldt2 = LocalDateTime.of(2020,9,19,21,10);
Duration durationDT = Duration.between(ldt1,ldt2);
System.out.println("两个LocalDateTime对象的时间差为:"+durationDT.toString());
//输出结果
两个LocalTime对象的时间差为:PT1M21.283S
两个LocalDateTime对象的时间差为:PT1M21.223S
Duration类同样有许多方法与LocalDate类用法相同,这里我们仅介绍其独有方法。
- public Duration abs():返回此Duration对象的正值的副本。
System.out.println(durationDT.abs());
//输出结果
PT26H38M2.033S
- public static Duration between(Temporal startInclusive, Temporal endExclusive):计算两个时间的时间间隔并创建Duration对象返回。此方法上面演示过,不贴测试代码了。
- public boolean isNegative()/public boolean isZero():判断此时间间隔是否是负数或零。
System.out.println("此时间间隔是否是负数:"+durationDT.isNegative());
System.out.println("此时间间隔是否为0:"+durationDT.isZero());
//输出结果
此时间间隔是否是负数:false
此时间间隔是否为0:false
Period
Period是不可变的日期差对象,它仅可以计算LocalDate对象的日期差。它的使用方法如下:
LocalDate date1 = LocalDate.now();
LocalDate date2 = LocalDate.of(2020,11,1);
Period period = Period.between(date1,date2);
System.out.println("两个LocalDate对象的日期差为:"+period.toString());
//输出结果
两个LocalDate对象的日期差为:P1M13D
ZonedDateTime
ZonedDateTime是不可变的存储了时区信息的日期时间对象。该对象同样与LocalDate拥有许多类似的方法,仅介绍其独有方法。
- public ZoneId getZone():获取时区id。
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println(zdt.toString());
System.out.println("时区id为:"+zdt.getZone());
//输出结果
2020-09-19T21:40:45.505+08:00[GMT+08:00]
时区id为:GMT+08:00
- public ZoneOffset getOffset():获取区域偏移量。
System.out.println(zdt.getOffset());
//输出结果
+08:00
ZoneId
ZoneId表示一个时区id。其常用方法如下:
public static ZoneId systemDefault():获取系统默认时区id。
ZoneId zoneId = ZoneId.systemDefault();
System.out.println("系统默认时区id为:"+zoneId.toString());
//输出结果
系统默认时区id为:GMT+08:00