概述
Java8引入了新的日期和时间API,修正了之前日期和时间的缺陷和BUG。
1 新的日期和时间API
1.1 LocalDate
LocalDate显示日期,不包含时间,是一个不可变的对象。打印出来的日期也简洁易懂:
// 2020-03-18
LocalDate date = LocalDate.of(2020,3,18);
// 2020
int year = date.getYear();
// MARCH
Month month = date.getMonth();
// 18
int day = date.getDayOfMonth();
// WEDNESDAY
DayOfWeek dow = date.getDayOfWeek();
// 31
int monthLen = date.lengthOfMonth();
// true
boolean leap = date.isLeapYear();
// 获取系统的当前日期
LocalDate today = LocalDate.now();
// 解析字符串
LocalDate dateParse = LocalDate.parse("2020-03-20");
日期类的操作基本都提供了类似的工厂方法。
通过TemporalField(我译为:时域)参数获取年月日:
LocalDate date = LocalDate.of(2020,3,18);
// ChronoField实现TemporalField接口
// 2020
int year = date.get(ChronoField.YEAR);
// 3
int month = date.get(ChronoField.MONTH_OF_YEAR);
// 18
int day = date.get(ChronoField.DAY_OF_MONTH);
1.2 LocalTime
LocalTime是用来表示时间的类。
// 14:45:45
LocalTime time = LocalTime.of(14,45,45);
// 14
int hour = time.getHour();
// 45
int minute = time.getMinute();
// 45
int second = time.getSecond();
// 解析字符串
LocalTime time1 = LocalTime.parse("14:40:40");
1.3 LocalDateTime
LocalDateTime表示是,年月日时分秒的时间格式(yyyyMMddHHmmss)。
下面介绍几种创建的方式:
// 2014-03-18T13:45:20
LocalDateTime dat1 = LocalDateTime.of(2014, Month.MARCH,18,13,45,20);
LocalDate date = LocalDate.of(2020,9,10);
LocalTime time = LocalTime.of(14,20,20);
// 2020-09-10T14:20:20
LocalDateTime dat2 = LocalDateTime.of(date,time);
// 2020-09-10T13:45:20 通过atTime向LocalDate传递一个时间对象
LocalDateTime dat3 = date.atTime(13,45,20);
// 2020-09-10T14:20:20 通过atTime向LocalDate传递一个时间对象
LocalDateTime dat4 = date.atTime(time);
// 2020-09-10T14:20:20 通过atDate向LocalTime传递一个日期对象
LocalDateTime dat5 = time.atDate(date);
// 2014-03-18 LocalDateTime对象通过toLocalDate()方法,获取日期
LocalDate datel = dat1.toLocalDate();
// 13:45:20 LocalDateTime对象通过toLocalTime()方法,获取时间
LocalTime timel = dat1.toLocalTime();
1.4 Instant
Instant类是以Unix元年时间(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的秒数进行计算的。
// 1970-01-01T00:00:03Z
Instant instant = Instant.ofEpochSecond(3);
// 1970-01-01T00:00:03Z 第二个参数是以纳秒为单位的
Instant instant1 = Instant.ofEpochSecond(3,0);
// 1970-01-01T00:00:04Z
Instant instant2 = Instant.ofEpochSecond(3,1_000_000_000);
// 1970-01-01T00:00:03Z
Instant instant3 = Instant.ofEpochSecond(4,-1_000_000_000);
Instant的设计是为了便于计算机的理解和使用。它包含的是由秒及纳秒所构成的数字。所以它无法通过ChronoField中的枚举值来获得日期和时间。
LocalDateTime,LocalDate,LocalTime和Instant是为不同的目的而设计的,一个是为了便于人阅读使用,另一个是为了便于机器处理,不能将两者混合使用。
1.5 Duration
Duration类主要用于以秒和纳秒衡量时间的长短,不能向between方法中传递一个LocalDate对象做参数。
LocalTime time1 = LocalTime.of(12,45,45);
LocalTime time2 = LocalTime.of(12,45,46);
// PT1S
Duration d1 = Duration.between(time1,time2);
LocalDateTime dt1 = LocalDateTime.of(2020,12,12,12,12,12);
LocalDateTime dt2 = LocalDateTime.of(2014,11,11,11,11,11);
// PT-53353H-1M-1S
Duration d2 = Duration.between(dt1,dt2);
Instant instant1 = Instant.ofEpochSecond(3);
Instant instant2 = Instant.ofEpochSecond(4);
// PT1S
Duration d3 = Duration.between(instant1,instant2);
// Exception
LocalDate date1 = LocalDate.of(2020,12,23);
LocalDate date2 = LocalDate.of(2020,12,13);
Duration d4 = Duration.between(date1,date2);
// PT3M 用方便的工厂类来创建对应的实例
Duration threeMinutes1 = Duration.ofMinutes(3);
// PT3M
Duration threeMinutes2 = Duration.of(3, ChronoUnit.MINUTES);
1.6 Period
在我们需要以年、月或者日的方式对多个时间单位建模时,使用Period类。
LocalDate date1 = LocalDate.of(2020,12,23);
LocalDate date2 = LocalDate.of(2020,12,13);
// P-10D
Period p1 = Period.between(date1,date2);
// P10D 用方便的工厂类来创建对应的实例
Period p2 = Period.ofDays(10);
// P21D
Period p3 = Period.ofWeeks(3);
// P2Y6M1D
Period p4 = Period.of(2,6,1);
日期-时间类中表示时间间隔的通用方法
方法名 | 是否是静态方法 | 方法描述 |
---|---|---|
between | 是 | 创建两个时间点之间的interval(间隔) |
from | 是 | 由一个临时时间点创建interval |
of | 是 | 由它的组成部分创建interval的实例 |
parse | 是 | 由字符串创建interval的实例 |
addTo | 否 | 创建interval的副本,并将其叠加到某个指定的temporal对象 |
get | 否 | 读取该interval的状态 |
isNegative | 否 | 检查该interval是否为负值,不包含零 |
isZero | 否 | 检查该interval的时长是否为零 |
minus | 否 | 通过减去一定的时间创建该interval的副本 |
multipliedBy | 否 | 将interval的值乘以某个标量创建该interval的副本 |
negated | 否 | 以忽略某个时长的方式创建该interval的副本 |
plus | 否 | 以增加某个指定的时长的方式创建该interval的副本 |
subtractFrom | 否 | 从指定的temporal对象中减去该interval |
2 日期的解析和格式化
2.1 以比较直观的方式操纵LocalDate对象属性
// 2020-03-18
LocalDate date1 = LocalDate.of(2020,3,18);
// 2019-03-18
LocalDate date2 = date1.withYear(2019);
// 2019-03-25
LocalDate date3 = date2.withDayOfMonth(25);
// 2019-09-25
LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR,9);
// DateTimeFormatter进行日期的格式化操作
LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dtf.format(dateTime));
2.2 以相对方式修改LocalDate对象属性
// 2014-03-18
LocalDate date1 = LocalDate.of(2014, 3, 18);
// 2014-03-25
LocalDate date2 = date1.plusWeeks(1);
// 2011-03-25
LocalDate date3 = date2.minusYears(3);
// 2011-09-25
LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS);
2.3 表示时间点的日期-时间类的通用方法
方法名 | 是否是静态方法 | 描述 |
---|---|---|
from | 是 | 依据传入的Temporal对象创建实例 |
now | 是 | 依据系统时钟创建Temporal对象 |
of | 是 | 由Temporal对象的某个部分创建该对象的实例 |
parse | 是 | 由字符串创建Temporal对象的实例 |
atOffset | 否 | 将Temporal对象和某个时区偏移相结合 |
atZone | 否 | 将Temporal对象和某个时区相结合 |
format | 否 | 使用某个指定的格式器将Temporal对象转换为字符串(Instunt类不提供该方法) |
get | 否 | 读取Temporal对象的某一部分的值 |
minus | 否 | 创建Temporal对象的一个副本,通过将当前Temporal对象的值减去一定的时长创建该副本 |
plus | 否 | 创建Temporal对象的一个副本,通过将当前Temporal对象的值加上一定的时长创建该副本 |
with | 否 | 以该Temporal对象为模版,对某些状态进行修改创建该对象的副本 |
2.4 TemporalAdjuster(时间调整器)
TemporalAdjuster预定义的方法:
// 2014-03-18
LocalDate date1 = LocalDate.of(2014,3,18);
// 2014-03-23
LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY));
// 2014-03-31
LocalDate date3 = date2.with(lastDayOfMonth());
// 2014-03-07
LocalDate date4 = date3.with(firstInMonth(DayOfWeek.FRIDAY));
2.5 TemporalAdjuster类中的工厂方法
方法名 | 描述 |
---|---|
dayOfWeekInMonth | 创建一个新的日期,它的值为同一个月中每一周的第几天 |
firstDayOfMonth | 创建一个新的日期,它的值为当月的第一天 |
firstDayOfNextMonth | 创建一个新的日期,它的值为下月的第一天 |
firstDayOfNextYear | 创建一个新的日期,它的值为明年的第一天 |
firstDayOfYear | 创建一个新的日期,它的值为当年的第一天 |
firstInMonth | 创建一个新的日期,它的值为同一个月中,第一个符合星期几要求的值 |
lastDayOfMonth | 创建一个新的日期,它的值为当月的最后一天 |
lastDayOfNextMonth | 创建一个新的日期,它的值为下月的最后一天 |
lastDayOfNextYear | 创建一个新的日期,它的值为明年的最后一天 |
lastDayOfYear | 创建一个新的日期,它的值为今年的最后一天 |
lastInMonth | 创建一个新的日期,它的值为同一个月中,最后一个符合星期几要求的值 |
next/previous | 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期 |
nextOrSame/previousOrSame | 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期,如果该日期已经符合要求,直接返回该对象 |
2.6 TemporalAdjuster类的自定义方法
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.*;
public class NextWorkingDay implements TemporalAdjuster {
@Override
public Temporal adjustInto(Temporal temporal) {
DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
int dayToAdd = 1;
if (dow == DayOfWeek.FRIDAY) {
dayToAdd = 3;
} else if (dow == DayOfWeek.SATURDAY) {
dayToAdd = 2;
}
return temporal.plus(dayToAdd, ChronoUnit.DAYS);
}
public static void main(String[] args) {
TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(temporal->{
DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
int dayToAdd = 1;
if (dow == DayOfWeek.FRIDAY) {
dayToAdd = 3;
} else if (dow == DayOfWeek.SATURDAY) {
dayToAdd = 2;
}
return temporal.plus(dayToAdd, ChronoUnit.DAYS);
});
LocalDate date = LocalDate.now();
date = date.with(nextWorkingDay);
System.out.println(date);
LocalDate date1 = LocalDate.of(2014,3,18);
System.out.println(date1);
String s1 = date1.format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(s1);
String s2 = date1.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(s2);
}
}
2.7 打印输出及解析日期-时间对象
// 2014-03-18
LocalDate date1 = LocalDate.of(2014,3,18);
// 18/03/2014
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String formattedDate = date1.format(formatter);
// 2014-03-18
LocalDate date2 = LocalDate.parse(formattedDate,formatter);
// 自定义格式化
DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder().appendText(ChronoField.DAY_OF_MONTH)
.appendLiteral(".")
.appendText(ChronoField.MONTH_OF_YEAR)
.appendLiteral(" ")
.appendText(ChronoField.YEAR)
.parseCaseInsensitive()
.toFormatter(Locale.ITALIAN);
System.out.println(italianFormatter);
LocalDate date = LocalDate.now();
String s = date.format(italianFormatter);
System.out.println(s);
3 时区的处理
时区的处理是Java8新版日期和时间API新增加的重要功能,使用起来也是非常的简单上手。
// Europe/Rome
ZoneId romeZone = ZoneId.of("Europe/Rome");
// Asia/Shanghai
ZoneId zoneId = TimeZone.getDefault().toZoneId();
LocalDate date = LocalDate.of(2014, Month.MARCH, 18);
// 2014-03-18T00:00+01:00[Europe/Rome]
ZonedDateTime zdt1 = date.atStartOfDay(romeZone);
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
// 2014-03-18T13:45+01:00[Europe/Rome]
ZonedDateTime zdt2 = dateTime.atZone(romeZone);
Instant instant = Instant.now();
// 2020-09-10T14:24:15.356+02:00[Europe/Rome]
ZonedDateTime zdt3 = instant.atZone(romeZone);
// LocalDateTime转换为Instant
LocalDateTime dateTime2 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
// 2014-03-19T07:45:00Z
Instant instantFromDateTime = dateTime2.toInstant(ZoneOffset.MIN);
// LocalDateTime
Instant instant2 = Instant.now();
// 2020-09-10T14:24:15.363
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant2, romeZone);
3.1 ZoneDateTime理解
在Java8中,我们可以相对于某个地区/位置的方式,或者以与UTC/格林尼治时间的绝对偏差的方式表示时区,并将其应用到日期-时间对象上,对其进行本地化。
可以使用各种各样的日历系统。
最后
以上就是无私画笔为你收集整理的Java8中新的日期和时间API的全部内容,希望文章能够帮你解决Java8中新的日期和时间API所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复