Java8中新的日期和时间API

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/格林尼治时间的绝对偏差的方式表示时区,并将其应用到日期-时间对象上,对其进行本地化。

可以使用各种各样的日历系统。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值