# Java – 日期和时间 API

> 原文： [https://howtodoinjava.com/java-date-and-time-apis/](https://howtodoinjava.com/java-date-and-time-apis/)

Java 主要使用两个包`java.time`和`java.util`支持日期和时间特性。 包`java.time`是在 Java 8 中添加的（ [JSR-310](https://jcp.org/en/jsr/detail?id=310) ），新添加的类旨在解决传统`java.util.Date`和`java.util.Calendar`类的缺点。

## 1\. 旧版日期时间 API

#### 1.1 类

Java 8 发行之前的主要类是：

*   [`System.currentTimeMillis()`](https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#currentTimeMillis())：表示自 1970 年 1 月 1 日起的当前日期和时间（以毫秒为单位）。
*   [`java.util.Date`](https://docs.oracle.com/javase/7/docs/api/java/util/Date.html)：表示特定的时间瞬间，精度为毫秒。
*   [`java.util.Calendar`](https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html)：一个抽象类，提供用于在实例之间进行转换并以不同的方式操纵日历字段的方法。
*   [`java.text.SimpleDateFormat`](https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html)：一个具体的类，用于以对语言环境敏感的方式以及任何预定义以及任何用户定义的模式来格式化和解析日期。
*   [`java.util.TimeZone`](https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html)：代表时区偏移量，并且还计算出夏令时。

#### 1.2 挑战

尽管这些 API 非常适合简单的用例，但 Java 社区仍在不断抱怨有效使用这些类的问题。 因此，其他许多第三方库（例如 [Joda-Time](https://www.joda.org/joda-time/) 或 [Apache Commons](https://commons.apache.org/) 中的类）也更加受欢迎。

很少有挑战：

*   `Date`类应表示日期，但也表示具有小时，分钟和秒的实例。
*   但是`Date`没有任何关联的时区。 它会自动选择默认时区。 您不能将日期表示为其他时区。
*   类是可变的。 因此，这给开发人员在传递可以更改日期的函数之前克隆日期增加了负担。
*   日期格式化类也不是线程安全的。 如果没有其他同步，则无法使用格式化器实例，否则代码可能会中断。
*   出于某种原因，还有另一种`java.sql.Date`，其中包含时区信息。
*   使用其他时区创建日期非常棘手，通常会导致错误的结果。
*   它的类使用零索引数月，这是多年来应用程序中许多错误的原因。

## 2\. Java 8 中的新日期时间 API

新的日期 api 尝试解决旧类的上述问题。 它主要包含以下类：

*   [`java.time.LocalDate`](https://howtodoinjava.com/java/date-time/compare-localdates/)：表示 ISO 日历中的年-月-日，对于表示没有时间的日期很有用。 它可用于表示仅日期的信息，例如出生日期或结婚日期。
*   [`java.time.LocalTime`](https://howtodoinjava.com/java/date-time/java-localtime/)：仅及时处理。 这对于表示基于人的时间（例如电影时间或本映射书馆的开放和关闭时间）很有用。
*   [`java.time.LocalDateTime`](https://howtodoinjava.com/java/date-time/compare-localdatetime/)：处理日期和时间，没有时区。 它是`LocalDate`与`LocalTime`的组合。
*   [`java.time.ZonedDateTime`](https://howtodoinjava.com/java/date-time/zoneddatetime-comparison/)：将`LocalDateTime`类与`ZoneId`类中给出的区域信息组合在一起。 它代表完整的日期时间戳以及时区信息。
*   `java.time.OffsetTime`：处理时间与格林威治/ UTC 有相应时区偏移的时间，没有时区 ID。
*   `java.time.OffsetDateTime`：处理具有与格林威治/ UTC 相对应的时区偏移的日期和时间，没有时区 ID。
*   `java.time.Clock`：提供对任何给定时区中的当前时刻，日期和时间的访问。 尽管使用`Clock`类是可选的，但是此特性使我们可以测试其他时区的代码，也可以使用时间不可变的固定时钟来测试您的代码。
*   `java.time.Instant`：表示时间轴上的纳秒的开始（自纪元开始），对于生成表示机器时间的时间戳很有用。 在纪元之前发生的瞬间具有负值，在纪元之后发生的瞬间具有正值。
*   `java.time.Duration`：两个瞬间之间的差异，以秒或纳秒为单位，并且不使用基于日期的构造，例如年，月和日，尽管该类提供了转换为天，小时和分钟的方法。
*   `java.time.Period`：以基于日期的值（年，月，日）定义日期之间的差异。
*   `java.time.ZoneId`：指定时区标识符，并提供用于在`Instant`和`LocalDateTime`之间进行转换的规则。
*   `java.time.ZoneOffset`：指定与格林威治/ UTC 时间的时区偏移。
*   [`java.time.format.DateTimeFormatter`](https://howtodoinjava.com/java/date-time/java8-datetimeformatter-example/)：提供许多预定义的格式化器，或者我们可以定义自己的格式化器。 它提供`parse()`或`format()`方法来解析和格式化日期时间值。

## 3\. 常见用例

这些示例使用 Java 8 日期时间 API 中引入的新类。

#### 3.1 获取当前日期和时间

所有日期时间类都有一个工厂方法`now()`，这是在 Java 8 中获取当前日期和时间的首选方法。

```java
LocalTime currentTime = LocalTime.now();				//13:33:43.557

LocalDate currentDate = LocalDate.now();				//2020-05-03

LocalDateTime currentDateTime = LocalDateTime.now();	//2020-05-03T13:33:43.557

```

#### 3.2 解析日期和时间

日期时间类中的`DateTimeFormatter`类和`parse()`方法帮助完成日期解析。

```java
String dateString = "2020-04-08 12:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime parsedDateTime = LocalDateTime.parse(dateString, formatter);

System.out.println(parsedDateTime);		//2020-04-08T12:30

```

#### 3.3 格式化日期和时间

日期格式通过日期时间类中的`DateTimeFormatter`类和`format()`方法来完成。

```java
//Format a date
LocalDateTime myDateObj = LocalDateTime.now();
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");

String formattedDate = myDateObj.format(myFormatObj);
System.out.println(formattedDate);	//	03-05-2020 13:46

```

## 4\. 更多例子

[Java – 获取两个日期之间的所有日期](https://howtodoinjava.com/java/date-time/dates-between-two-dates/)

[Java 8 - 获取下一个和上一个日期](https://howtodoinjava.com/java/date-time/java8-next-previous-date/)

[Java 8 - 获取当前日期时间](https://howtodoinjava.com/java/date-time/current-date-time/)

[Java 8 – 获取当前时间戳](https://howtodoinjava.com/java/date-time/get-current-timestamp/)

[Java 8 – 日期比较](https://howtodoinjava.com/java/date-time/compare-dates/)

[Java 8 - 转换为 EST 时区](https://howtodoinjava.com/java/date-time/convert-date-time-to-est-est5edt/)

[Java 8 – 测量经过时间](https://howtodoinjava.com/java/date-time/execution-elapsed-time/)

[Java 8 – 向日期添加天数](https://howtodoinjava.com/java/date-time/add-days-to-date-localdatetime/)

[Java 8 – 两个日期之间的差异](https://howtodoinjava.com/java/date-time/duration-between-two-dates/)

[Java 8 – 两个日期之间的差异](https://howtodoinjava.com/java/date-time/calculate-difference-between-two-dates-in-java/)

[Java 8 – 加或减 N 个工作日](https://howtodoinjava.com/java/date-time/add-subtract-business-days/)

[Java 8 – 计算两个日期之间的工作日](https://howtodoinjava.com/java/date-time/calculate-business-days/)

[Java 8 – 计算两个日期之间的天数](https://howtodoinjava.com/java/date-time/calculate-days-between-dates/)

[Java – 获取当前用户区域设置](https://howtodoinjava.com/java/date-time/how-to-get-current-user-locale-in-java/)

[Java – 检查给定的年份是否为闰年？](https://howtodoinjava.com/java/date-time/check-leap-year/)

[Java – 将字符串解析为日期](https://howtodoinjava.com/java/date-time/java-parse-string-to-date/)

[Java – 将`XMLGregorianCalendar`格式设置为`MM/dd/yyyy hh:mm:ss`模式](https://howtodoinjava.com/java/date-time/format-xmlgregoriancalendar-to-date-pattern/)

[Java – 将`XMLGregorianCalendar`格式化为字符串](https://howtodoinjava.com/java/date-time/xmlgregoriancalendar-date-string-example/)

[Java – 以 12 小时格式格式化日期/时间戳](https://howtodoinjava.com/java/date-time/format-time-12-hours-pattern/)

[Java – 时区转换](https://howtodoinjava.com/java/date-time/convert-date-between-timezones/)

[Java – 严格日期验证](https://howtodoinjava.com/java/date-time/strict-date-validation-simpledateformat-setlenient/)

学习愉快！

[下载源码](https://github.com/lokeshgupta1981/Core-Java/tree/master/src/com/howtodoinjava/core/datetime)