JAVA8 日期和时间(LocalDate、LocalDateTime、ZoneId、Duration、Period、Instant)API 用法详解 文章目录一、LocalDate、LocalTime、Instant、Duration、Period1、LocalDate和LocalTimea、LocalDateb、LocalTime2、合并时间和日期3、机器日期和时间格式4、定义Duration 和Period二、操纵、解析和格式化日期1、使用TemporalAdjuster2、打印输出及解析日期a、格式化和解析日期java8提供了线程安全DateTimeFormatter类创建格式化器最简单的方法时通过它的静态工厂方法及常量。b、按照某个模式创建DateTimeFormatterc、创建本地化的DateTimeFormatter三、处理不同时区前言java8之前我们创建时间new Date或者使用Calendar很不幸这些类设计的有缺陷导致使用这些方法写出的代码很容易出错。DateFormat是一个线程不安全的类在多线程使用会有意想不到的结果出现。在java8中整合了很多Joda-Time的特性。一、LocalDate、LocalTime、Instant、Duration、Period如果创建简单的时间和日期。java.time包提供了很多新类帮你解决问题分别是LocalDate、LocalTime、Instant、Duration、Period实现的接口都是TemporalAccessor这些类都是final类型的都不能修改。1、LocalDate和LocalTime可以通过of的静态方法创建LocalDate和LocalTime实例。a、LocalDateLocalDate date LocalDate.of(2019, 9, 1); int year date.getYear(); Month month date.getMonth(); int day date.getDayOfMonth(); DayOfWeek dow date.getDayOfWeek(); int len date.lengthOfMonth(); boolean leap date.isLeapYear();还可以通过工厂方法系统日期获取当前日期LocalDate today LocalDate.now();还可以传递一个TemporalField参数给get方法也可以拿到同样的信息。TemporalField是一个接口ChronoField实现了这一接口。int year date.get(ChronoField.YEAR); int month date.get(ChronoField.MONTH_OF_YEAR); int day date.get(ChronoField.DAY_OF_MONTH);b、LocalTime创建LocalTime也可以使用of静态方法LocalTime time LocalTime.of(15, 30, 20); int hour time.getHour(); int minute time.getMinute(); int second time.getSecond();LocalDate和LocalTime都可以使用parse方法将字符串解析为LocalDate或LocalTimeLocalDate date LocalDate.parse(2019-09-01); LocalTime time LocalTime.parse(15:30:20);2、合并时间和日期LocalDateTime是LocalDate和LocalTime的合体。它同时表示了日期和时间但不带有时区信息。可以使用atTime或atDate创建LocalDateTimeLocalDateTime dt1 LocalDateTime.of(2019, 9, 1, 15, 45, 20); LocalDate date LocalDate.now(); LocalTime date1 LocalTime.now(); LocalDateTime dt3 date.atTime(15, 45, 20); LocalDateTime dt5 date1.atDate(date);也可以使用toLocalDate或toLocalTime从LocalDateTime提取LocalDate或LocalTime。LocalDate date1 dt1.toLocalDate(); LocalTime time1 dt1.toLocalTime();3、机器日期和时间格式今天是某年某月某日等等作为人我们可以看懂但是作为机器是看不懂的。从机器角度看建模时间最自然的格式是表示一个持续时间段上某个点的单一大整型数。这也是java.time.Instant类对时间建模的方式。基本上是以Unix元年时间(1970年1月1日)开始所经历秒数计算的。可以使用静态工厂方式创建该实例Instant instant Instant.ofEpochSecond(3); Instant.ofEpochSecond(3,-1000000);//三秒之前的100w纳秒(1秒) Instant.ofEpochSecond(3,1000000);//三秒之后的100w纳秒(1秒)4、定义Duration 和Period需要创建Temporal对象之间的Duration (间隔)Duration 类的静态工厂方法between就是为了这个目的设计的。Duration d1 Duration.between(time1, time2); Duration d1 Duration.between(dateTime1, dateTime2); Duration d2 Duration.between(instant1, instant2)如果是需要以年月日的方式对多个时间建模可以使用Period类。该类也有between方法。Period tenDays Period.between(LocalDate.of(2019, 3, 8), LocalDate.of(2019, 9, 1));Duration 和Period提供了很多静态方法可以直接创建对应的实例。Duration threeMinutes Duration.ofMinutes(3); Duration threeMinutes Duration.of(3, ChronoUnit.MINUTES); Period tenDays Period.ofDays(10); Period threeWeeks Period.ofWeeks(3); Period twoYearsSixMonthsOneDay Period.of(2, 6, 1);二、操纵、解析和格式化日期如果已经有了一个LocalDate对象想要创建它的修改版本最直接的方法使用withxxx()方法。withxxx()会创建一个对象的副本。LocalDate date1 LocalDate.of(2019, 1, 1); LocalDate date2 date1.withYear(2011); LocalDate date3 date2.withDayOfMonth(25); LocalDate date4 date3.with(ChronoField.MONTH_OF_YEAR, 9);还可以加上或者减去一段时间LocalDate date1 LocalDate.of(2019, 9, 1); LocalDate date2 date1.plusWeeks(1); LocalDate date3 date2.minusYears(3); LocalDate date4 date3.plus(6, ChronoUnit.MONTHS);LocalDate、LocalTime、LocalDateTIme、Instant都有大量的通用方法1、使用TemporalAdjuster截止目前看到的日期比较都是相对比较直接的有时候需要更加复杂的操作。比如将日期调整到下个周日、下个工作日等。可以使用with的重载版本向其传递一个更多定制化的TemporalAdjuster对象。LocalDate date1 LocalDate.of(2019, 9, 1); LocalDate date2 date1.with(nextOrSame(DayOfWeek.SUNDAY)); LocalDate date3 date2.with(lastDayOfMonth());TemporalAdjuster的工厂方法列表如果没有符合你要求的预定义TemporalAdjuster你可以创建自己的TemporalAdjuster//函数式接口 FunctionalInterface public interface TemporalAdjuster { Temporal adjustInto(Temporal 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); } }由于TemporalAdjuster是一个函数式接口你能以lambda方式想该adjuster接口传递行为date date.with(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); });如果你使用lambda方式定义TemporalAdjuster对象推荐使用TemporalAdjusters的ofDateAdjuster方法TemporalAdjuster nextWorkingDay TemporalAdjusters.ofDateAdjuster( temporal - { DayOfWeek dow DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK)); int dayToAdd 1; if (dow DayOfWeek.FRIDAY) dayToAdd 3; if (dow DayOfWeek.SATURDAY) dayToAdd 2; return temporal.plus(dayToAdd, ChronoUnit.DAYS); }); date date.with(nextWorkingDay);2、打印输出及解析日期a、格式化和解析日期java8提供了线程安全DateTimeFormatter类创建格式化器最简单的方法时通过它的静态工厂方法及常量。下面例子生成不同格式的字符串LocalDate date LocalDate.of(2019, 9, 1); String s1 date.format(DateTimeFormatter.BASIC_ISO_DATE);//20190901 String s2 date.format(DateTimeFormatter.ISO_LOCAL_DATE);//2019-09-01可以用prase方法解析字符串LocalDate date1 LocalDate.parse(20190901, DateTimeFormatter.BASIC_ISO_DATE); LocalDate date2 LocalDate.parse(2019-09-01, DateTimeFormatter.ISO_LOCAL_DATE);b、按照某个模式创建DateTimeFormatterDateTimeFormatter formatter DateTimeFormatter.ofPattern(dd/MM/yyyy); LocalDate date1 LocalDate.of(2019, 9, 1); String formattedDate date1.format(formatter); LocalDate date2 LocalDate.parse(formattedDate, formatter);c、创建本地化的DateTimeFormatterDateTimeFormatter italianFormatter DateTimeFormatter.ofPattern(d. MMMM yyyy, Locale.ITALIAN); LocalDate date1 LocalDate.of(2019, 3, 1); String formattedDate date.format(italianFormatter); // 1. marzo 2019 LocalDate date2 LocalDate.parse(formattedDate, italianFormatter);三、处理不同时区时区的处理是新版日期和时间API新增的功能。新的java.time.ZoneId替代了老版的java.util.TimeZone。例ZoneId romeZone ZoneId.of(Europe/Rome);//区域/城市toZoneId可以将老时区对象转换为ZoneIdZoneId zoneId TimeZone.getDefault().toZoneId();为时间点添加区域LocalDate date LocalDate.of(2014, Month.MARCH, 18); ZonedDateTime zdt1 date.atStartOfDay(romeZone); LocalDateTime dateTime LocalDateTime.of(2014, Month.MARCH, 18, 13, 45); ZonedDateTime zdt2 dateTime.atZone(romeZone); Instant instant Instant.now(); ZonedDateTime zdt3 instant.atZone(romeZone);下面这张图可以更好的让我我们理解LocalDate、LocalTime、LocalDateTime、ZonedDateTime通过ZoneId可以将LocalDateTime转换为InstantLocalDateTime dateTime LocalDateTime.of(2014, Month.MARCH, 18, 13, 45); Instant instantFromDateTime dateTime.toInstant(romeZone);反之也可以转换为LocalDateTimeInstant instant Instant.now(); LocalDateTime timeFromInstant LocalDateTime.ofInstant(instant, romeZone);LocalDateTime和Date转换实例public static void dateToCoverLocadate() { Date date new Date(); Instant instant date.toInstant(); ZoneId zoneId ZoneId.systemDefault(); LocalDateTime localDateTime LocalDateTime.ofInstant(instant, zoneId); System.out.println(localDateTime); } public static void LocaldateToCoverDate() { LocalDateTime now LocalDateTime.now(); ZoneId zoneId ZoneId.systemDefault(); Instant instant now.atZone(zoneId).toInstant(); Date from Date.from(instant); System.out.println(from); }