JDK1.8系列文章
- JDK1.8新特性(一):Lambda表达式
- JDK1.8新特性(二):Optional 类
- JDK1.8新特性(三):Stream
- JDK1.8新特性(四):Maps
- JDK1.8新特性(五):新的日期时间 API
Java 8 在 java.time
包中包含一个全新的日期和时间 API。新的 Date API 与 Joda-Time 库具有可比性,但是并不相同。下面的示例涵盖了这个新API的最重要部分。
在《阿里巴巴 Java 开发手册》中有提到,SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。
正例:注意线程安全,使用 DateUtils。亦推荐如下处理:
private static final ThreadLocal df = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
} };
如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar, DateTimeFormatter 代替 Simpledateformatter,官方给出的解释:simple beautiful strong immutable thread-safe。
一、Clock
Clock 提供对访问当前日期和时间的方法。Clocks 与时区相关,可以用 System.currentTimeMillis() 来获取当前的微秒数。 某一个特定的时间点也可以使用 Instant 类来表示,Instant 类也可以用来创建旧版本的 java.util.Date 对象。
Clock clock = Clock.systemDefaultZone();
long millis = clock.millis();
Instant instant = clock.instant();
Date legacyDate = Date.from(instant); // legacy java.util.Date
二、Timezones
时区由 ZoneId 表示,可以通过静态工厂方法轻松访问它们。时区定义了偏移量,这对于在瞬间与本地日期和时间之间进行转换很重要。
System.out.println(ZoneId.getAvailableZoneIds());
// prints all available timezone ids
ZoneId zone1 = ZoneId.of("Europe/Berlin");
ZoneId zone2 = ZoneId.of("Brazil/East");
System.out.println(zone1.getRules());
System.out.println(zone2.getRules());
// ZoneRules[currentStandardOffset=+01:00]
// ZoneRules[currentStandardOffset=-03:00]
三、LocalTime
LocalTime 表示没有时区的时间,例如晚上10点或17:30:15。以下示例为上面定义的时区创建两个本地时间。然后,我们比较两个时间,并计算两个时间之间的小时和分钟差异。
LocalTime now1 = LocalTime.now(zone1);
LocalTime now2 = LocalTime.now(zone2);
System.out.println(now1.isBefore(now2)); // false
long hoursBetween = ChronoUnit.HOURS.between(now1, now2);
long minutesBetween = ChronoUnit.MINUTES.between(now1, now2);
System.out.println(hoursBetween); // -3
System.out.println(minutesBetween); // -239
LocalTime 带有各种工厂方法来简化新实例的创建,包括时间字符串的解析。
LocalTime late = LocalTime.of(23, 59, 59);
System.out.println(late); // 23:59:59
DateTimeFormatter germanFormatter =
DateTimeFormatter
.ofLocalizedTime(FormatStyle.SHORT)
.withLocale(Locale.GERMAN);
LocalTime leetTime = LocalTime.parse("13:37", germanFormatter);
System.out.println(leetTime); // 13:37
四、LocalDate
LocalDate 代表一个不同的日期,例如2014-03-11。它是不可变的,并且完全类似于 LocalTime。该示例演示了如何通过增加或减去天,月或年来计算新日期。请记住,每种操作都会返回一个新实例。
LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
LocalDate yesterday = tomorrow.minusDays(2);
LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4);
DayOfWeek dayOfWeek = independenceDay.getDayOfWeek();
System.out.println(dayOfWeek); // FRIDAY
从字符串中解析 LocalDate 就像解析 LocalTime 一样简单:
DateTimeFormatter germanFormatter =
DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.GERMAN);
LocalDate xmas = LocalDate.parse("24.12.2014", germanFormatter);
System.out.println(xmas); // 2014-12-24
五、LocalDateTime
LocalDateTime 表示日期时间。如上所述,它将日期和时间组合为一个实例。 LocalDateTime 是不可变的,其工作方式类似于 LocalTime 和 LocalDate 。我们可以利用方法从日期时间检索某些字段:
LocalDateTime sylvester = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59);
DayOfWeek dayOfWeek = sylvester.getDayOfWeek();
System.out.println(dayOfWeek); // WEDNESDAY
Month month = sylvester.getMonth();
System.out.println(month); // DECEMBER
long minuteOfDay = sylvester.getLong(ChronoField.MINUTE_OF_DAY);
System.out.println(minuteOfDay); // 1439
利用时区信息,可以将其转换为一个时间点Instant对象。Instant时间点对象可以轻松地转换为 java.util.Date
类型的日期。
Instant instant = sylvester
.atZone(ZoneId.systemDefault())
.toInstant();
Date legacyDate = Date.from(instant);
System.out.println(legacyDate); // Wed Dec 31 23:59:59 CET 2014
格式化日期时间就像格式化日期或时间一样。可以使用自定义模式创建格式化程序,而不是使用预定义格式。
DateTimeFormatter formatter =
DateTimeFormatter
.ofPattern("MMM dd, yyyy - HH:mm");
LocalDateTime parsed = LocalDateTime.parse("Nov 03, 2014 - 07:13", formatter);
String string = formatter.format(parsed);
System.out.println(string); // Nov 03, 2014 - 07:13
和 java.text.NumberFormat 不一样,新版的 DateTimeFormatter 是不可变的并且是线程安全的。
六、公众号
如果大家想要第一时间看到我更新的 Java 方向学习文章,可以关注一下公众号【Lucas的咖啡店】。所有学习文章公众号首发,请各位大大扫码关注一下哦!
Java 8 新特性学习视频请关注公众号,私信【Java8】即可免费无套路获取学习视频。