在 Java8 之前为了得到一个过去或未来的日期时间我们往往需要组合 Date 和 Calendar 一起使用不幸的是这对组合并不那么好使正所谓谁用谁知道心照不宣吧

Java8 中新增了一套全新的日期时间 API它明确的将日期时间划分为 LocalDateLocalTime 以及 LocalDateTime分别用于表示日期时间和日期时间并且产生的结果是不可变的和线程安全的

Month

月份在 Java8 中声明成了枚举类型增强了代码的可读性和可靠性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 枚举类型
Month january = Month.JANUARY; // JANUARY
// 获取显示的名字
String displayName = january.getDisplayName(TextStyle.FULL, Locale.getDefault()); // 一月
// 月份+1, 得到的是2月份
Month february = january.plus(1); // FEBRUARY
// 2月份的天数最少的时候的值
int minDaysOfMonth = february.minLength(); // 28
// 2月份的天数最多的时候的值
int maxDaysOfMonth = february.maxLength(); // 29
// 获取2016年2月份的天数
int daysOfMonth = february.length(Year.isLeap(2016)); // 29
// 获取2月份表示的整数值
int februaryValue = february.getValue(); // 2
// 月份-2, 得到的是12月份
Month december = february.minus(2); // DECEMBER
// 用整数值构造月份, 1表示1月份, 4表示4月份...
Month april = Month.of(4); // APRIL

DayOfWeek

星期在 Java8 中也声明成了枚举类型增强了代码的可读性和可靠性

1
2
3
4
5
6
7
8
9
10
11
12
// 枚举类型
DayOfWeek monday = DayOfWeek.MONDAY; // MONDAY
// 获取显示的名字
String displayName = monday.getDisplayName(TextStyle.FULL, Locale.getDefault()); // 星期一
// 星期+4, 得到的是星期五
DayOfWeek friday = monday.plus(4); // FRIDAY
// 获取星期五表示的整数值
int fridayValue = friday.getValue(); // 5
// 星期-2, 得到的是星期三
DayOfWeek wednesday = friday.minus(2); // WEDNESDAY
// 用整数值构造星期, 1表示星期一, 7表示星期日...
DayOfWeek sunday = DayOfWeek.of(7); // SUNDAY

LocalDate

用于表示日期不包含时间和时区采用标准的 ISO-8601 日历日期表示方法(年-月-日, yyyy-MM-dd)如 2007-12-03

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 当前的日期
LocalDate now = LocalDate.now(); // 2016-09-19
// 获取年份值
int year = now.getYear(); // 2016
// 获取月份值
int month = now.getMonthValue(); // 9
// 获取天数值
int dayOfMonth = now.getDayOfMonth(); // 19
// 获取今天是今年的第几天
int dayOfYear = now.getDayOfYear(); // 263
// 获取月份
Month currMonth = now.getMonth(); // SEPTEMBER
// 获取星期
DayOfWeek dayOfWeek = now.getDayOfWeek(); // MONDAY
// 是否为闰年
boolean leapYear = now.isLeapYear(); // true
// 今年有多少天
int lengthOfYear = now.lengthOfYear(); // 366
// 本月有多少天
int lengthOfMonth = now.lengthOfMonth(); // 30
// 修改月份为10月
LocalDate date1 = now.withMonth(Month.OCTOBER.getValue()); // 2016-10-19
// 修改年份为2017年
LocalDate date2 = now.withYear(2017); // 2017-09-19
// 修改天数为今年的第2天
LocalDate date3 = now.withDayOfYear(2); // 2016-01-02
// 修改天数为本月的第2天
LocalDate date4 = now.withDayOfMonth(2); // 2016-09-02
// 天数+1
LocalDate date5 = now.plusDays(1); // 2016-09-20
// 月份+1
LocalDate date6 = now.plusMonths(1); // 2016-10-19
// 增加一个星期
LocalDate date7 = now.plusWeeks(1); // 2016-09-26
// 年份+1
LocalDate date8 = now.plusYears(1); // 2017-09-19
// 天数-1
LocalDate date9 = now.minusDays(1); // 2016-09-18
// 月份-1
LocalDate date10 = now.minusMonths(1); // 2016-08-19
// 减少一个星期
LocalDate date11 = now.minusWeeks(1); // 2016-09-12
// 年份-1
LocalDate date12 = now.minusYears(1); // 2015-09-19
// 构造一个日期对象
LocalDate date13 = LocalDate.of(2016, Month.OCTOBER, 1); // 2016-10-01
// 修改日期
LocalDate date14 = now.with(TemporalAdjusters.next(DayOfWeek.MONDAY)); // 2016-09-26
// 必须是严格的 yyyy-MM-dd 格式, 否则将抛出 DateTimeParseException 异常
LocalDate date15 = LocalDate.parse("2016-09-09");
// 自定义解析格式
LocalDate date16 = LocalDate.parse("2016/09/09", DateTimeFormatter.ofPattern("yyyy/MM/dd"));

