我们知道Java8一个比较大的改动就是引入了新的表示日期和时间的API,还是很有必要抽点时间了解一下基本的用法。
Java8之前的问题
在讨论Java8的API之前,我们先看看原来API的问题。我们知道Java8之前只有java.util.Date和java.util.Calendar来表示和处理时间,它们的一些常见的问题如下:Date返回getMonth返回值为0~11,分别对应1~12月;
Calendar处理夏令时可能会引起问题;
这两个类以及DateTimeFormat都不是线程安全的;
缺乏很多时间概念,如无时区日期,时间,间隔等等;
缺乏很多常用的日期操作,如计算两个日期相差天数
JSR 310就是这样应运而生,Java8的API也是依据此规范而来。This JSR will tackle the problem of a complete date and time model, including dates and times (with and without time zones), durations and time periods, intervals, formatting and parsing.
概览包名功能java.time表示日期、时间、瞬时和期间的公共类
java.time.chrono非ISO日历系统的API
java.time.format格式化类
java.time.temporal使用fields,units,adjusters访问日期和时间
java.time.zone支持时区及其规则
常用类类功能Instant自1970年1月1日以来的一个时间点,以纳秒为单位
Duration时长,以纳秒为单位
Calendrical与底层API有关
DateTimeFields存储域——值对的一个映射,不要求一致
DayOfWeek星期中的一天
LocalDate本地日期(年月日),没有调整
LocalTime本地时间(时分秒),没有调整
LocalDateTimeLocalDate和LocalTime的组合
MonthDay月日
OffsetTime带时区的偏移时间,不包括日期或时区值
OffsetDateTime带时区偏移的日期时间,不包括时区值
Period时间长度的描述,如两个月零三天
ZonedDateTime带时区和偏移的日期时间
Year年
YearMonth年月
ZoneOffset从UTC开始的时间偏移(时分秒)
ZoneId定义一个时区,如Canada/Eastern,及其转换规则
如果对哪个类不是特别理解,打开IDE,简单的操作一下即可。
简单用例
查看当天日期1
2
3
4
5
6
7
8System.out.println(LocalDate.now());
System.out.println(LocalTime.now());
System.out.println(LocalDateTime.now());
output:
2017-01-03
16:24:11.520
2017-01-03T16:24:11.520
格式化日期和时间
下面是DateTimeFormatter类提供的格式化样式,只需简单了解一下即可,需要时可以查询DateTimeFormatter文档。
还有一个值得注意的是,模式中字母的重复次数对应这字符串预期长度。例如”MMM”对应”Jan”,””MMMM”对应”January”。你可能会好奇为什么”MMMM”为什么不是对应”Janu”,这点可以参考上面的文档,如何对应在文档中也有说明。符号含义显示形式例子G公元文本AD;Anno Domini
y公元年年份2004;04
u公元年年份公元年和y相同,公元前3年,y返回3,u返回-2
D一年中的第几天数字189
M/L月数字/文本7;07;Jul;July;J
d一月中的第几天数字10
Q/q一年中的第几季数字/文本3;03;Q3,3rd quarter
Y年年份1996;96
w一年中的某一周数字27
W一个月中的某一周数字4
e/c星期中的本地天数数字/文本2;02;Tue;Tuesday;T
E星期中的第几天文本Tue;Tuesday;T
F某月中星期几出现的序数(第几个)数字3
aAM/PM表示文本PM
h12小时制的小时数(1~12)数字12
K12小时制的小时数(0~11)数字0
k24小时制的小时数(1~24)数字24
H24小时制的小时数(0~23)数字0
m小时内第几分数字30
s一分内第几秒数字55
S秒的小数(毫秒)小数978
A千分之一天数字1234
n纳秒数字987654321
N十亿分之一(纳)天数字1234000000
V时区ID值文本America/Los_Angeles;Z;-08:30
z时区名文本Pacific Standard Time;PST
X时区偏移ZOffset-XZ;-08;-0830;-08:30;-083015;-08:30:15
x时区偏移Offset-x+0000;-08;-0830;-08:30;-083015;-08:30:15
Z时区的GMT偏移Offset-Z+0000;-0800;-08:00
O本地时区偏移Offset-OGMT+8;GMT+08:00;UTC-08:00
p填充下一个填充符11
2
3
4
5
6
7DateTimeFormatter df = DateTimeFormatter.ofPattern("yy/LL/dd");
System.out.println(df.format(LocalDate.now()));
System.out.println(LocalDate.parse("17/01/04",df));
output:
17/01/04
2017-01-04
日期和时间戳转换1
2
3
4
5
6
7
8
9
10System.out.println(ZonedDateTime.now());
System.out.println(ZonedDateTime.now().toInstant().getEpochSecond());
Instant instant = Instant.ofEpochSecond(1483492172L);
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime);
output:
2017-01-04T09:13:39.624+08:00[Asia/Shanghai]
1483492419
2017-01-04T09:09:32+08:00[Asia/Shanghai]
字符串解析为日期1
2
3
4
5
6
7
8
9
10
11
12
13
14
15LocalDate localDate = LocalDate.parse("2016-01-04");
System.out.println(localDate);
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("dd LLL yyyy");
System.out.println(pattern.format(LocalDate.now()));
//注意LocalDate是和本地相关的,所以要用一月,上面就是看看本地输出格式
DateTimeFormatter df = DateTimeFormatter.ofPattern("dd MMM yyyy");
System.out.println(LocalDate.parse("04 一月 2011", df));
output:
2016-01-04
04 一月 2017
2011-01-04
日期间的计算1
2
3
4
5
6
7
8
9
10
11LocalDate last = LocalDate.of(2016, 1, 1);
LocalDate now = LocalDate.now();
Period diff = Period.between(last, now);
System.out.println(diff);
//今天是2017/1/4
Period p = Period.ofDays(1);
System.out.println(now.plus(p));
output:
P1Y3D
2017-01-05
参考链接