引言
Java 1.0 中引入了 Date 类,Java 1.1 中引入了 Calendar ,Java 8 中引入了java.time API ,这是 Java 非常吸引人的一次对时间日期的升级。它修正了过去的缺陷,同时也清晰易用。在 Java 8 引入time api 中,Instant 代表时间线上的一个点。
三个时间类
LocalDate、LocalTime、LocalDateTime
第一个只负责日期相关的处理,第二个负责时间相关的处理,第三个日期时间一起处理,其本质是前两者操作的再封装。
获取当前时间
LocalDateTime now = LocalDateTime.now();
//output : 2018-09-04T14:16:05.323
获取自定义时间
指定字符串:
LocalDateTime nationalDay = LocalDateTime.of(2018, Month.OCTOBER, 1, 14, 30);
// output : 2018-10-01T14:30
指定数字:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime someDay = LocalDateTime.parse("2018-10-01 14:30:30", formatter);
// output : 2018-10-01T14:30:30
日期时间格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String nowStr = now.format(formatter);
// output : 2018-09-04 14:37:32
注意,Java 8 有一个 BUG ,当日期字符串中带有毫秒值,无法成功格式化,是会抛出解析异常:
Exception in thread "main" java.time.format.DateTimeParseException:
Text '20191120100921234' could not be parsed at index 0at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)at java.time.LocalDateTime.parse(LocalDateTime.java:492)at com.ykt.ffan.common.utils.DateUtilPlus.main(DateUtilPlus.java:161)
官方解释说 Java9 已经解决了这个问题,但是Java8 的用户不可能通过升级JDK 来处理线上问题,那么这里贴出我本人的兼容方案:
if (format.contains("SSS")) {try {DateFormat df = new SimpleDateFormat(format);Instant instant = df.parse(dateStr).toInstant();return instant.atZone(ZoneId.systemDefault()).toLocalDateTime();} catch (ParseException e) {e.printStackTrace();}
}
日期比较大小
// LocalDateTime.now() == 2018-09-04 14:42:59
boolean nowIsBefore = LocalDateTime.now().isBefore(nationalDay);// nationalDay == 2018-10-01T14:30:30
// output : true
boolean nowIsAfter = LocalDateTime.now().isAfter(nationalDay);// nationalDay == 2018-10-01T14:30:30
// output : false
日期相差多少年 | 月 | 天 | 小时 | 分钟 | 秒
// now = 2018-09-04T14:50:34.857 ; nationalDay == 2018-10-01T14:30:30
long diffYears = ChronoUnit.YEARS.between(LocalDateTime.now(), nationalDay);
// output : 0
long diffMonths = ChronoUnit.MONTHS.between(LocalDateTime.now(), nationalDay);
// output : 0
long diffDays = ChronoUnit.DAYS.between(LocalDateTime.now(), nationalDay);
// output : 26
long diffHours = ChronoUnit.HOURS.between(LocalDateTime.now(), nationalDay);
// output : 647
long diffMins = ChronoUnit.MINUTES.between(LocalDateTime.now(), nationalDay);
// output :38859
long diffSecs = ChronoUnit.SECONDS.between(LocalDateTime.now(), nationalDay);
// output : 2331188
获取分钟
最简单
int mins2 = LocalDateTime.now().getMinute();
// output : 26
最万能 (用于非默认语义,如天的分钟数)
long mins = LocalDateTime.now().getLong(ChronoField.MINUTE_OF_HOUR);
// output : 26
long mins = LocalDateTime.now().getLong(ChronoField.MINUTE_OF_DAY);
// output : 926
两个特殊枚举
Month、DayOfWeek
获取星期
LocalDateTime sunDay = LocalDateTime.of(2018, 9, 2, 0, 0);DayOfWeek dayOfWeek = sunDay.getDayOfWeek();
// output : SUNDAY
int dayOfWeek = sunDay.getDayOfWeek().getValue();
// output : 7
获取月份
Month month = LocalDateTime.now().getMonth();
// output : SEPTEMBER
int month = LocalDateTime.now().getMonth().getValue();
// output : 9
获取年份
int year = LocalDateTime.now().getYear();
// output : 2018
Year year = Year.now();
// output : 2018