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