JDK1.8新特性(五):新的日期时间 API

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】即可免费无套路获取学习视频。

你可能感兴趣的:(JDK1.8新特性(五):新的日期时间 API)