Java8新特性-新时间与日期API

总结一下java8中的新特性新时间与日期API

LocalDate、LocalTime、LocalDateTime 类的实 例是不可变的对象,分别表示使用 ISO-8601日 历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间息。也不包含与时区相关的信息。

LocalDateTime常用方法

LocalDate / LocalTime用法类似,只不过LocalDate 包含年月日LocalTime只包含时分秒

方法名 返回值类型 解释
now( ) static LocalDateTime 从默认时区的系统时钟获取当前日期
of(int year, int month, int dayOfMonth, int hour, int minute, int second) static LocalDateTime 从年,月,日,小时,分钟和秒获得 LocalDateTime的实例,将纳秒设置为零
plus(long amountToAdd, TemporalUnit unit) LocalDateTime 返回此日期时间的副本,并添加指定的数量
get(TemporalField field) int 从此日期时间获取指定字段的值为 int
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void test1(){
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);// 2020-12-10T11:48:43.387

LocalDateTime ld2 = LocalDateTime.of(2020, 12, 10, 11, 11, 10);
System.out.println(ld2);// 2020-12-10T11:11:10

LocalDateTime ldt3 = ld2.plusYears(20);
System.out.println(ldt3);// 2040-12-10T11:11:10

LocalDateTime ldt4 = ld2.minusMonths(2);
System.out.println(ldt4);// 2020-10-10T11:11:10

System.out.println(ldt.getYear());// 2020
System.out.println(ldt.getMonthValue());// 12
System.out.println(ldt.getDayOfMonth());// 10
System.out.println(ldt.getHour());// 11
System.out.println(ldt.getMinute());// 48
System.out.println(ldt.getSecond());// 43
}

时间戳Instant

Instant:用于“时间戳”的运算。它是以Unix元年(传统 的设定为UTC时区1970年1月1日午夜时分)开始 所经历的描述进行运算,也就是UTC时间或者GMT格林威治时间

GMT=UTC
UTC+8=北京时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//2. Instant : 时间戳。 (使用 Unix 元年  1970年1月1日 00:00:00 所经历的毫秒值)
@Test
public void test2(){
Instant ins = Instant.now(); //默认使用 UTC 时区
System.out.println(ins);// 2020-12-10T03:50:25.814Z

OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
System.out.println(odt);// 2020-12-10T11:50:25.814+08:00

System.out.println(ins.getNano());// 814000000

Instant ins2 = Instant.ofEpochSecond(5);
System.out.println(ins2);// 1970-01-01T00:00:05Z
}

时间 / 日期 差

  • Duration:计算两个时间之间的间隔
  • Period:计算两个日期之间的间隔
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
//Duration : 用于计算两个“时间”间隔
//Period : 用于计算两个“日期”间隔
@Test
public void test3(){
Instant ins1 = Instant.now();

System.out.println("--------------------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}

Instant ins2 = Instant.now();
// 获取两个时间间隔
Duration duration = Duration.between(ins1, ins2);
System.out.println("所耗费时间为(单位毫秒):" + duration.toMillis());// 所耗费时间为(单位秒):1001

System.out.println("----------------------------------");

LocalDate ld1 = LocalDate.now();
System.out.println("现在日期为:"+ ld1);// 现在日期为:2020-12-10
LocalDate ld2 = LocalDate.of(2011, 1, 1);
// 获取两个日期间隔
Period pe = Period.between(ld2, ld1);
System.out.println("年间隔" + pe.getYears());// 9
System.out.println("月间隔" + pe.getMonths());// 11
System.out.println("天间隔" + pe.getDays());// 9
}

时间校正器

  • TemporalAdjuster : 时间校正器。有时我们可能需要获 取例如:将日期调整到“下个周日”等操作。
  • TemporalAdjusters : 该类通过静态方法提供了大量的常 用 TemporalAdjuster 的实现。

TemporalAdjuster是一个函数接口,因此还可也用lambda表达式实现里面的接口

1
2
3
4
5
6
@FunctionalInterface
public interface TemporalAdjuster {

Temporal adjustInto(Temporal temporal);

}
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
@Test
public void test4(){
// 当前日期
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
// 本月第12天
LocalDateTime ldt2 = ldt.withDayOfMonth(12);
System.out.println(ldt2);
// 下一个周日
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt3);

//自定义:下一个工作日
LocalDateTime ldt5 = ldt.with((l) -> {
LocalDateTime ldt4 = (LocalDateTime) l;

DayOfWeek dow = ldt4.getDayOfWeek();

if(dow.equals(DayOfWeek.FRIDAY)){
return ldt4.plusDays(3);
}else if(dow.equals(DayOfWeek.SATURDAY)){
return ldt4.plusDays(2);
}else{
return ldt4.plusDays(1);
}
});

System.out.println(ldt5);

}

解析与格式化

java.time.format.DateTimeFormatter 类:该类提供了三种 格式化方法:

  • 预定义的标准格式
  • 语言环境相关的格式
  • 自定义的格式
1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void test5(){
// DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");

LocalDateTime ldt = LocalDateTime.now();
String strDate = ldt.format(dtf);

System.out.println(strDate);

LocalDateTime newLdt = ldt.parse(strDate, dtf);
System.out.println(newLdt);
}

DateTimeFormatter时间工具类,转自DateTimeFormatter时间工具类

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
 
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

