1
2
3
4
java.lang.Object
└── java.text.Format
└── java.text.DateFormat
└── java.text.SimpleDateFormat

SimpleDateFormat是格式和语言环境敏感的方式解析一个类的具体日期。可以格式化(日期→文本),分析(文本→日期),和归一化。

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class FormatTest {

public static void main(String[] args) {
//实例化转换规则
//常用格式
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//Date格式的字符串转Date格式
SimpleDateFormat formatDate = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy",Locale.ENGLISH);

//Date转String 返回2018-4-3 16:42:23
String datetimeS = format.format(new Date());

//Date格式的字符串转Date 返回Tue Apr 03 16:43:46 CST 2018
try {
Date date = formatDate.parse((new Date()).toString());
} catch (ParseException e) {
e.printStackTrace();
}
}
}

SimpleDateFormat参数

这里只介绍本文使用到的参数,其他参数请参照API文档
当在实例化规则时
SimpleDateFormat format = new SimpleDateFormat();
()中的字符将被解释为规则,使用'可以避免解释
例如yyyy-MM-dd's可以被解释为年-月-日s,即2018-04-03s,其中s不会被解释
解释参数如下:

参数 作用
y
M
d
H
m
s

不同参数不同数量有着不同的解释
M ,当只有一个或两个M参与解释时,将被解释为number类型,即四月的输出结果为 404 (这里M的数量决定了 4 还是 04 ,一个M对应 4,两个M在月份长度不超过两位时自动补全为两位)
M的数量超过两位时,就会被解释为Text类型,如 MMM 的四月的输出结果为 Apr(这里M的数量对应简写的长度)

各个参数更详细的对应关系请参考API文档

Date格式

Java中Date的格式默认为星期简写 月份简写 日期 时间 时区缩写 年份

源码学习

在阅读源码之前,可以先看看 SimpleDateFormat 的继承关系,如下:

1
2
3
4
java.lang.Object
└── java.text.Format
└── java.text.DateFormat
└── java.text.SimpleDateFormat

以下引用于 java.text.Format

Subclassing

The Java Platform provides three specialized subclasses of Format– DateFormat, MessageFormat, and NumberFormat–for formatting dates, messages, and numbers, respectively.

Concrete subclasses must implement three methods:

  1. format(Object obj, StringBuffer toAppendTo, FieldPosition pos)
  2. formatToCharacterIterator(Object obj)
  3. parseObject(String source, ParsePosition pos)

上面那段的意思是 java.text.Format 就是官方提供了三个子类,分别格式化日期、数字、消息。而格式化日期的子类就是 SimpleDateFormat 的父类 DateFormat,主要提供字符串转日期类和日期类转字符串。
其中,三个子类都必须实现三个功能,分别是对象转字符串,生成中间对象 AttributedCharacterIterator (k-v 类型),字符串转对象。
接下来看一下子类 DateFormat 是怎么继承这三个接口的。

format

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public final StringBuffer format(Object obj, StringBuffer toAppendTo,
FieldPosition fieldPosition)
{
if (obj instanceof Date)
return format( (Date)obj, toAppendTo, fieldPosition );
else if (obj instanceof Number)
return format( new Date(((Number)obj).longValue()),
toAppendTo, fieldPosition );
else
throw new IllegalArgumentException("Cannot format given Object as a Date");
}

public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition fieldPosition);

public final String format(Date date)
{
return format(date, new StringBuffer(),
DontCareFieldPosition.INSTANCE).toString();
}

parseObject

1
2
3
4
5
6
7
8
9
10
11
public abstract Object parseObject (String source, ParsePosition pos);

public Object parseObject(String source) throws ParseException {
ParsePosition pos = new ParsePosition(0);
Object result = parseObject(source, pos);
if (pos.index == 0) {
throw new ParseException("Format.parseObject(String) failed",
pos.errorIndex);
}
return result;
}

未完待续…