Java 8 Date Time AP
Java 8 Date Time AP 是受开发者最受追捧的变更。 java在之前并没有处理日期、时间的一致性方法。
为什么我们需要新的 Java Date Time API?
我们关注Java 8 Date Time API使用之前,先看一下我们为什么需要它们。之前,在与日期、时间关联的java类中存在以下几个问题:
- java的日期、时间类定义不一致。 之前在 java.util、java.sql包中都定义了Date类;但是格式化个解析类又放在java.text包下。
- java.util.Date 包含了日期和时间,但是java.sql.Date只包含了日期。 这两个类具有共同的名字,真是糟糕的设计。
- 对于时间, 时间戳, 格式化和解析并没有清晰定义的java类。 一般使用java.text.DateFormat提供的格式化、解析方法。 通常使用 SimpleDateFormat 类进行格式化日期时间与解析日期时间。
- 所有的日期类均不是线程安全的。这也是Date 和Calendar类存在的最大问题之一。
- Date 类没有提供国际化,也不支持时区。
Date 、Calendar还存在其他的问题,但是上述问题已经表明java需要更强大的日期时间API了。这也是为什么 Joda Time 作为Java Date Time的替代者的原因了。
Java 8 Date
Java 8 Date Time API 是 JSR-310的实现。 设计初衷是为了克服固有的Date Time API遗留下来的缺陷。新的Date Time API设计原则:
- 稳定不变性 新的Date Time API 是线程安全的。
- 关注点分离 新的API 将人与机器的关注点分离了(二者关注的分别是时间日期、unix时间戳),设计了诸如Date, Time, DateTime, Timestamp, Timezone这些类。
- 清晰 在众多类中声明了同样动作的方法。例如 now()方法获得当前实例。format()、parse()都在这些类中有定义。而不是分离出来在不同的类中定义。所有这些类设计是按工厂模式、策略模式来进行的,易于操作。一旦你学会使用其中一个类地方法,使用其他类就很简单了。
- 通用工具方法 所有新的Date Time API 类均提供了常用的方法。加、减、格式、解析以及分离日期和时间等操作。
- 扩展性 新的Date Time API是基于ISO-8601日历系统设计的,我们也可以采用其他非ISO 日历系统设计。
Java 8 Date Time API 包
Java 8 Date Time API包含以下包:
- java.time包 这是新的Java Date Time API基础包。 主要的基础类均在这个包中,如 LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有这些类均是线程安全的。 大多数情况下,这些类已经能够处理常用操作了。
- java.time.chrono包 这个包定义了通用的非ISO日历系统的API。我们可以继承AbstractChronology 类扩展我们自定义的日历系统。
- java.time.format包 这个包包含了格式化、解析时间的类。更多的时候我们并不会用到他们,因为 java.time 包已经提供了日期格式化、解析的方法。
- java.time.temporal 包 提供了一些获取临时信息的对象。 比如获取当期月的第一或最后一天。你能很好识别这些方法,因为他们通常被命名为“withXXX”。
- java.time.zone包 支持不同时区和其他规则。
Java 8 Date Time API使用示例
了解新Java Date Time API的重要性之后,我们通过实例来学习Date Time相关的类。
LocalDate
LocalDate 是一个用来表示日期的不可变类(final修饰),默认格式是 yyyy-MM-dd。我们可以通过其now()方法获取当前日期。也提供了可以表示year, month 和 date 入参来获取LocalDate 实例。这个类提供了now()的重载方法通过提供一个时区的入参获取指定时区的日期。这个类的功能和java.sql.Date类似的功能。
代码语言:javascript复制package com.byron4j.hightLevel.java8.date;
import java.time.LocalDate;
import java.time.ZoneId;
/**
*
* <pre>
* LocalDate示例
* </pre>
* @author Byron.Y.Y
*/
public class LocalDateTest {
public static void main(String[] args) {
//获取当前日期默认格式yyyy-MM-d
System.out.println(LocalDate.now().toString());
//使用now()重载方法,ZoneId的of方法使用了其内嵌的时区map映射表
System.out.println(LocalDate.now(ZoneId.of("CTT", ZoneId.SHORT_IDS)));
//获取指定上海时区的日期(时区的id参见ZoneId 类的文档)
System.out.println(LocalDate.now(ZoneId.of("Asia/Shanghai")));
//2017-05-07
System.out.println(LocalDate.of(2017, 5, 7));
//入参为从1970-01-01起的累计天数(1970-01-01为0)
System.out.println(LocalDate.ofEpochDay(17293));
//指定年的第多少天(2017年的第127天是5月7日)
System.out.println(LocalDate.ofYearDay(2017, 127));
}
}
编写该代码时是2017-05-07日,所以程序运行结果都是:2017-05-07。
LocalTime
LocalTime 代表了一个人们可读格式的时间实例。
代码语言:javascript复制package com.byron4j.hightLevel.java8.date;
import java.time.LocalTime;
import java.time.ZoneId;
/**
*
* <pre>
* LocalTime类的示例
* </pre>
* @author Byron.Y.Y
*/
public class LocalTimeTest {
public static void main(String[] args) {
//输出格式HH:mm:ss.ms 毫秒
System.out.println(LocalTime.now());
//hour minute second 纳秒
System.out.println(LocalTime.of(20, 53, 30, 70));
System.out.println(LocalTime.now(ZoneId.of("Asia/Shanghai")));
System.out.println(LocalTime.ofSecondOfDay(86399));
}
}
输出结果:
代码语言:javascript复制20:59:58.916
20:53:30.000000070
20:59:58.917
23:59:59
LocalDateTime
LocalDateTime 代表了日期加时间,默认格式为: yyyy-MM-dd-HH-mm-ss.zzz。它提供了一个工厂方法,使用LocalDate 和LocalTime输入参数构建LocalDateTime实例。
代码语言:javascript复制package com.byron4j.hightLevel.java8.date;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
/**
*
* <pre>
* LocalDateTime演示实例
* </pre>
* @author Byron.Y.Y
*/
public class LocalDateTimeTest {
public static void main(String[] args) {
System.out.println(LocalDateTime.now());
System.out.println(LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
//入参LocalDate、LocalTime
System.out.println(LocalDateTime.of(LocalDate.now(), LocalTime.now()));
}
}
输出结果:
代码语言:javascript复制2017-05-07T21:07:39.785
2017-05-07T21:07:39.786
2017-05-07T21:07:39.786
Instant
Instant 代表了机器识别格式的实例。存储格式是unix 时间戳。格式形如:2017-05-07T13:12:23.741Z
Java 8 日期格式化和解析
代码语言:javascript复制package com.byron4j.hightLevel.java8.date;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
*
* <pre>
* java8 日期格式化示例
* </pre>
* @author Byron.Y.Y
*/
public class DateTimeFormatTest {
public static void main(String[] args) {
LocalDate now = LocalDate.now();
//LocalDate的format仅仅支持日期的格式 不支持小时分秒等格式(否则错误Unsupported field)
System.out.println(now.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE));
}
}
输出结果:
20170507 2017-05-07