# Java – 日期格式

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

学习在 Java 8 中将**日期格式化为字符串**。我们将学习  Java 7 中的[`DateTimeFormatter`](https://howtodoinjava.com/java/date-time/java8-datetimeformatter-example/)的*自定义模式*和`SimpleDateFormat`的*内置模式*。

## 1\. `DateTimeFormatter` – Java 8

在 Java 8 中，我们可以将`DateTimeFormatter`用于所有类型的日期和时间相关的格式化任务。 它是[**线程安全的**](https://howtodoinjava.com/java/multi-threading/what-is-thread-safety/)或[不可变的](https://howtodoinjava.com/java/basics/how-to-make-a-java-class-immutable/) ，因此可以在并发环境中使用而没有风险。

#### 1.1 日期格式示例

Java 8 示例，以所需的字符串模式格式化`LocalDateTime`和`LocalDate`实例。

```java
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class DateFormatting 
{
	public static void main(String[] args) 
	{
		String dateTimeString = formatLocalDateTime(LocalDateTime.now()); 
		System.out.println(dateTimeString);  //2020-05-08 23:17:22 PM

		String dateString = formatLocalDate(LocalDate.now()); 
		System.out.println(dateString);  //2020-05-08
	}

	//Format LocalDateTime to String

	public static final String TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss a"; 
	public static final DateTimeFormatter LDT_FOMATTER 
                      = DateTimeFormatter.ofPattern(TIMESTAMP_PATTERN);

	private static String formatLocalDateTime(LocalDateTime ldt)
	{
		return LDT_FOMATTER.format(ldt);
	}

	//Format LocalDate to String

	public static final String DATE_PATTERN = "yyyy-MM-dd"; 
	public static final DateTimeFormatter LD_FOMATTER 
                      = DateTimeFormatter.ofPattern(DATE_PATTERN);

	private static String formatLocalDate(LocalDate ld)
	{
		return LD_FOMATTER.format(ld);
	}
}

```

#### 1.2 模式串

`DateTimeFormatter`提供了两种方法来定义模式：

*   将近 15 种内置的**预定义模式**，例如 `ISO_LOCAL_DATE`（`2011-12-03`）或`ISO_OFFSET_DATE_TIME`（`2011-12-03T10:15:30+01:00`）
*   使用`DateTimeFormatter.ofPattern(pattern)`的任何**自定义样式**

定制模式串可以具有任意数量的具有自己含义的预定义字母和符号。 最常用的符号是：`Y, M, D, h, m, s`。

另请注意，模式中字母的重复次数也具有不同的含义。 例如，`MMM`给出`Jan`，而`MMMM`给出`January`。

让我们看看这些符号以供快速参考。

| 符号 | 含义 | 类型 | 示例 |
| --- | --- | --- | --- |
| `G` | 时代 | `String` | `AD`；`Anno Domini` |
| `y` | 时代中的一年 | `Year` | 2004 或 04 |
| `u` | 时代中的一年 | `Year` | 与`y`类似，但返回年份。 |
| `D` | 一年中的一天 | `Number` | 235 |
| `M / L` | 一年中的一月 | `Number`/`String` | 7 或 07； `J`或`Jul`或`July` |
| `d` | 一月中的一天 | `Number` | 21 |
| `Q / q` | 一年中的季度 | `Number` / String | 3 或 03；`Q3`或`3rd quarter` |
| `Y` | 基于周的年份 | `Year` | 1996 或 96 |
| `w` | 一年中的一周 | `Number` | 32 |
| `W` | 一月中的一周 | `Number` | 3 |
| `e / c` | 本地化一周中的一天 | `Number`/`String` | 2 或 02；`T`或`Tue`或`Tuesday` |
| `E` | 一周中的一天 | `String` | `T`或`Tue`或`Tuesday` |
| `F` | 一月中的一周 | `Number` | 3 |
| `a` | 一天的上午/下午 | `String` | `PM` |
| `h` | 上午/下午的小时（1-12） | `Number` | 12 |
| `K` | 上午/下午的小时（0-11） | `Number` | 0 |
| `k` | 一天中的小时（1-24） | `Number` | 15 |
| `H` | 一天中的小时（0-23） | `Number` | 15 |
| `m` | 小时中的分钟 | `Number` | 30 |
| `s` | 分钟中的秒钟 | `Number` | 55 |
| `S` | 秒钟的小数 | `Fraction` | 978 |
| `A` | 一天中的毫秒 | `Number` | 1234 |
| `n` | 秒钟中的纳秒 | `Number` | 987654321 |
| `N` | 一天中的纳秒 | `Number` | 1234560000 |
| `V` | 时区编号 | `Zone-id` | `America/Los_Angeles` 或`Z`或`–08:30` |
| `z` | 时区名称 | `Zone-name` | `Pacific Standard Time`或`PST` |
| `X` | 区域偏移（`Z`代表零） | `Offset-X` | `Z`或`–08`或`–0830`或`–08:30`或`–083015`或`–08:30:15` |
| `x` | 区域偏移 | `Offset-x` | `+0000`或`–08`或`–0830`或`–08:30`或`–083015`或`–08:30:15` |
| `Z` | 区域偏移 | `Offset-Z` | `+0000`或`–0800`或`–08:00` |
| `O` | 本地区域偏移 | `Offset-O` | `GMT+8`或`GMT+08:00`或`UTC–08:00` |
| `p` | 填充 | 填充修饰符 | 1 |

#### 1.3 `UnsupportedTemporalTypeException`

如果我们尝试将`DateTimeFormatter`与日期时间实例不支持的模式一起使用，则其`format()`将引发此异常。

例如，如果我们尝试使用包含小时和分钟的模式格式化`LocalDate`，则将引发此异常，因为`LocalDate`不支持任何时间信息。

```java
public static final String TIMESTAMP_PATTERN 
						= "yyyy-MM-dd HH:mm:ss a"; 
public static final DateTimeFormatter FOMATTER 
						= DateTimeFormatter.ofPattern(TIMESTAMP_PATTERN);

String formmatedString = FOMATTER.format( LocalDate.now() );

```

```java
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay
	at java.base/java.time.LocalDate.get0(LocalDate.java:709)
	at java.base/java.time.LocalDate.getLong(LocalDate.java:688)
	at java.base/java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:308)
	at java.base/java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2704)
	at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2343)
	at java.base/java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1847)
	at java.base/java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1821)
	at com.howtodoinjava.core.datetime.DateFormatting.formatLocalDate(DateFormatting.java:33)
	at com.howtodoinjava.core.datetime.DateFormatting.main(DateFormatting.java:21)

```

## 2\. `SimpleDateFormat` – Java 7

如果您仍然停留在 Java 7 上并且由于某些旧版应用程序的依赖性而无法升级，则可以使用`SimpleDateFormat`进行日期格式化。

尽管`SimpleDateFormat`不是线程安全的或不可变的，但它仍然可以很好地达到目的。 不要在具有同步功能的多线程环境中使用此类。

```java
import java.text.SimpleDateFormat;
import java.util.Date;

public class JavaDateValidations 
{
	public static final String TIMESTAMP_PATTERN 
							= "yyyy-MM-dd HH:mm:ss a"; 

	public static void main(String[] args) 
	{
		SimpleDateFormat sdf = new SimpleDateFormat(TIMESTAMP_PATTERN);

		Date date = new Date();

		String formattedDate = sdf.format(date);
		System.out.println(formattedDate);		//2020-05-09 00:32:28 AM
	}
}

```

## 3\. 总结

如果您有将 Java 7 应用程序升级到 Java 8 的自由，请优先执行。 就性能而言，`DateTimeFormatter`的线程安全性和不变性是对`SimpleDateFormat`的巨大胜利。

这两个类都提供了`format()`示例，用于将日期对象格式化为字符串。

在评论中给我您有关 Java 日期格式化器示例的问题和建议。

学习愉快！

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