在刚学习 Java 时间 API 的时候,我的内心其实是拒绝的,内心只有一个想法,这 TM 太麻烦了吧。原来的时间 API 我也不太了解,Java 8 既然提供了新的时间 API,我们就来学习一下新的 API 吧,旧的就让它成为过去式吧。
代表日期、时间和时区的新类
有3个类来替代原来的 Date
类,这3个类分别是 LocalDate
, LocalTime
和 LocalDateTime
。
LocalDate
LocalDate
代表日期,没有时间和时区的概念。
LocalDate localDate = LocalDate.now();
System.out.println(localDate.toString()); //2018-04-22
System.out.println(localDate.getDayOfWeek().toString()); //SUNDAY
System.out.println(localDate.getDayOfMonth()); //22
System.out.println(localDate.getDayOfYear()); //112
System.out.println(localDate.isLeapYear()); //false
System.out.println(localDate.plusDays(12).toString()); //2018-05-04
LocalTime
LocalTime
代表时间,没有日期和时区的概念。
//LocalTime localTime = LocalTime.now(); //toString() in format 19:13:33.291
LocalTime localTime = LocalTime.of(12, 20);
System.out.println(localTime.toString()); //12:20
System.out.println(localTime.getHour()); //12
System.out.println(localTime.getMinute()); //20
System.out.println(localTime.getSecond()); //0
System.out.println(localTime.MIDNIGHT); //00:00
System.out.println(localTime.NOON); //12:00
LocalDateTime
LocalDateTime
代表日期时间,没有时区的概念。
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime.toString()); //2018-04-15T10:01:14.911
System.out.println(localDateTime.getDayOfMonth()); //15
System.out.println(localDateTime.getHour()); //10
System.out.println(localDateTime.getNano()); //911000000
如果我们需要带上有时区信息,那么可以使用另外3个相似的类OffsetDate
, OffsetTime
和 OffsetDateTime
。时区偏移可以用 “+05:30” or “Europe/Paris” 格式来表示。Java 通过一个 ZoneId
类来表示。
OffsetDateTime offsetDateTime = OffsetDateTime.now();
System.out.println(offsetDateTime.toString()); //2018-04-22T19:27:23.117+08:00
offsetDateTime = OffsetDateTime.now(ZoneId.of("+05:30"));
System.out.println(offsetDateTime.toString()); //2018-04-22T16:57:23.117+05:30
offsetDateTime = OffsetDateTime.now(ZoneId.of("-06:30"));
System.out.println(offsetDateTime.toString()); //2018-04-22T04:57:23.117-06:30
ZonedDateTime zonedDateTime =
ZonedDateTime.now(ZoneId.of("Europe/Paris"));
System.out.println(zonedDateTime.toString()); //2018-04-22T13:27:23.120+02:00[Europe/Paris]
代表时间戳和时间区间的新类
** Instant**
Instant
代表任意时刻的时间戳,精度达到了纳秒。对 Instant
包括 与另外一个 Instant
进行对比,加减一段时间区间。
Instant instant = Instant.now();
System.out.println(instant.toString()); //2018-04-22T11:29:05.299Z
System.out.println(instant.plus(Duration.ofMillis(5000)).toString()); //2018-04-22T11:29:10.299Z
System.out.println(instant.minus(Duration.ofMillis(5000)).toString()); //2018-04-22T11:29:00.299Z
System.out.println(instant.minusSeconds(10).toString()); //2018-04-22T11:28:55.299Z
Duration
Duration
代表2个时间戳的差值,即时间区间。
Duration duration = Duration.ofMillis(5000);
System.out.println(duration.toString()); //PT5S
duration = Duration.ofSeconds(60);
System.out.println(duration.toString()); //PT1M
duration = Duration.ofMinutes(10);
System.out.println(duration.toString()); //PT10M
duration = Duration.ofHours(2);
System.out.println(duration.toString()); //PT2H
duration = Duration.between(Instant.now(), Instant.now().plus(Duration.ofMinutes(10)));
System.out.println(duration.toString()); //PT10M
Duration
处理的是小单位的时间区间,比如 毫秒,秒,分钟和小时。更加适合和机器交互的场景。如果在和人进行交互的场景下,可以使用 Period
。
Period
Period
代表更大的时间间隔。
Period period = Period.ofDays(6);
System.out.println(period.toString()); //P6D
period = Period.ofMonths(6);
System.out.println(period.toString()); //P6M
period = Period.between(LocalDate.now(),
LocalDate.now().plusDays(60));
System.out.println(period.toString()); //P1M30D
添加新的枚举类
在 Java 8 中添加了一些新的枚举类,我们就拿 DayOfWeek
类来距离。
DayOfWeek
//day-of-week to represent, from 1 (Monday) to 7 (Sunday)
System.out.println(DayOfWeek.of(2)); //TUESDAY
DayOfWeek day = DayOfWeek.FRIDAY;
System.out.println(day.getValue()); //5
localDate = LocalDate.now();
System.out.println(localDate.with(DayOfWeek.MONDAY)); //2018-04-16 i.e. when was monday in current week ?
其他的类还有 Month
, MonthDay
, Year
, YearMonth
, 当然还有更多。
Date adjusters
Date adjusters 表示日期管理员,这是一个实用的工具类。这个类的主要功能是用于解决这类问题的,“上个月的最后一天?”,“下一个工作日?” 或者 “下一个周四?”。
LocalDate date = LocalDate.of(2018, Month.APRIL, 22); //Today
LocalDate endOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(endOfMonth.toString()); //2018-04-30
LocalDate nextTue = date.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
System.out.println(nextTue.toString()); //2018-04-24
创建 date 对象
现在可以使用构造者模式来创建 date 对象。构造者模式能够以单独的部分来进行构造。这些方法都是以 "at" 作为方法前缀。
//Builder pattern used to make date object
OffsetDateTime date1 = Year.of(2018)
.atMonth(Month.APRIL).atDay(22)
.atTime(0, 0)
.atOffset(ZoneOffset.of("+08:00"));
System.out.println(date1); //2018-04-22T00:00+08:00
//factory method used to make date object
OffsetDateTime date2 = OffsetDateTime.
of(2018, 4, 22, 0, 0, 0, 0, ZoneOffset.of("+08:00"));
System.out.println(date2);
模拟系统时钟的新类
Clock
类能够模拟系统时钟。这个有什么用呢?当我们在编写与时间有关的逻辑的时候,单元测试的时候,我们可能会需要将来的某个时间点,因此需要修改系统的时间然后重启使其生效。
现在,有了 Clock
类,就不必这么做了。Clock 能够模拟系统时钟。
Clock clock = Clock.systemDefaultZone();
System.out.println(clock); //SystemClock[Asia/Shanghai]
System.out.println(clock.instant().toString()); //2018-04-22T13:25:59.384Z
System.out.println(clock.getZone()); //Asia/Shanghai
Clock anotherClock = Clock.system(ZoneId.of("Europe/Tiraspol"));
System.out.println(anotherClock); //SystemClock[Europe/Tiraspol]
System.out.println(anotherClock.instant().toString()); //2018-04-22T13:25:59.397Z
System.out.println(anotherClock.getZone()); //Europe/Tiraspol
Clock forwardedClock = Clock.tick(anotherClock, Duration.ofSeconds(600));
System.out.println(forwardedClock.instant().toString()); //2018-04-22T13:20:00Z
这里对这个 tick
方法说明一下,因为这个方法我看了半天都不懂这个方法到底想做什么。tick
方法就是将时钟以给定的 Duration为间隔进行打点,然后找到最接近给定 Clock 的 Clock。哎说不清楚,举例子说明吧。
假如你的时钟现在处于 10s 的状态。你给定的 Duration 为2s,那么就会从0s 开始以2s为间隔进行打点,0s,2s,4s,6s,8s 最近的就是8s 了,所有就会返回这个 Clock。如果你指定的是0.5s,那么就是0s,0.5s,1s,.....知道9.5s。
格式化
日期格式化主要通过2个类,DateTimeFormatterBuilder
和DateTimeFormatter
。DateTimeFormatterBuilder
类主要是提供构造者模式创建自定义的 DateTimeFormatter
类。
DateTimeFormatterBuilder formatterBuilder = new DateTimeFormatterBuilder();
formatterBuilder.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendLiteral("-")
.appendZoneOrOffsetId();
DateTimeFormatter formatter = formatterBuilder.toFormatter();
System.out.println(formatter.format(ZonedDateTime.now()));
哎,感觉讲完这些还是需要实例才能弄明白,下面一篇写一点例子吧。
欢迎关注我的微信公众号:java初学者的日常
java初学者的日常
网友评论