第八章:新的日期和时间API

时间:2023-02-10 13:27:42

8.1 LocalDate,LocalTime,Instant,Duration 以及 Period

8.1.1 使用 LocalDate 和 LocalTime

  创建一个LocalDate对象并读取它的值

LocalDate localDate = LocalDate.of(2018, 06, 17);
int year = localDate.getYear();
Month month = localDate.getMonth();
int dayOfMonth = localDate.getDayOfMonth();
DayOfWeek dayOfWeek = localDate.getDayOfWeek();
int lengthOfMonth = localDate.lengthOfMonth();
boolean leapYear = localDate.isLeapYear();
System.out.println("year:" + year + ", month:" + month + ", dayOfMonth:" + 
                   dayOfMonth + ", dayOfWeek:" + dayOfWeek + ", lengthOfMonth:" + 
                   lengthOfMonth + ", leapYear:" + leapYear);

  你还可以使用工厂方法从系统中获取当前的日期

LocalDate now = LocalDate.now();

  通过传递一个TemporalField参数给get方法拿到同样的信息。TemporalField是一个接口,它定义了如何访问TemporalField对象某个字段的值。ChronoField枚举实现了这一个接口,你可以使用get方法获取枚举元素的值

year = localDate.get(ChronoField.YEAR);
int monthVal = localDate.get(ChronoField.MONTH_OF_YEAR);
int day = localDate.get(ChronoField.DAY_OF_MONTH);
System.out.println(year + "-" + String.format("%02d", monthVal) + "-" + day);

  创建LocalTime并读取它的值

LocalTime localTime = LocalTime.of(10, 24, 30);
int hour = localTime.getHour();
int minute = localTime.getMinute();
int second = localTime.getSecond();
System.out.println(hour + ":" + minute + ":" + second);

  LocalDate和LocalTime都可以通过解析代表它们的字符串创建。使用静态方法parse

LocalDate parseDate = LocalDate.parse("2018-06-17");
LocalTime parseTime = LocalTime.parse("10:24:30");

8.1.2 合并日期和时间

  这个复合类名叫LocalDateTime,是LocalDate和LocalTIme的结合体,它同时表示了日期和时间

LocalDateTime dt1 = LocalDateTime.of(2018, 6, 17, 10, 24, 30);
LocalDateTime dt2 = LocalDateTime.of(parseDate, parseTime);
LocalDateTime dt3 = parseDate.atTime(parseTime);
LocalDateTime dt4 = parseDate.atTime(10, 24, 30);
LocalDateTime dt5 = parseTime.atDate(parseDate);

  时间比较

LocalDateTime dt1 = LocalDateTime.of(2018, 6, 17, 10, 24, 29);
LocalDateTime dt2 = LocalDateTime.of(2018, 6, 17, 10, 24, 30);
int compareTo = dt1.compareTo(dt2);

  从LocalDateTime中提取LocalDate和LocalTime

LocalDateTime ldt = LocalDateTime.of(2018, 6, 17, 10, 24, 30);
LocalDate ld = ldt.toLocalDate();
LocalTime lt = ldt.toLocalTime();

8.1.3 定义Duration和Period

  Duration类主要用于以秒和纳秒衡量时间的长短,Period用于年、月或日的方式对多个时间单位进行建模

// Duration
Duration duration = Duration.between(LocalDateTime.of(2018, 5, 17, 10, 23, 30), 
                                     LocalDateTime.of(2018, 6, 17, 10, 24, 29));
System.out.println(duration.getSeconds());
System.out.println(duration.toMillis());
// Period
Period period = Period.between(LocalDate.of(2018, 5, 16), 
                               LocalDate.of(2018, 6, 16));
System.out.println(period.getDays());
System.out.println(period.getMonths());

8.2 操纵、解析和格式化日期

8.2.1 操纵时间

LocalDate ld1 = LocalDate.of(2018, 6, 17);
LocalDate ld2 = ld1.withYear(2019);
LocalDate ld3 = ld2.with(ChronoField.MONTH_OF_YEAR, 8);
LocalDate ld4 = ld3.withDayOfMonth(18);
LocalDate _ld1 = LocalDate.of(2018, 6, 17);
LocalDate _ld2 = _ld1.plusYears(1);
LocalDate _ld3 = _ld2.minus(-2, ChronoUnit.MONTHS);
LocalDate _ld4 = _ld3.plusWeeks(1);