/**
* @author xiaobu
* @version JDK1.8.0_171
* @date on 2019/1/11 11:52
* @description V1.0 LocalDateTime工具类
* SQL -> Java
* date -> LocalDate
* time -> LocalTime
* timestamp -> LocalDateTime
*/
public class DateTimeUtils {

public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss");
public static final DateTimeFormatter YEAR_MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM");
public static final DateTimeFormatter SHORT_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static final DateTimeFormatter SHORT_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final DateTimeFormatter LONG_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS");

/**
* 返回当前的日期
*/
public static LocalDate getCurrentLocalDate() {
return LocalDate.now();
}

/**
* 返回当前时间
*/
public static LocalTime getCurrentLocalTime() {
return LocalTime.now();
}

/**
* 返回当前日期时间
*/
public static LocalDateTime getCurrentLocalDateTime() {
return LocalDateTime.now();
}

/**
* yyyy-MM-dd
*/
public static String getCurrentDateStr() {
return LocalDate.now().format(DATE_FORMATTER);
}

/**
* yyMMdd
*/
public static String getCurrentShortDateStr() {
return LocalDate.now().format(SHORT_DATE_FORMATTER);
}

public static String getCurrentMonthStr() {
return LocalDate.now().format(YEAR_MONTH_FORMATTER);
}

/**
* yyyy-MM-dd HH:mm:ss
*/
public static String getCurrentDateTimeStr() {
return LocalDateTime.now().format(DATETIME_FORMATTER);
}


public static String getCurrentLongDateTimeStr(){
return LocalDateTime.now().format(LONG_DATETIME_FORMATTER);
}

/**
* yyMMddHHmmss
*/
public static String getCurrentShortDateTimeStr() {
return LocalDateTime.now().format(SHORT_DATETIME_FORMATTER);
}

/**
* HHmmss
*/
public static String getCurrentTimeStr() {
return LocalTime.now().format(TIME_FORMATTER);
}

public static String getCurrentDateStr(String pattern) {
return LocalDate.now().format(DateTimeFormatter.ofPattern(pattern));
}

public static String getCurrentDateTimeStr(String pattern) {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern));
}

public static String getCurrentTimeStr(String pattern) {
return LocalTime.now().format(DateTimeFormatter.ofPattern(pattern));
}

public static LocalDate parseLocalDate(String dateStr, String pattern) {
return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
}

public static LocalDateTime parseLocalDateTime(String dateTimeStr, String pattern) {
return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(pattern));
}

public static LocalTime parseLocalTime(String timeStr, String pattern) {
return LocalTime.parse(timeStr, DateTimeFormatter.ofPattern(pattern));
}

public static String formatLocalDate(LocalDate date, String pattern) {
return date.format(DateTimeFormatter.ofPattern(pattern));
}

public static String formatLocalDateTime(LocalDateTime datetime, String pattern) {
return datetime.format(DateTimeFormatter.ofPattern(pattern));
}

public static String formatLocalTime(LocalTime time, String pattern) {
return time.format(DateTimeFormatter.ofPattern(pattern));
}

public static LocalDate parseLocalDate(String dateStr) {
return LocalDate.parse(dateStr, DATE_FORMATTER);
}

public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
}

public static LocalDateTime parseLongLocalDateTime(String longDateTimeStr){
return LocalDateTime.parse(longDateTimeStr, LONG_DATETIME_FORMATTER);
}

public static LocalTime parseLocalTime(String timeStr) {
return LocalTime.parse(timeStr, TIME_FORMATTER);
}

public static String formatLocalDate(LocalDate date) {
return date.format(DATE_FORMATTER);
}

public static String formatLocalDateTime(LocalDateTime datetime) {
return datetime.format(DATETIME_FORMATTER);
}

public static String formatLocalTime(LocalTime time) {
return time.format(TIME_FORMATTER);
}

/**
* 日期相隔秒
*/
public static long periodHours(LocalDateTime startDateTime,LocalDateTime endDateTime){
return Duration.between(startDateTime, endDateTime).get(ChronoUnit.SECONDS);
}

/**
* 日期相隔天数
*/
public static long periodDays(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.DAYS);
}

/**
* 日期相隔周数
*/
public static long periodWeeks(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.WEEKS);
}

/**
* 日期相隔月数
*/
public static long periodMonths(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.MONTHS);
}

/**
* 日期相隔年数
*/
public static long periodYears(LocalDate startDate, LocalDate endDate) {
return startDate.until(endDate, ChronoUnit.YEARS);
}

/**
* 是否当天
*/
public static boolean isToday(LocalDate date) {
return getCurrentLocalDate().equals(date);
}
/**
* 获取当前毫秒数
*/
public static Long toEpochMilli(LocalDateTime dateTime) {
return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}

/**
* 判断是否为闰年
*/
public static boolean isLeapYear(LocalDate localDate){
return localDate.isLeapYear();
}
}

时区

Java 8不仅分离了日期和时间,也把时区分离出来了。现在有一系列单独的类如ZoneId来处理特定时区,ZoneDateTime类来表示某时区下的时间。这在Java 8以前都是 GregorianCalendar类来做的。下面这个例子展示了如何把本时区的时间转换成另一个时区的时间。

获取所有时区id

1
Set<String> set = ZoneId.getAvailableZoneIds();
1
2
3
4
5
6
7
8
9
// ZonedDate、ZonedTime、ZonedDateTime : 带时区的时间或日期
@Test
public void test7(){
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(ldt);

ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("US/Pacific"));
System.out.println(zdt);
}