除此之外用于表示日期的还有 YearMonth(年月)MonthDay(月日)Year(年)

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
28
// 当前的年月
YearMonth yearMonth1 = YearMonth.now(); // 2016-09
// 构造一个年月
YearMonth yearMonth2 = YearMonth.of(2016, Month.FEBRUARY); // 2016-02
// 本月份的天数
int lengthOfMonth = yearMonth2.lengthOfMonth(); // 29
// ----------------------------------------------------------------------
// 当前的月天
MonthDay monthDay1 = MonthDay.now(); // --09-19
// 构造一个月天
MonthDay monthDay2 = MonthDay.of(Month.FEBRUARY, 29); // --02-29
// 先后判断
boolean bool = monthDay2.isBefore(monthDay1); // true
// ----------------------------------------------------------------------
// 当前的年份
Year year = Year.now(); // 2016
// 2014年
Year year2014 = Year.of(2014);
// 判断是否为闰年
boolean leapYear1 = year2014.isLeap(); // false
// 判断是否为闰年
boolean leapYear2 = Year.isLeap(2016); // true
// 获取该年份有多少天
int length = year2014.length(); // 365

LocalTime

表示与时区无关的本地时间不包含日期采用标准的 ISO-8601 日历时间表示方法:
HH:mmHH:mm:ssHH:mm:ss.SSSHH:mm:ss.SSSSSSHH:mm:ss.SSSSSSSSS
对于某个特定的时间LocalTime 将采用其中的一个能表示它且格式是最短的一个其余位没有的则隐含为0如 10:15:30.

用法与 LocalDate 相似:

1
2
3
4
5
6
7
8
// 当前时间
LocalTime now = LocalTime.now(); // 16:14:15.809
// 获取小时
int hour = now.getHour(); // 16
// 小时+2
LocalTime time1 = now.plusHours(2); // 18:14:15.809
// 构造时间
LocalTime time2 = LocalTime.of(20, 18, 16); // 20:18:16

LocalDateTime

表示与时区无关的本地日期时间采用标准的 ISO-8601 日历日期时间表示方法按 ISO-8601 标准日期和时间的组合表示时需要在时间前面加一大写字母 T如2004年5月3日下午5点30分8秒表示成2004-05-03T17:30:08.

用法与 LocalDate 和 LocalTime 相似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 当前日期时间
LocalDateTime now = LocalDateTime.now(); // 2016-09-19T16:46:12.988
// 转化成日期
LocalDate date = now.toLocalDate(); // 2016-09-19
// 转化成时间
LocalTime time = now.toLocalTime(); // 16:46:12.988
// 构造日期时间
LocalDateTime datetime1 = LocalDateTime.of(2018, Month.APRIL, 1, 8, 30, 20); // 2018-04-01T08:30:20
// 构造日期时间
LocalDateTime datetime2 = date.atTime(8, 30, 20); // 2016-09-19T08:30:20
// 构造日期时间
LocalDateTime datetime3 = time.atDate(LocalDate.of(2016, Month.DECEMBER, 8)); // 2016-12-08T16:46:12.988
// 格式化日期时间
String formatStr = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); // 2016-09-19 16:46:12