JDK8——日期相关API

背景

JDK8中增加了一套全新的日期时间API,这里进行总结下,方便查询使用:

作用 备注
Instant 表示时间戳 对应jdk7之前的Date,可通过Epoch Time 纪元时相互转换
LocalDateTime 获取当前系统的日期时间(内部不记录时区) 可以认为由LocalDate和LocalTime组成
LocalDate 获取当前系统的日期 年月日,对应java.sql.date
LocalTime 获取当前系统的时间 时分秒,对应java.sql.time
ZoneId 时区,”+01:00”和”Europe/Paris” ZoneId除了处理与标准时间的时间差还处理地区时(夏令时,冬令时等)
ZoneOffset 时区,只处理 “+01:00” ZoneOffset是ZoneId的子类,只处理与格林尼治的时间差
ZoneDateTime 特定时区的日期和时间 LocalDateTime内部不记录时区,ZoneDateTime记录
DateTimeFormatter 格式化日期 替换SimpleDateFormat,线程安全
Period 计算年月日格式的时间差异 只能精确到年月日
Duration 计算时间戳的时间差异 可用于LocalDateTime、Instant类
ChronoUnit 标准的日期单位 可用于日期计算时指定日期单位

获取日期时间的信息

LocalDate

LocalDate类获取日期信息。格式为 2018-09-06

  1. LocalDate nowDate = LocalDate.now();
  2. System.out.println("今天的日期:" + nowDate);//今天的日期:2018-09-06
  3. int year = nowDate.getYear();//年:一般用这个方法获取年
  4. System.out.println("year:" + year);//year:2018
  5. int month = nowDate.getMonthValue();//月:一般用这个方法获取月
  6. System.out.println("month:" + month);//month:9
  7. int day = nowDate.getDayOfMonth();//日:当月的第几天,一般用这个方法获取日
  8. System.out.println("day:" + day);//day:6
  9. int dayOfYear = nowDate.getDayOfYear();//日:当年的第几天
  10. System.out.println("dayOfYear:" + dayOfYear);//dayOfYear:249
  11. //星期
  12. System.out.println(nowDate.getDayOfWeek());//THURSDAY
  13. System.out.println(nowDate.getDayOfWeek().getValue());//4
  14. //月份
  15. System.out.println(nowDate.getMonth());//SEPTEMBER
  16. System.out.println(nowDate.getMonth().getValue());//9

LocalTime

LocalTime类获取时间信息。格式为 15:33:56.749

  1. LocalTime nowTime = LocalTime.now();
  2. System.out.println("今天的时间:" + nowTime);//今天的时间:15:33:56.749
  3. int hour = nowTime.getHour();//时
  4. System.out.println("hour:" + hour);//hour:15
  5. int minute = nowTime.getMinute();//分
  6. System.out.println("minute:" + minute);//minute:33
  7. int second = nowTime.getSecond();//秒
  8. System.out.println("second:" + second);//second:56
  9. int nano = nowTime.getNano();//纳秒
  10. System.out.println("nano:" + nano);//nano:749000000

LocalDateTime

LocalDateTime类获取日期时间信息。格式为 2018-09-06T15:33:56.750

  1. LocalDateTime nowDateTime = LocalDateTime.now();
  2. System.out.println("今天是:" + nowDateTime);//今天是:2018-09-06T15:33:56.750
  3. System.out.println(nowDateTime.getYear());//年
  4. System.out.println(nowDateTime.getMonthValue());//月
  5. System.out.println(nowDateTime.getDayOfMonth());//日
  6. System.out.println(nowDateTime.getHour());//时
  7. System.out.println(nowDateTime.getMinute());//分
  8. System.out.println(nowDateTime.getSecond());//秒
  9. System.out.println(nowDateTime.getNano());//纳秒
  10. //日:当年的第几天
  11. System.out.println("dayOfYear:" + nowDateTime.getDayOfYear());//dayOfYear:249
  12. //星期
  13. System.out.println(nowDateTime.getDayOfWeek());//THURSDAY
  14. System.out.println(nowDateTime.getDayOfWeek().getValue());//4
  15. //月份
  16. System.out.println(nowDateTime.getMonth());//SEPTEMBER
  17. System.out.println(nowDateTime.getMonth().getValue());//9

