Java DateTimeFormatter 初识(一)
📅 ( 更新 ) | 🏷️ #DateTimeFormatter文章目录
今天趁着有空闲时间看了 Java8 DateTimeFormatter 的文档总算对 Java 的时间格式有了基本的认识,这里做个笔记记录一下。
时间格式化字符串定义
该表来自于 DateTimeFormatter JDK 8 官方文档
格式字符 | 意义 | 描述 | 例子 |
G | era | text | AD; Anno Domini; A |
u | year | year | 2004; 04 |
y | year-of-era | year | 2004; 04 |
D | day-of-year | number | 189 |
M/L | month-of-year | number/text | 7; 07; Jul; July; J |
d | day-of-month | number | 10 |
Q/q | quarter-of-year | number/text | 3; 03; Q3; 3rd quarter |
Y | week-based-year | year | 1996; 96 |
w | week-of-week-based-year | number | 27 |
W | week-of-month | number | 4 |
E | day-of-week | text | Tue; Tuesday; T |
e/c | localized day-of-week | number/text | 2; 02; Tue; Tuesday; T |
F | week-of-month | number | 3 |
a | am-pm-of-day | text | PM |
h | clock-hour-of-am-pm (1-12) | number | 12 |
K | hour-of-am-pm (0-11) | number | 0 |
k | clock-hour-of-am-pm (1-24) | number | 0 |
H | hour-of-day (0-23) | number | 0 |
m | minute-of-hour | number | 30 |
s | second-of-minute | number | 55 |
S | fraction-of-second | fraction | 978 |
A | milli-of-day | number | 1234 |
n | nano-of-second | number | 987654321 |
N | nano-of-day | number | 1234000000 |
V | time-zone ID | zone-id | America/Los_Angeles; Z; -08:30 |
z | time-zone name | zone-name | Pacific Standard Time; PST |
O | localized zone-offset | offset-O | GMT+8; GMT+08:00; UTC-08:00; |
X | zone-offset 'Z' for zero | offset-X | Z; -08; -0830; -08:30; -083015; -08:30:15; |
x | zone-offset | offset-x | +0000; -08; -0830; -08:30; -083015; -08:30:15; |
Z | zone-offset | offset-Z | +0000; -0800; -08:00; |
p | pad next | pad modifier | 1 |
' | escape for text | delimiter | |
'' | single quote | literal | ' |
[ | optional section start | ||
] | optional section end | ||
'# | reserved for future use | ||
{ | reserved for future use | ||
} | reserved for future use |
年份格式
和年份有关的格式化字符有 4 个分别是: G,u,y,Y
G:纪年标志
G 纪元标识,显示当前年份属于公元前还是公元后。要注意的是:yyyy 格式下不存在公元前零年, 或者公元后零年。年份从一开始,年份值为零时对应的是公元前一年。
u,y,Y:年份标志
prolptic-year:u/Y 和 year-of-ear:y 的差别
u,y,Y 都是年份格式字符串。但是区别在于 u/Y 是 prolptic-year y 属于 year-of-era。二者的差别可详见 Stack Overflow。
简略的来说 u/Y 在年份为公元前时会将年份转换为从零开始的负数,而 y 在 转换公元前的年份时则是从一开始递增。
1DateTimeFormatter formatter =
2 DateTimeFormatter.ofPattern("'proleptic-year:' u Y G '-- era-year:' y G");
3formatter.format(LocalDate.of(2,3,1));//结果:proleptic-year: 2 2 公元 -- era-year: 2 公元
4formatter.format(LocalDate.of(1,3,1));//结果:proleptic-year: 1 1 公元 -- era-year: 1 公元
5formatter.format(LocalDate.of(0,3,1));//结果:proleptic-year: 0 0 公元前 -- era-year: 1 公元前
6formatter.format(LocalDate.of(-1,3,1));//结果:proleptic-year: -1 -1 公元前 -- era-year: 2 公元前
year-of-ear:y 和 week-based-year:Y 的差别
y 和 Y 的差别在于第一周存在跨年时 YYYY 会根据 WeekFields 中 firstDayOfWeek(每周 第一天) 和 minimalDays(当年第一周天数最小数) 属性值来计算跨年周属于哪一年。从每 周第一天开始计算如果在新年的天数大于等于第一周天数最小数那么跨年周属于新年的第一 周,否则属于旧年的最后一周。同时改周内所有的天数年分都会被设定为周所在年份,这也 就是为什么不推荐使用 YYYY 格式化年份的原因。
DateTimeFormatter 中 WeekFields 上述两个字段的默认值由 Locale 决定。WeekFields 默认有两种规则 ISO(起始天为周一,第一周最少 4 天)和 SUNDAY_START(起始天为周四, 第一周最少 1 天) 。
要注意的是 Locale.CHINA 默认使用的是 SUNDAY_START。
1 LocalDate date = LocalDate.of(2022, 1, 1);
2 DateTimeFormatter formatterUK =
3 DateTimeFormatter.ofPattern("YYYY-MM-dd '第'ww'周'", Locale.UK);
4 DateTimeFormatter formatterCN =
5 DateTimeFormatter.ofPattern("YYYY-MM-dd '第'ww'周'",Locale.CHINA);
6 System.out.printf("中国时间:%s\n",formatterCN.format(date));//结果:中国时间:2022-01-01 01
7 System.out.printf("英国时间:%s\n",formatterUK.format(date));//结果:英国时间:2021-01-01 52 因为跨年周在2021年有5天所以被判定为 2021 年
季度格式
季度相关的格式化字符只有 Q/q 两个,规则都是从一月开始每三个月算一个季度。 唯一不同的在于格式化结果不一样,q 格式除了 qq 显示 01 外,其他数量的 q 都显示为 1 。 而 Q 格式则是不同数量的 Q 在不同地区下有着不同的格式化结果。
格式 | 英语地区 | 中文地区 |
Q | 1 | 1 |
01 | 01 | |
QQQ | Q1 | 1 季 |
QQQQ | 1st quarter | 第 1 季度 |
QQQQQ | 1 | 1 |
月份格式
月份格式也只有两个: M/L ,两个格式大同小异,区别在于 M 能支持更多的格式结果
格式 | 英语地区 | 中文地区 |
M/L | 1/1 | 1/1 |
MM/LL | 01/01 | 01/01 |
MMM/LLL | Jan/1 | 一月/一月 |
MMMM/LLLL | January/1 | 一月/一月 |
MMMMM/LLLLL | J/1 | 1/一月 |
周格式
周格式有三个:W(基于月的周数),w(基于 Y 格式的周数)。
其中格式 w 在遭遇跨年时会按照 WeekFields 的规则来进行周数判断,格式化的结果时该
周在当年属于第几周。
而格式 W ,则是在遭遇跨月时按照 WeekFields 的规则来判断。如
果该周在新月份中的天数小于 WeekFields 中的一周最小天数,那么结果为 0 ,反之为 1。
时间 | 格式 | 英语地区 | 中文地区 |
2022-01-01 | W/w | 0/52 | 1/1 |
2022-01-05 | W/w | 1/1 | 2/2 |
2022-04-01 | W/w | 0/13 | 1/14 |
天格式
关于天的格式有:D, d , E , F , e , c
格式 | 规则 | 日期例子 | 结果 | 备注 |
D | 查找该天在当年是第几天 | 2022-02-10 | 41 | |
d | 查找该天在当月是第几天 | 2022-02-10 | 10 | |
E | 查找该天在当周是第几天 | 2022-02-10 | Thu;Thursday;星期四 | 受地区影响有本地化输出 |
e/c | 根据 WeekFields 的firstDayOfWeek 来判定该天在当周是第几天 | 2022-02-10 | 4 | 受地区影响有本地化输出 |
F | 把每月一号当作第一周的第一天,来计算当天属于周内第几天 | 2022-02-10 | 3 | JDK8 官方文档错误,11 已纠正 |
小时格式
关于小时的格式有:a,h,K,k,H
格式 | 规则 | 日期例子 | 结果 | 备注 |
a | 上午还是下午标志 | 2022-02-10 13:00:00 | PM;下午 | 受Local 影响有本地化输出 |
h | 时钟式时间 1-12 | 2022-02-10 13:00:00 | 1;01 | 12:00 输出为 12 |
K | 12小时制时间 0-11 | 2022-02-10 13:00:00 | 1;01 | 12:00 输出为 00 |
k | 时钟式时间 1-24 | 2022-02-10 13:00:00 | 13 | 00:00 输出为 24 |
H | 24小时制 0-23 | 2022-02-10 13:00:00 | 13 | 00:00 输出为 00 |
分秒格式
关于分和秒的格式有: m,s,S,A,n,N
格式 | 规则 | 日期例子 | 结果 | 备注 |
m | 小时内的分钟值 | 13:10:00 | 10 | |
s | 分钟内的秒值 | 13:10:11 | 11 | |
S | 毫秒值 0-999 | 13:10:12.434 | 434 | |
A | 对应时间是当天的第多少毫秒 | 14:00:00.123 | 50400123 | 一秒等于一千毫秒 |
n | 秒内的纳秒数 | 14:00:00.123 | 123000000 | 一百万纳秒等于一毫米 |
N | 对应时间是当天的第多少纳秒 | 14:00:00.123 | 50400123000000 |
额外格式
格式 | 规则 | 日期例子 | 结果 | 备注 |
VV | 输出当前时区Id | 14:00:00 | Asia/Shanghai | 1.只接受VV,其他个数的V会抛出异常。2.只能用来格式化 ZonedDateTime |
z | 输出当前时区名 | 14:00:00 | CST | 注意美国中部时间和北京时间都是 CST |