8.2.2 使用TemporalAdjusters

import static java.time.temporal.TemporalAdjusters.*;

LocalDate $ld = LocalDate.of(2018, 6, 17);
LocalDate $ld1 = $ld.with(nextOrSame(DayOfWeek.SUNDAY));
LocalDate $ld2 = $ld.with(lastDayOfMonth());

  TemporalAdjusters类中的方法

方法名 描述    
dayOfWeekInMonth 创建一个新的日期,它的值为同一个月中每一周的第几天
firstDayOfMonth 创建一个新的日期,它的值为当月的第一天
firstDayOfNextMonth 创建一个新的日期,它的值为下月的第一天
firstDayOfNextYear 创建一个新的日期,它的值为明年的第一天
firstDayOfYear 创建一个新的日期,它的值为当年的第一天
firstInMonth 创建一个新的日期,它的值为同一个月中第一个符合星期几要求的值
firstDayOfMonth 创建一个新的日期,它的值为当月的最后一天
firstDayOfNextMonth 创建一个新的日期,它的值为下月的最后一天
firstDayOfNextYear 创建一个新的日期,它的值为明年的最后一天
lastDayOfYear 创建一个新的日期,它的值为今年的最后一天
lastInMonth 创建一个新的日期,它的值为同一个月中最后一个符合星期几要求的值
next/previous 创建一个新的日期,并将其值设定为日期调整后或调整前,第一个符合指定星期几要去的日期
nextOrSame/previousOrSame 创建一个新的日期,并将其值设定为日期调整后或调整前,第一个符合指定星期几要去的日期,如果该日期已经符合要求,直接返回该对象

 

 

 

 

 

 

 

 

 

 

 

 

 

 

使用TemporalAdjusters.ofDateAdjuster方法

练习:实现当天的下一个工作日日期,周六周日排除

分析

  当天为周一至周四、周日,则当天加1天即可

  当天为周五,则当天加3天即可

  当天为周六,则当天加2天即可

实现

// 实现当天的下一个工作日日期,周六周日排除
TemporalAdjuster ofDateAdjuster = TemporalAdjusters.ofDateAdjuster(date -> {
    // 获取当天是星期几
    int weekDay = date.get(ChronoField.DAY_OF_WEEK);
    // 定义增加天数的变量
    int addDays = 1;
    if(weekDay == 5) {
        addDays = 3;
    } else if(weekDay == 6) {
        addDays = 2;
    }
    return date.plus(addDays, ChronoUnit.DAYS);
});
LocalDate testDay = LocalDate.of(2018, 6, 15);
LocalDate nextWorkingDay = testDay.with(ofDateAdjuster);

8.2.3 解析和格式化日期

DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localNow = LocalDateTime.now();
String formatTime = localNow.format(timeFormatter);
LocalDateTime parseLocalTime = LocalDateTime.parse(formatTime, timeFormatter);

自定义DateTimeFormatter(yyyy年MM月dd日   HH时mm分ss秒)

// 自定义DateTimeFormatter
DateTimeFormatter myDateFormat = new DateTimeFormatterBuilder()
                                         .appendText(ChronoField.YEAR)
                                         .appendLiteral("年")
                                         .appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW)
                                         .appendLiteral("月")
                                         .appendText(ChronoField.DAY_OF_MONTH)
                                         .appendLiteral("日   ")
                                         .appendText(ChronoField.HOUR_OF_DAY)
                                         .appendLiteral("时")
                                         .appendText(ChronoField.MINUTE_OF_HOUR)
                                         .appendLiteral("分")
                                         .appendText(ChronoField.SECOND_OF_MINUTE)
                                         .appendLiteral("秒")
                                         .toFormatter();
String format = LocalDateTime.now().format(myDateFormat);

 

 

备注:

摘自文献:《Java8实战》(中文版)《Java8 in Action》(英文版)

 

代码(GitHub地址): https://github.com/changlezhong/java8InAction