取指定的时间日期

LocalDate

  1. System.out.println(LocalDate.of(1991, 11, 11));//直接传入对应的年月日
  2. System.out.println(LocalDate.of(1991, Month.NOVEMBER, 11));//相对上面只是把月换成了枚举
  3. LocalDate birDay = LocalDate.of(1991, 11, 11);
  4. System.out.println(LocalDate.ofYearDay(1991, birDay.getDayOfYear()));//第一个参数为年,第二个参数为当年的第多少天
  5. System.out.println(LocalDate.ofEpochDay(birDay.toEpochDay()));//参数为距离1970-01-01的天数
  6. System.out.println(LocalDate.parse("1991-11-11"));
  7. System.out.println(LocalDate.parse("19911111",DateTimeFormatter.ofPattern("yyyyMMdd")));

LocalTime

  1. System.out.println(LocalTime.of(8, 20));//时分
  2. System.out.println(LocalTime.of(8, 20, 30));//时分秒
  3. System.out.println(LocalTime.of(8, 20, 30, 150));//时分秒纳秒
  4. LocalTime mTime = LocalTime.of(8, 20, 30, 150);
  5. System.out.println(LocalTime.ofSecondOfDay(mTime.toSecondOfDay()));//参数为距离当天零时的秒数
  6. System.out.println(LocalTime.ofNanoOfDay(mTime.toNanoOfDay()));//参数为距离当天零时的纳秒数
  7. System.out.println(LocalTime.parse("08:20:30"));
  8. System.out.println(LocalTime.parse("082030", DateTimeFormatter.ofPattern("HHmmss")));

LocalDateTime

