Java 8之前的库对日期和时间的支持并不理想,为了解决这个问题,Java 8引入了一套全新的时间日期API,位于java.time路径下。
LocalDate类型包含了年月日信息,下面举些LocalDate的使用示例:
LocalDate date = LocalDate.of(2018, 4, 20); // 2018-04-20 int year = date.getYear(); // 2018 int month = date.getMonth().getValue(); // 4 int day = date.getDayOfMonth(); // 20 // 查看该月有多少天 int days = date.lengthOfMonth(); // 30 // 是否是闰年 boolean isLeap = date.isLeapYear(); // false 复制代码
可以使用LocalDate.now()获取当天的日期信息:
// 查看当天 年月日 LocalDate today = LocalDate.now(); // 2018-04-20 复制代码
除了调用LocalDate的getYear方法外,我们也可以使用ChronoField枚举类型来实现相同的功能:
int year1 = date.get(ChronoField.YEAR); // 2018 int month1 = date.get(ChronoField.MONTH_OF_YEAR); // 4 int day1 = date.get(ChronoField.DAY_OF_MONTH); // 20 // 当前日期属于该月第几周 int weekOfMonth = date.get(ChronoField.ALIGNED_WEEK_OF_MONTH); // 3 复制代码
ChronoField枚举类型包含了诸多的属性可供选择:
我们也可以修改LocalDate对象:
LocalDate date3 = LocalDate.of(2018, 4, 20); // 2018-04-20 LocalDate date4 = date3.withDayOfMonth(22); // 2018-04-22 LocalDate date5 = date3.with(ChronoField.DAY_OF_MONTH, 22); // 2018-04-22 LocalDate date6 = date3.withYear(2019); // 2019-04-20 LocalDate date7 = date3.plusDays(5); // 2018-04-25 LocalDate date8 = date3.plus(5, ChronoUnit.DAYS); // 2018-04-25 LocalDate date9 = date3.minusYears(10); // 2008-04-20 复制代码
TemporalAdjusters类提供了许多静态方法来修改LocalDate对象。当我们需要获取下一个周天,下一个工作日,本月的最后一天等信息时,TemporalAdjusters类便可派上用场:
import static java.time.temporal.TemporalAdjusters.*; LocalDate date10 = date3.with(nextOrSame(DayOfWeek.MONDAY)); // 2018-04-23 LocalDate date11 = date3.with(lastDayOfMonth()); // 2018-04-30 LocalDate date12 = date3.with(previous(DayOfWeek.SATURDAY)); // 2018-04-14 复制代码
可参考4月的日历来理解上面的结果:
我们还可以对LocalDate进行格式化操作:
String str1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); // 20180420 String str2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2018-04-20 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String str5 = date.format(dtf); // 2018-04-20 LocalDate date13 = LocalDate.parse(str5, dtf); // 2018-04-20 复制代码
LocalDate和下面要介绍的LocalTime,LocalDateTime之间共享了许多类似的方法,上面介绍的LocalDate修改、格式化等方法通用适用于LocalTime和LocalDateTime。
LocalTime和LocalDate类似,区别在于LocalTime包含的是时分秒(毫秒)信息。举些LocalTime的例子:
LocalTime time = LocalTime.of(20, 13, 54); // 20:13:54 int hour = time.getHour(); // 20 int minute = time.getMinute(); // 13 int second = time.getSecond(); // 54 复制代码
LocalDate和LocalTime都可以通过字符串来创建:
LocalDate date = LocalDate.parse("2018-04-20"); LocalTime time = LocalTime.parse("20:13:54"); 复制代码
LocalDateTime是LocalDate和LocalTime的组合形式,包含了年月日时分秒信息。举些LocalDateTime的使用示例:
LocalDateTime ldt1 = LocalDateTime.of(2018, 4, 20, 20, 13, 54); // 2018-04-20T20:13:54 LocalDateTime ldt2 = LocalDateTime.of(date, time); // 2018-04-20T20:13:54 复制代码
LocalDateTime可以转换为LocalDate和LocalTime,转换后包含的信息减少了:
LocalDate date1 = ldt1.toLocalDate(); // 2018-04-20 LocalTime time1 = ldt1.toLocalTime(); // 20:13:54 复制代码
同样的,LocalDate和LocalTime也可以转换为LocalDateTime,只需要补上日期或者时间:
LocalDateTime ldt3 = date.atTime(time); // 2018-04-20T20:13:54 LocalDateTime ldt4 = date.atTime(20, 13, 54); // 2018-04-20T20:13:54 LocalDateTime ldt5 = time.atDate(date); // 2018-04-20T20:13:54 复制代码
Duration用于计算两个LocalTime或者LocalDateTime的时间差,例如:
LocalTime time2 = LocalTime.of(23, 59, 59); Duration duration = Duration.between(time1, time2); long seconds = duration.getSeconds(); // 13565 复制代码
time1和time2之间相差了13565秒。
手动创建Duration对象:
Duration threeMinutes = Duration.ofMinutes(3); threeMinutes = Duration.of(3, ChronoUnit.MINUTES); // 创建了一个3分钟的Duration,两种创建方式等价 复制代码
Period用于计算两个LocalDate之间的时长。举些例子:
LocalDate date2 = LocalDate.of(2018, 5, 21); Period period = Period.between(date1, date2); int monthsBetween = period.getMonths(); // 1 int daysBetween = period.getDays(); // 1 复制代码
2018-04-21和2018-04-20之间月份相差1,天数相差1。
同样的,我们也可以手动创建Period对象:
Period tenDays = Period.ofDays(10); Period threeWeeks = Period.ofWeeks(3); Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1); 复制代码
LocalDate date15 = LocalDate.of(2018,4,21); date.isEqual(date15); // false date.isAfter(date15); // false date.isBefore(date15); // true 复制代码
MonthDay只包含月日信息,可以用于存放类似于生日,结婚纪念日等信息。举个使用MonthDay的例子:
LocalDate birthday = LocalDate.of(1999, 9, 9); MonthDay monthDay = MonthDay.of(birthday.getMonth(), birthday.getDayOfMonth()); MonthDay currentMonthDay = MonthDay.from(LocalDate.now()); if (currentMonthDay.equals(monthDay)) { System.out.println("happy birthday!"); } 复制代码
假如用户的生日是1999年9月9号,那么可以通过这种方法来判断今天是否是用户的生日,如果是的话便发送生日祝福。同样的也有YearMonth类。
Java 8 新的日期时间API还提供了不同时区和历法的获取方法,由于较少使用而且不易于理解,这里不再列出。