这里的 birDay 和 mTime 复用上面的变量。

  1. System.out.println(LocalDateTime.of(birDay, mTime));//参数为LocalDate和LocalTime
  2. System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20));
  3. System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20));
  4. System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20, 30));
  5. System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20, 30));
  6. System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20, 30, 150));
  7. System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20, 30, 150));
  8. System.out.println(LocalDateTime.parse("1991-11-11T08:20:30"));
  9. System.out.println(LocalDateTime.parse("1991-11-11 08:20:30", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

日期时间的比较

在JDK8中,LocalDate类中使用isBefore()、isAfter()、equals()方法来比较两个日期,可直接进行比较。
以LocalDate为例。

  1. LocalDate myDate = LocalDate.of(2018, 9, 5);
  2. LocalDate nowDate = LocalDate.now();
  3. System.out.println("今天是2018-09-06吗? " + nowDate.equals(myDate));//今天是2018-09-06吗? false
  4. System.out.println(myDate + "是否在" + nowDate + "之前? " + myDate.isBefore(nowDate));//2018-09-05是否在2018-09-06之前? true
  5. System.out.println(myDate + "是否在" + nowDate + "之后? " + myDate.isAfter(nowDate));//2018-09-05是否在2018-09-06之后? false

如何在java中判断是否是某个节日或者重复事件,使用MonthDay类。这个类由月日组合,不包含年信息,可以用来代表每年重复出现的一些日期。它和新的日期库中的其他类一样也都是不可变且线程安全的。

  1. LocalDate birDate = LocalDate.of(1991, 10, 1);
  2. LocalDate nowDate = LocalDate.now();
  3. MonthDay nowDay = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth());
  4. MonthDay monthDay = MonthDay.of(birDate.getMonth(), birDate.getDayOfMonth());
  5. MonthDay birDay = MonthDay.from(nowDate);
  6. System.out.println("今天是你的生日吗? " + nowDay.equals(birDay));//今天是你的生日吗? false

YearMonth表示固定的日期。Year表示年。

  1. YearMonth yearMonth = YearMonth.of(2004, 2);
  2. System.out.println(yearMonth + "有多少天? " + yearMonth.lengthOfMonth());//2004-02有多少天? 29
  3. Year year = Year.of(2004);
  4. System.out.println(year + "有多少天? " + year.length());//2004有多少天? 366
  5. System.out.println(year + "是否是闰年? " + year.isLeap());//2004是否是闰年? true

新版本的日期时间API中的这几个类中好多方法都是一样的作用,使用时可灵活选择。

对日期时间的修改

LocalDateTime 综合了 LocalDate 和 LocalTime 里面的方法,所以下面只用 LocalDate 和 LocalTime 来举例。
这些方法返回的是一个新的实例引用,因为LocalDateTime 、LocalDate 、LocalTime 都是不可变的。

  1. LocalDate nowDate = LocalDate.now();
  2. System.out.println(nowDate);//当前日期
  3. System.out.println(nowDate.minusYears(1));//一年前
  4. System.out.println(nowDate.minusMonths(1));//一月前
  5. System.out.println(nowDate.minusWeeks(1));//一周前
  6. System.out.println(nowDate.minusDays(1));//一天前
  7. System.out.println(nowDate.plusYears(1));//一年后
  8. System.out.println(nowDate.plusMonths(1));//一月后
  9. System.out.println(nowDate.plusWeeks(1));//一周后
  10. System.out.println(nowDate.plusDays(1));//一天后
  11. LocalTime nowTime = LocalTime.now();
  12. System.out.println(nowTime);//当前时间
  13. System.out.println(nowTime.minusHours(1));//一小时前
  14. System.out.println(nowTime.minusMinutes(1));//一分钟前
  15. System.out.println(nowTime.minusSeconds(1));//一秒前
  16. System.out.println(nowTime.minusNanos(1));//一纳秒前
  17. System.out.println(nowTime.plusHours(1));//一小时后
  18. System.out.println(nowTime.plusMinutes(1));//一分钟后
  19. System.out.println(nowTime.plusSeconds(1));//一秒后
  20. System.out.println(nowTime.plusNanos(1));//一纳秒后

还可以直接使用 minus 和 plus 方法来增加和减少日期时间。LocalDateTime 、LocalDate 、LocalTime 都是类似的。

  1. System.out.println(nowDate.minus(1, ChronoUnit.YEARS));
  2. System.out.println(nowDate.plus(1, ChronoUnit.YEARS));

ChronoUnit 用来表示时间单位, ChronoUnit 后面只需要替换成相应的年、月、周、日、时、分、秒、纳秒,就能减少或增加相应的单位。

时间戳

JDK8获取时间戳特别简单。Instant类由一个静态的工厂方法now()可以返回当前时间戳。

  1. Instant instant = Instant.now();
  2. System.out.println("当前时间戳是:" + instant);//当前时间戳是:2018-09-06T10:14:29.460Z
  3. Date date = Date.from(instant);
  4. System.out.println("当前时间戳是:" + date);//当前时间戳是:Thu Sep 06 18:14:29 CST 2018
  5. instant = date.toInstant();

可以看到,当前时间戳是包含日期和时间的,与java.util.Date很类似,事实上Instant就是JDK8以前的Date,可以使用这两个类中的方法在这两个类型之间进行转换。

日期时间格式化

在JDK8之前,时间日期的格式化非常麻烦,经常使用SimpleDateFormat来进行格式化,但是SimpleDateFormat并不是线程安全的。在JDK8中,引入了一个全新的线程安全的日期与时间格式器DateTimeFormatter。

  1. LocalDateTime ldt = LocalDateTime.now();
  2. System.out.println(ldt);//2018-09-06T18:22:47.366
  3. DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  4. String ldtStr = ldt.format(dtf);
  5. System.out.println(ldtStr);//2018-09-06 18:22:47
  6. String ldtStr1 = dtf.format(ldt);
  7. System.out.println(ldtStr1);//2018-09-06 18:22:47

正反都能调用format方法。

计算日期时间差

在Java8中,我们可以使用以下类来计算日期时间差异:

java.time.Period

主要是 Period 类方法 getYears(),getMonths() 和 getDays() 来计算。只能精确到年月日。
用于 LocalDate 之间的比较。

  1. LocalDate today = LocalDate.now();
  2. System.out.println(today);//2018-09-06
  3. LocalDate birthDate = LocalDate.of(1992, 1, 11);
  4. System.out.println(birthDate);//1990-10-01
  5. Period period = Period.between(birthDate, today);//第二个参数减第一个参数
  6. System.out.printf("年龄 : %d 年 %d 月 %d 日", period.getYears(), period.getMonths(), period.getDays());//年龄 : 27 年 11 月 5 日

java.time.Duration

提供了使用基于时间的值测量时间量的方法。
用于 LocalDateTime 之间的比较。也可用于 Instant 之间的比较。

  1. LocalDateTime today = LocalDateTime.now();
  2. System.out.println(today);
  3. LocalDateTime birthDate = LocalDateTime.of(1990,10,1,10,50,30);
  4. System.out.println(birthDate);
  5. Duration duration = Duration.between(birthDate, today);//第二个参数减第一个参数
  6. System.out.println(duration.toDays());//两个时间差的天数
  7. System.out.println(duration.toHours());//两个时间差的小时数
  8. System.out.println(duration.toMinutes());//两个时间差的分钟数
  9. System.out.println(duration.toMillis());//两个时间差的毫秒数
  10. System.out.println(duration.toNanos());//两个时间差的纳秒数

java.time.temporal.ChronoUnit

ChronoUnit类可用于在单个时间单位内测量一段时间,这个工具类是最全的了,可以用于比较所有的时间单位。

  1. LocalDateTime today = LocalDateTime.now();
  2. System.out.println(today);
  3. LocalDateTime birthDate = LocalDateTime.of(1990,10,1,10,50,30);
  4. System.out.println(birthDate);
  5. System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
  6. System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
  7. System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today));
  8. System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today));
  9. System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today));
  10. System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today));
  11. System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today));
  12. System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today));
  13. System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today));
  14. System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today));
  15. System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
  16. System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today));
  17. System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today));
  18. System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today));
  19. System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today));

ZoneId/ZoneOffSet

ZoneId/ZoneOffSet的区别。
ZoneOffSet只处理与标准时的时区差,ZoneId除了处理与标准时的时间差,还处理地区时(夏令时,冬令时等时间调整)

  1. (ZoneOffset) ZoneId.of("+01:00")
  2. //ZoneOffset只处理("+01:00")类型的时区问题,所以下面的代码会抛出异常
  3. (ZoneOffset) ZoneId.of("Europe/Paris")

ZonedDateTime

与LocalDateTime的区别是,ZonedDateTime内部记录了时区,而LocalDateTime没有。
因此LocalDateTime转Instant需要指定ZoneOffSet而ZoneDateTime不需要。

  1. LocalDateTime.now().toInstant(ZoneOffset.of("+01:00"));
  2. ZonedDateTime.now().toInstant();

一.在Java 8中将Date转换为LocalDateTime

方法1:
将Date转换为LocalDatetime,我们可以使用以下方法:

  1. 1.从日期获取ZonedDateTime并使用其方法toLocalDateTime()获取LocalDateTime
  2. 2.使用LocalDateTimeInstant()工厂方法

示例:

  1. public class Test {
  2. public static void main(String[] args) {
  3. Date date = new Date();
  4. Instant instant = date.toInstant();
  5. ZoneId zoneId = ZoneId.systemDefault();
  6. LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
  7. System.out.println("Date = " + date);
  8. System.out.println("LocalDateTime = " + localDateTime);
  9. }
  10. }

结果:

  1. Date = Fri Jun 16 15:35:26 CST 2017
  2. LocalDateTime = 2017-06-16T15:35:26.970

方法2:
我们也可以使用LocalDateTime的FactoryInput()方法使用系统的默认时区。

  1. LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), zoneId);

二.在Java 8中将LocalDateTime转换为Date

要将LocalDateTime转换回java.util.Date,我们可以使用以下步骤:

  1. 1.使用atZone()方法将LocalDateTime转换为ZonedDateTime
  2. 2.ZonedDateTime转换为Instant,并从中获取Date

示例:

  1. public class Test {
  2. public static void main(String[] args) {
  3. ZoneId zoneId = ZoneId.systemDefault();
  4. LocalDateTime localDateTime = LocalDateTime.now();
  5. ZonedDateTime zdt = localDateTime.atZone(zoneId);
  6. Date date = Date.from(zdt.toInstant());
  7. System.out.println("LocalDateTime = " + localDateTime);
  8. System.out.println("Date = " + date);
  9. }
  10. }

结果:

  1. LocalDateTime = 2017-06-16T15:38:48.580
  2. Date = Fri Jun 16 15:38:48 CST 2017

原文地址:https://blog.csdn.net/hspingcc/article/details/73332380