关于lambda表达式、streamAPI、Optional和新的日期时间API的总结
JDK1.8新特性
lambda
以函数作为方法的参数
Java8中常用的函数式接口
函数式接口使用例子
Stream API
什么是流?
流是Java8引入的全新概念,它用来处理集合中的数据,暂且可以把它理解为一种【高级集合】。 众所周知,集合操作非常麻烦,若要对集合进行筛选、投影,需要写大量的代码,而流是以声明的形式操作集合,它就像SQL语句,我们只需告诉流需要对集合进行什么操作,它就会自动进行操作,并将执行结果交给你,无需我们自己手写代码。 因此,流的集合操作对我们来说是透明的,我们只需向流下达命令,它就会自动把我们想要的结果给我们。由于操作过程完全由Java处理,因此它可以根据当前硬件环境选择最优的方法处理,我们也无需编写复杂又容易出错的多线程代码了。
流的特点
- 【只能遍历一次】 我们可以把流想象成一条流水线,流水线的源头是我们的数据源(一个集合),数据源中的元素依次被输送到流水线上,我们可以在流水线上对元素进行各种操作。 一旦元素走到了流水线的另一头,那么这些元素就被“消费掉了”,我们无法再对这个流进行操作。当然,我们可以从数据源那里再获得一个新的流重新遍历一遍。
- 采用【内部迭代】方式 若要对集合进行处理,则需我们手写处理代码,这就叫做外部迭代。 而要对流进行处理,我们只需告诉流我们需要什么结果,处理过程由流自行完成,这就称为内部迭代。
流的操作分类
流的操作分为两种,分别为中间操作和终端操作。
- 中间操作 当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“中间操作”。 【中间操作仍然会返回一个流对象】,因此多个中间操作可以串连起来形成一个流水线。
- 终端操作 当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终端操作。 【终端操作将返回一个执行结果】,这就是你想要的数据。
中间操作和终端操作汇总
流的操作过程
- 准备数据源
- 执行中间操作,可以有多个中间操作
- 执行终端操作,本次流执行结束,获取结果
如何获取流?
通过集合【最常用】
通过集合的Stream方法
1
2List<Person> people = new ArrayList<>();
Stream<Person> stream = people.stream();通过数组
通过数组的Arrays的stream静态方法可以获取
1
2String[] strings = new String[]{};
Stream<String> stream = Arrays.stream(strings);值
直接将几个值变为stream流
1
Stream<String> stringStream = Stream.of("1", "2", "3");
文件,注意这里可不是文件的IO流
1
2
3
4try(Stream lines = Files.lines(Paths.get("test.txt"), Charset.defaultCharset())){
//可对lines做一些操作
}catch(IOException e){
}iterate,无限流
返回通过将函数f迭代应用到初始元素seed产生的无限顺序有序Stream ,产生由seed 、 f(seed) 、 f(f(seed))等组成的Stream 。
1
Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);
中间操作
常用 filter、map、limit、skip、sorted、distinct
筛选 filter:简而言之就是把符合括号中条件的值筛选出来
filter 函数接收一个Lambda表达式作为参数,该表达式返回boolean,在执行过程中,流将元素逐一输送给filter,并筛选出执行结果为true的元素。
1
2
3
4
5
6
7
8// 筛选出不为空的字符串
List<String> strings = Arrays.asList("hc", "", "zs", "H", "I");
strings.stream().filter(e -> !e.isEmpty()).forEach(System.out::println);
//结果
hc
zs
H
I去重 distinct:就是去掉重复的结果
1
2
3
4
5
6
7List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().distinct().forEach(System.out::println);
// 结果
3
2
7
5截取 limit:截取前n个元素
1
2
3
4
5List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().limit(2).forEach(System.out::println);
// 结果
3
2跳过 skip:跳过前n个元素
1
2
3
4
5
6
7
8List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().skip(2).forEach(System.out::println);
// 结果
2
3
7
3
5映射 map:将流中的每个元素按照map的括号中lambda表达式的逻辑进行计算,然后变成计算后的样子。对流中的【每个元素】执行一个函数,使得【元素转换成另一种类型输出】。流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。 如,获取每个人的姓名(实则是将Perosn类型转换成String类型):
1
2List<Person> personList = getPersonList();
List<String> collect = personList.stream().map(Person::getName).collect(Collectors.toList());排序 sorted,对流进行排序 默认自然序升序,想降序的话使用 sorted(Comparator.reverseOrder())
1
2
3
4
5
6
7
8
9
10List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().sorted().forEach(System.out::println);
// 返回值
2
2
3
3
3
5
7展平 flatMap:当你想要让一个值转换为另一个值的时候可以用map,但是当想要用一个值获取多个值,然后还想把这多个值都装到一个list里面,就该考虑用flatMap了,展平map!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/**
* flatMap,当你想要让一个值转换为另一个值的时候可以用map,但是当想要用一个值获取多个值,然后还想
* 把这多个值都装到一个list里面,就该考虑用flatMap了,展平map!
*/
private static void flatMapOperation(){
// 场景:列出list中各不相同的单词
List<String> list = new ArrayList<String>();
list.add("I am a boy");
list.add("I love the girl");
list.add("But the girl loves another girl");
// 先切分句子得出每个单词,切分肯定会得到若干个String[],怎么把这么多的String[]整合到一个Stream<String>里面呢?
// 使用flatMap,展平为Stream<String>
// 然后去重,再合并为一个list
List<String> collect = list.stream().map(line -> line.split(" "))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
collect.forEach(System.out::println);
}
终端操作
常用 allMatch、anyMatch、noneMatch、findAny、findFirst
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17private static void endOperation() {
List<Integer> numbers = Arrays.asList(2, 3, 2, 3, 7, 3, 5);
// allMatch 是否匹配所有元素,判断流中所有元素是否都符合指定条件
// 流中元素是否都小于10 true
System.out.println(numbers.stream().allMatch(num -> num < 10));
// anyMatch 用于判断流中是否存在至少一个元素满足指定的条件
// 流中元素至少有一个是等于5的 true
System.out.println(numbers.stream().anyMatch(num -> num == 5));
// noneMatch 与allMatch相反,判断流中所有元素是否都不符合指定条件
// 流中元素都不小于10 false
System.out.println(numbers.stream().noneMatch(num -> num < 10));
// findAny 从流中随便选一个元素出来,返回的是Optional类型的元素
Optional<Integer> any = numbers.stream().findAny();
System.out.println(any);
// findFirst 取流中第一个元素 返回的是Optional类型的元素
System.out.println(numbers.stream().findFirst());
}归约:指将集合中的元素经过指定运算,折叠成一个元素输出,如:求平均值、最值等等,在流中,reduce能够实现归约。
reduce接收两个参数:1.初始值 2.进行归约操作的lambda表达式
1
2
3
4
5
6
7
8
9
10
11List<Integer> numbers = Arrays.asList(2, 3, 2, 3, 7, 3, 5);
// 第一个参数的含义:表示reduce计算的初始值是0
// 第二个参数的含义:是一个两个参数的lambda表达式,表示要进行的归约操作
// reduce会把流中元素两两输给lambda表达式,最后将计算出累加之和
Integer reduce = numbers.stream().reduce(0, (num1, num2) -> num1 + num2);
// 上面的还可以这样写,使用Integer自带的sum方法,这么着得话,Integer的min,max方法也都可以用
Integer reduce1 = numbers.stream().reduce(0, Integer::sum);
System.out.println(reduce);
// 求numbers中的最大值,这里不加第一个参数了,直接进行函数里的计算
Optional<Integer> reduce2 = numbers.stream().reduce(Integer::min);
System.out.println(reduce2);数值流:Stream API提供了三种数值流:IntStream、DoubleStream、LongStream
也提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong,采用reduce进行数值操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低。当流操作为纯数值操作时,使用【数值流能获得较高的效率】。
1
2
3
4IntStream intStream = numbers.stream().mapToInt(num -> num);
// 每种数值流也都有计算函数如max、min、sum
OptionalInt max = numbers.stream().mapToInt(num -> num).max();
System.out.println(max);collect
干掉空指针之Optional
参考:
新的日期时间API
常用的日期时间类
Java8日期时间类相关API说明,涉及到localDate、localTime、localDateTime、instant、duration、period
LocalDate
LocalDate类表示一个具体的日期,但不包含具体时间,也不包含时区信息。可以通过LocalDate的静态方法of()创建一个实例,LocalDate也包含一些方法用来获取年份,月份,天,星期几等。
代码演示
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/**
* LocalDate API使用
* LocalDate类表示一个具体的日期,但不包含具体时间,也不包含时区信息。
* 可以通过LocalDate的静态方法of()创建一个实例
* LocalDate也包含一些方法用来获取年份,月份,天,星期几等
*/
private static void localDate() {
// 初始化日期 2021-10-02
LocalDate localDate = LocalDate.of(2021, 10, 2);
// 也可以通过静态方法now() 来获取当前日期
LocalDate now = LocalDate.now();
System.out.println("当前日期:" + now);
// 获取年份
int year = localDate.getYear();
// 获取月份枚举
Month month = localDate.getMonth();
// 获取当前时间是当前月中的第几天
int dayOfMonth = localDate.getDayOfMonth();
// 获取当前日期是本周第几天 也就是周几 返回的是一个week的枚举
DayOfWeek dayOfWeek = localDate.getDayOfWeek();
// 获取当前月一共有几天
int lengthOfMonth = localDate.lengthOfMonth();
// 是否为闰年
boolean leapYear = localDate.isLeapYear();
System.out.println("当前年份:" + year + " 当前月份:" + month + " 当前天是当前月的第几天:" + dayOfMonth
+ " 当前天是本周第几天:" + dayOfWeek + " 当前月共多少天:" + lengthOfMonth + " 是否为闰年:" + leapYear);
}运行结果
1
2当前日期:2021-10-05
当前年份:2021 当前月份:OCTOBER 当前天是当前月的第几天:2 当前天是本周第几天:SATURDAY 当前月共多少天:31 是否为闰年:false
LocalTime
LocalTime和LocalDate类似,LocalTime是针对具体时间来说的,比如时分秒;LocalDate是针对日期的,比如年月日
代码演示
1
2
3
4
5
6
7
8
9
10
11
12/**
* LocalTime API 使用
* LocalTime和LocalDate类似,LocalTime是针对具体时间来说的,比如时分秒;LocalDate是针对日期的,比如年月日
*/
private static void localTime() {
LocalTime localTime = LocalTime.of(22, 23, 16);
System.out.println("LocalTime:" + localTime);
int hour = localTime.getHour();
int minute = localTime.getMinute();
int second = localTime.getSecond();
System.out.println("时分秒:" + hour + ":" + minute + ":" + second);
}运行结果
1
2LocalTime:22:23:16
时分秒:22:23:16
LocalDateTime
LocalDateTime是LocalDate和LocalTime的结合,拥有年月日时分秒
代码演示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/**
* LocalDateTime API使用
* LocalDateTime是LocalDate和LocalTime的结合,拥有年月日时分秒
*/
private static void localDateTime() {
// 通过年月日时分秒创建
LocalDateTime of = LocalDateTime.of(2021, 10, 2, 22, 30, 16);
// 也可以通过localDate和localTime对象创建
LocalDate localDate = LocalDate.of(2021, 10, 2);
LocalTime localTime = LocalTime.of(22, 23, 16);
LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
// 也可以通过localDate.atTime()
LocalDateTime atTime = localDate.atTime(localTime);
// 也可以通过localTime.atDate()
LocalDateTime atDate = localTime.atDate(localDate);
// localDateTime也可以取出localDate和localTime
LocalDate toLocalDate = localDateTime.toLocalDate();
LocalTime toLocalTime = localDateTime.toLocalTime();
}
Instant
Instant用于表示一个时间戳,它与我们常使用的System.currentTimeMillis()有些类似,不过Instant可以精确到纳秒(Nano-Second),System.currentTimeMillis()方法只精确到毫秒(Milli-Second)。如果查看Instant源码,发现它的内部使用了两个常量,seconds表示从1970-01-01 00:00:00开始到现在的秒数,nanos表示纳秒部分(nanos的值不会超过999,999,999)。Instant除了使用now()方法创建外,还可以通过ofEpochSecond方法创建
代码演示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/**
* Instant用于表示一个时间戳,它与我们常使用的System.currentTimeMillis()有些类似
* 不过Instant可以精确到纳秒(Nano-Second),System.currentTimeMillis()方法只精确到毫秒(Milli-Second)
* 如果查看Instant源码,发现它的内部使用了两个常量,seconds表示从1970-01-01 00:00:00开始到现在的秒数,nanos表示纳秒部分(nanos的值不会超过999,999,999)
* Instant除了使用now()方法创建外,还可以通过ofEpochSecond方法创建:
*/
private static void instant() {
// 第一个参数是秒,第二个参数是纳秒
// 下面代码表示从1970-01-01 00:00:00开始后两分钟的10万纳秒的时刻
Instant instant = Instant.ofEpochSecond(120, 100000);
System.out.println(instant);
Instant now = Instant.now();
System.out.println(now);
}运行结果
1
21970-01-01T00:02:00.000100Z
2021-10-05T12:18:14.931Z
Duration
Duration的内部实现与Instant类似,也是包含两部分:seconds表示秒,nanos表示纳秒。两者的区别是Instant用于表示一个时间戳(或者说是一个时间点),而Duration表示一个时间段,所以Duration类中不包含now()静态方法。可以通过Duration.between()方法创建Duration对象。
代码演示
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/**
* Duration的内部实现与Instant类似,也是包含两部分:seconds表示秒,nanos表示纳秒。
* 两者的区别是Instant用于表示一个时间戳(或者说是一个时间点),而Duration表示一个时间段,
* 所以Duration类中不包含now()静态方法。可以通过Duration.between()方法创建Duration对象
*/
private static void duration() {
// 当前时间
LocalDateTime from = LocalDateTime.of(2021, 10, 4, 19, 41, 16);
// 火车发车时间
LocalDateTime to = LocalDateTime.of(2021, 10, 7, 11, 58, 00);
// 看看距离火车发车还有多长时间2333333
Duration duration = Duration.between(from, to);
long days = duration.toDays();
long hours = duration.toHours();
long minutes = duration.toMinutes();
long seconds = duration.getSeconds();
long millis = duration.toMillis();
long nanos = duration.toNanos();
System.out.println("距离发车还有:" + days + "天");
System.out.println("距离发车还有:" + hours + "小时");
System.out.println("距离发车还有:" + minutes + "分钟");
System.out.println("距离发车还有:" + seconds + "秒");
System.out.println("距离发车还有:" + millis + "毫秒");
System.out.println("距离发车还有:" + nanos + "纳秒");
// 其他创建duration对象的方法,第一个参数是时长,第二个参数是时间单位
Duration of = Duration.of(5, ChronoUnit.DAYS);
System.out.println(of.toDays());
}运行结果
1
2
3
4
5
6
7距离发车还有:2天
距离发车还有:64小时
距离发车还有:3856分钟
距离发车还有:231404秒
距离发车还有:231404000毫秒
距离发车还有:231404000000000纳秒
5
Period
Period在概念上和Duration类似,区别在于Period是以年月日来衡量一个时间段
代码演示
1
2
3
4
5
6
7
8
9/**
* Period在概念上和Duration类似,区别在于Period是以年月日来衡量一个时间段
*/
private static void period() {
// 两年六个月三天
Period period = Period.of(2, 6, 3);
// 形容一段时间
Period between = Period.between(LocalDate.of(2021, 10, 4), LocalDate.of(2023, 10, 4));
}
日期操作和格式化
日期相关操作,加减日期,修改日期等等
代码演示
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/**
* 日期操作
*/
private static void dateOperation() {
// 简单操作 - 直接改日期
LocalDate localDate = LocalDate.of(2021, 10, 4);
// 将日期中的年改为2022年
LocalDate withYear = localDate.withYear(2022);
// 将月份改为12月
LocalDate withMonth = localDate.withMonth(12);
// 修改天
LocalDate withDayOfMonth = localDate.withDayOfMonth(2);
// 改为2022年12月02日
LocalDate date = localDate.withYear(2022).withMonth(12).withDayOfMonth(2);
System.out.println("withYear:" + withYear);
System.out.println("withMonth:" + withMonth);
System.out.println("withDayOfMonth:" + withDayOfMonth);
System.out.println("date:" + date);
// 简单操作 - 日期加减
// 加两年
LocalDate plusYears = localDate.plusYears(2);
// 减去俩月
LocalDate minusMonths = localDate.minusMonths(2);
// 加五天
LocalDate plus = localDate.plus(2, ChronoUnit.DAYS);
System.out.println("plusYears:" + plusYears);
System.out.println("minusMonths:" + minusMonths);
System.out.println("plus:" + plus);
// 更灵活的操作,使用with方法+TemporalAdjuster,TemporalAdjusters类中包含了很多静态方法可以直接使用
// 返回下一个距离当前日期最近的星期日
LocalDate with1 = localDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
// 返回本月最后一个星期六
LocalDate with2 = localDate.with(TemporalAdjusters.lastInMonth(DayOfWeek.SATURDAY));
System.out.println("with1:" + with1);
System.out.println("with2:" + with2);
// 自定义操作日期 - 给定一个日期,计算该日期的下一个工作日(就是跳过星期六和星期天)
LocalDate testDate = LocalDate.of(2021, 10, 4);
LocalDate with3 = testDate.with(temporal -> {
DayOfWeek dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
// 正常情况,每次增加一天
int dayToAdd = 1;
// 如果是星期五,加三天
if (dayOfWeek == DayOfWeek.FRIDAY) {
dayToAdd = 3;
}
// 如果是周六,加两天
if (dayOfWeek == DayOfWeek.SATURDAY) {
dayToAdd = 2;
}
return temporal.plus(dayToAdd, ChronoUnit.DAYS);
});
System.out.println("with3:" + with3);
}运行结果
1
2
3
4
5
6
7
8
9
10withYear:2022-10-04
withMonth:2021-12-04
withDayOfMonth:2021-10-02
date:2022-12-02
plusYears:2023-10-04
minusMonths:2021-08-04
plus:2021-10-06
with1:2021-10-10
with2:2021-10-30
with3:2021-10-05
对于更灵活的操作,需要使用with方法+TemporalAdjuster,TemporalAdjusters类中包含了很多静态方法可以直接使用,TemporalAdjusters类中包含了很多静态方法可以直接使用,下面的表格列出了一些方法:
日期格式化
新的日期API中提供了一个DateTimeFormatter类用于处理日期格式化操作,它被包含在java.time.format包中,Java 8的日期类有一个format()方法用于将日期格式化为字符串。
该方法接收一个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/**
* 格式化日期
* 新的日期API中提供了一个DateTimeFormatter类用于处理日期格式化操作
* 它被包含在java.time.format包中,Java 8的日期类有一个format()方法用于将日期格式化为字符串
* 该方法接收一个DateTimeFormatter类型参数
*/
private static void dateFormat() {
// 2021-10-04T22:34:19.059
LocalDateTime now = LocalDateTime.now();
// 20211004
String basicIsoDate = now.format(DateTimeFormatter.BASIC_ISO_DATE);
// 2021-10-04
String isoLocalDate = now.format(DateTimeFormatter.ISO_LOCAL_DATE);
// 22:34:19.059
String isoLocalTime = now.format(DateTimeFormatter.ISO_LOCAL_TIME);
// 自定义
String customizeDate = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String customizeDateTime = now.format(DateTimeFormatter.ofPattern("今天是:yyyy年 MMMM dd日 E", Locale.CHINESE));
System.out.println("now:" + now);
System.out.println("basicIsoDate:" + basicIsoDate);
System.out.println("isoLocalDate:" + isoLocalDate);
System.out.println("isoLocalTime:" + isoLocalTime);
System.out.println("customizeDate:" + customizeDate);
System.out.println("customizeDateTime:" + customizeDateTime);
// 将字符串解析成日期对象
String strDate = "2021-10-05";
String strDateTime = "2021-10-05 19:49:16";
LocalDate date = LocalDate.parse(strDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDateTime dateTime = LocalDateTime.parse(strDateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("date: " + date);
System.out.println("dateTime: " + dateTime);
}运行结果
1
2
3
4
5
6
7
8now:2021-10-05T20:41:47.926
basicIsoDate:20211005
isoLocalDate:2021-10-05
isoLocalTime:20:41:47.926
customizeDate:2021-10-05
customizeDateTime:今天是:2021年 十月 05日 星期二
date: 2021-10-05
dateTime: 2021-10-05T19:49:16
时区
Java 8中的时区操作被很大程度上简化了,新的时区类java.time.ZoneId是原有的java.util.TimeZone类的替代品。ZoneId对象可以通过ZoneId.of()方法创建,也可以通过ZoneId.systemDefault()获取系统默认时区
代码演示
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/**
* Java 8中的时区操作被很大程度上简化了
* 新的时区类java.time.ZoneId是原有的java.util.TimeZone类的替代品。
* ZoneId对象可以通过ZoneId.of()方法创建,也可以通过ZoneId.systemDefault()获取系统默认时区:
*/
private static void zoneId() {
// 获取系统默认时区
ZoneId zoneId = ZoneId.systemDefault();
// 自己创建时区
ZoneId of = ZoneId.of("Asia/Shanghai");
System.out.println("of: " + of);
System.out.println("zoneId: " + zoneId);
// of参数里面不知道传啥值比较合理?可以通过ZoneId.getAvailableZoneIds()来获取可选择的ZoneId
// 也就是所有合法的“区域/城市”字符串
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
System.out.println("availableZoneIds: " + availableZoneIds);
// 有了ZoneId,我们就可以将一个LocalDate、LocalTime或LocalDateTime对象转化为ZonedDateTime对象
LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
System.out.println("zonedDateTime: " + zonedDateTime);
// 另一种表示时区的方式是使用ZoneOffset,它是以当前时间和世界标准时间(UTC)/格林威治时间(GMT)的偏差来计算
ZoneOffset zoneOffset = ZoneOffset.of("+09:00");
LocalDateTime now = LocalDateTime.now();
OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, zoneOffset);
System.out.println("offsetDateTime: " + offsetDateTime);
}运行结果
1
2
3
4
5of: Asia/Shanghai
zoneId: Asia/Shanghai
availableZoneIds: [Asia/Aden, America/Cuiaba, Etc/GMT+9, Etc/GMT+8, Africa/Nairobi, America/Marigot, Asia/Aqtau, Pacific/Kwajalein, America/El_Salvador, Asia/Pontianak, Africa/Cairo, Pacific/Pago_Pago, Africa/Mbabane, Asia/Kuching, Pacific/Honolulu, Pacific/Rarotonga, America/Guatemala, Australia/Hobart, Europe/London, America/Belize, America/Panama, Asia/Chungking, America/Managua, America/Indiana/Petersburg, Asia/Yerevan, Europe/Brussels, GMT, Europe/Warsaw, America/Chicago, Asia/Kashgar, Chile/Continental, Pacific/Yap, CET, Etc/GMT-1, Etc/GMT-0, Europe/Jersey, America/Tegucigalpa, Etc/GMT-5, Europe/Istanbul, America/Eirunepe, Etc/GMT-4, America/Miquelon, Etc/GMT-3, Europe/Luxembourg, Etc/GMT-2, Etc/GMT-9, America/Argentina/Catamarca, Etc/GMT-8, Etc/GMT-7, Etc/GMT-6, Europe/Zaporozhye, Canada/Yukon, Canada/Atlantic, Atlantic/St_Helena, Australia/Tasmania, Libya, Europe/Guernsey, America/Grand_Turk, US/Pacific-New, Asia/Samarkand, America/Argentina/Cordoba, Asia/Phnom_Penh, Africa/Kigali, Asia/Almaty, US/Alaska, Asia/Dubai, Europe/Isle_of_Man, America/Araguaina, Cuba, Asia/Novosibirsk, America/Argentina/Salta, Etc/GMT+3, Africa/Tunis, Etc/GMT+2, Etc/GMT+1, Pacific/Fakaofo, Africa/Tripoli, Etc/GMT+0, Israel, Africa/Banjul, Etc/GMT+7, Indian/Comoro, Etc/GMT+6, Etc/GMT+5, Etc/GMT+4, Pacific/Port_Moresby, US/Arizona, Antarctica/Syowa, Indian/Reunion, Pacific/Palau, Europe/Kaliningrad, America/Montevideo, Africa/Windhoek, Asia/Karachi, Africa/Mogadishu, Australia/Perth, Brazil/East, Etc/GMT, Asia/Chita, Pacific/Easter, Antarctica/Davis, Antarctica/McMurdo, Asia/Macao, America/Manaus, Africa/Freetown, Europe/Bucharest, Asia/Tomsk, America/Argentina/Mendoza, Asia/Macau, Europe/Malta, Mexico/BajaSur, Pacific/Tahiti, Africa/Asmera, Europe/Busingen, America/Argentina/Rio_Gallegos, Africa/Malabo, Europe/Skopje, America/Catamarca, America/Godthab, Europe/Sarajevo, Australia/ACT, GB-Eire, Africa/Lagos, America/Cordoba, Europe/Rome, Asia/Dacca, Indian/Mauritius, Pacific/Samoa, America/Regina, America/Fort_Wayne, America/Dawson_Creek, Africa/Algiers, Europe/Mariehamn, America/St_Johns, America/St_Thomas, Europe/Zurich, America/Anguilla, Asia/Dili, America/Denver, Africa/Bamako, Europe/Saratov, GB, Mexico/General, Pacific/Wallis, Europe/Gibraltar, Africa/Conakry, Africa/Lubumbashi, Asia/Istanbul, America/Havana, NZ-CHAT, Asia/Choibalsan, America/Porto_Acre, Asia/Omsk, Europe/Vaduz, US/Michigan, Asia/Dhaka, America/Barbados, Europe/Tiraspol, Atlantic/Cape_Verde, Asia/Yekaterinburg, America/Louisville, Pacific/Johnston, Pacific/Chatham, Europe/Ljubljana, America/Sao_Paulo, Asia/Jayapura, America/Curacao, Asia/Dushanbe, America/Guyana, America/Guayaquil, America/Martinique, Portugal, Europe/Berlin, Europe/Moscow, Europe/Chisinau, America/Puerto_Rico, America/Rankin_Inlet, Pacific/Ponape, Europe/Stockholm, Europe/Budapest, America/Argentina/Jujuy, Australia/Eucla, Asia/Shanghai, Universal, Europe/Zagreb, America/Port_of_Spain, Europe/Helsinki, Asia/Beirut, Asia/Tel_Aviv, Pacific/Bougainville, US/Central, Africa/Sao_Tome, Indian/Chagos, America/Cayenne, Asia/Yakutsk, Pacific/Galapagos, Australia/North, Europe/Paris, Africa/Ndjamena, Pacific/Fiji, America/Rainy_River, Indian/Maldives, Australia/Yancowinna, SystemV/AST4, Asia/Oral, America/Yellowknife, Pacific/Enderbury, America/Juneau, Australia/Victoria, America/Indiana/Vevay, Asia/Tashkent, Asia/Jakarta, Africa/Ceuta, Asia/Barnaul, America/Recife, America/Buenos_Aires, America/Noronha, America/Swift_Current, Australia/Adelaide, America/Metlakatla, Africa/Djibouti, America/Paramaribo, Asia/Qostanay, Europe/Simferopol, Europe/Sofia, Africa/Nouakchott, Europe/Prague, America/Indiana/Vincennes, Antarctica/Mawson, America/Kralendijk, Antarctica/Troll, Europe/Samara, Indian/Christmas, America/Antigua, Pacific/Gambier, America/Indianapolis, America/Inuvik, America/Iqaluit, Pacific/Funafuti, UTC, Antarctica/Macquarie, Canada/Pacific, America/Moncton, Africa/Gaborone, Pacific/Chuuk, Asia/Pyongyang, America/St_Vincent, Asia/Gaza, Etc/Universal, PST8PDT, Atlantic/Faeroe, Asia/Qyzylorda, Canada/Newfoundland, America/Kentucky/Louisville, America/Yakutat, Asia/Ho_Chi_Minh, Antarctica/Casey, Europe/Copenhagen, Africa/Asmara, Atlantic/Azores, Europe/Vienna, ROK, Pacific/Pitcairn, America/Mazatlan, Australia/Queensland, Pacific/Nauru, Europe/Tirane, Asia/Kolkata, SystemV/MST7, Australia/Canberra, MET, Australia/Broken_Hill, Europe/Riga, America/Dominica, Africa/Abidjan, America/Mendoza, America/Santarem, Kwajalein, America/Asuncion, Asia/Ulan_Bator, NZ, America/Boise, Australia/Currie, EST5EDT, Pacific/Guam, Pacific/Wake, Atlantic/Bermuda, America/Costa_Rica, America/Dawson, Asia/Chongqing, Eire, Europe/Amsterdam, America/Indiana/Knox, America/North_Dakota/Beulah, Africa/Accra, Atlantic/Faroe, Mexico/BajaNorte, America/Maceio, Etc/UCT, Pacific/Apia, GMT0, America/Atka, Pacific/Niue, Australia/Lord_Howe, Europe/Dublin, Pacific/Truk, MST7MDT, America/Monterrey, America/Nassau, America/Jamaica, Asia/Bishkek, America/Atikokan, Atlantic/Stanley, Australia/NSW, US/Hawaii, SystemV/CST6, Indian/Mahe, Asia/Aqtobe, America/Sitka, Asia/Vladivostok, Africa/Libreville, Africa/Maputo, Zulu, America/Kentucky/Monticello, Africa/El_Aaiun, Africa/Ouagadougou, America/Coral_Harbour, Pacific/Marquesas, Brazil/West, America/Aruba, America/North_Dakota/Center, America/Cayman, Asia/Ulaanbaatar, Asia/Baghdad, Europe/San_Marino, America/Indiana/Tell_City, America/Tijuana, Pacific/Saipan, SystemV/YST9, Africa/Douala, America/Chihuahua, America/Ojinaga, Asia/Hovd, America/Anchorage, Chile/EasterIsland, America/Halifax, Antarctica/Rothera, America/Indiana/Indianapolis, US/Mountain, Asia/Damascus, America/Argentina/San_Luis, America/Santiago, Asia/Baku, America/Argentina/Ushuaia, Atlantic/Reykjavik, Africa/Brazzaville, Africa/Porto-Novo, America/La_Paz, Antarctica/DumontDUrville, Asia/Taipei, Antarctica/South_Pole, Asia/Manila, Asia/Bangkok, Africa/Dar_es_Salaam, Poland, Atlantic/Madeira, Antarctica/Palmer, America/Thunder_Bay, Africa/Addis_Ababa, Asia/Yangon, Europe/Uzhgorod, Brazil/DeNoronha, Asia/Ashkhabad, Etc/Zulu, America/Indiana/Marengo, America/Creston, America/Punta_Arenas, America/Mexico_City, Antarctica/Vostok, Asia/Jerusalem, Europe/Andorra, US/Samoa, PRC, Asia/Vientiane, Pacific/Kiritimati, America/Matamoros, America/Blanc-Sablon, Asia/Riyadh, Iceland, Pacific/Pohnpei, Asia/Ujung_Pandang, Atlantic/South_Georgia, Europe/Lisbon, Asia/Harbin, Europe/Oslo, Asia/Novokuznetsk, CST6CDT, Atlantic/Canary, America/Knox_IN, Asia/Kuwait, SystemV/HST10, Pacific/Efate, Africa/Lome, America/Bogota, America/Menominee, America/Adak, Pacific/Norfolk, Europe/Kirov, America/Resolute, Pacific/Tarawa, Africa/Kampala, Asia/Krasnoyarsk, Greenwich, SystemV/EST5, America/Edmonton, Europe/Podgorica, Australia/South, Canada/Central, Africa/Bujumbura, America/Santo_Domingo, US/Eastern, Europe/Minsk, Pacific/Auckland, Africa/Casablanca, America/Glace_Bay, Canada/Eastern, Asia/Qatar, Europe/Kiev, Singapore, Asia/Magadan, SystemV/PST8, America/Port-au-Prince, Europe/Belfast, America/St_Barthelemy, Asia/Ashgabat, Africa/Luanda, America/Nipigon, Atlantic/Jan_Mayen, Brazil/Acre, Asia/Muscat, Asia/Bahrain, Europe/Vilnius, America/Fortaleza, Etc/GMT0, US/East-Indiana, America/Hermosillo, America/Cancun, Africa/Maseru, Pacific/Kosrae, Africa/Kinshasa, Asia/Kathmandu, Asia/Seoul, Australia/Sydney, America/Lima, Australia/LHI, America/St_Lucia, Europe/Madrid, America/Bahia_Banderas, America/Montserrat, Asia/Brunei, America/Santa_Isabel, Canada/Mountain, America/Cambridge_Bay, Asia/Colombo, Australia/West, Indian/Antananarivo, Australia/Brisbane, Indian/Mayotte, US/Indiana-Starke, Asia/Urumqi, US/Aleutian, Europe/Volgograd, America/Lower_Princes, America/Vancouver, Africa/Blantyre, America/Rio_Branco, America/Danmarkshavn, America/Detroit, America/Thule, Africa/Lusaka, Asia/Hong_Kong, Iran, America/Argentina/La_Rioja, Africa/Dakar, SystemV/CST6CDT, America/Tortola, America/Porto_Velho, Asia/Sakhalin, Etc/GMT+10, America/Scoresbysund, Asia/Kamchatka, Asia/Thimbu, Africa/Harare, Etc/GMT+12, Etc/GMT+11, Navajo, America/Nome, Europe/Tallinn, Turkey, Africa/Khartoum, Africa/Johannesburg, Africa/Bangui, Europe/Belgrade, Jamaica, Africa/Bissau, Asia/Tehran, WET, Europe/Astrakhan, Africa/Juba, America/Campo_Grande, America/Belem, Etc/Greenwich, Asia/Saigon, America/Ensenada, Pacific/Midway, America/Jujuy, Africa/Timbuktu, America/Bahia, America/Goose_Bay, America/Virgin, America/Pangnirtung, Asia/Katmandu, America/Phoenix, Africa/Niamey, America/Whitehorse, Pacific/Noumea, Asia/Tbilisi, America/Montreal, Asia/Makassar, America/Argentina/San_Juan, Hongkong, UCT, Asia/Nicosia, America/Indiana/Winamac, SystemV/MST7MDT, America/Argentina/ComodRivadavia, America/Boa_Vista, America/Grenada, Asia/Atyrau, Australia/Darwin, Asia/Khandyga, Asia/Kuala_Lumpur, Asia/Famagusta, Asia/Thimphu, Asia/Rangoon, Europe/Bratislava, Asia/Calcutta, America/Argentina/Tucuman, Asia/Kabul, Indian/Cocos, Japan, Pacific/Tongatapu, America/New_York, Etc/GMT-12, Etc/GMT-11, Etc/GMT-10, SystemV/YST9YDT, Europe/Ulyanovsk, Etc/GMT-14, Etc/GMT-13, W-SU, America/Merida, EET, America/Rosario, Canada/Saskatchewan, America/St_Kitts, Arctic/Longyearbyen, America/Fort_Nelson, America/Caracas, America/Guadeloupe, Asia/Hebron, Indian/Kerguelen, SystemV/PST8PDT, Africa/Monrovia, Asia/Ust-Nera, Egypt, Asia/Srednekolymsk, America/North_Dakota/New_Salem, Asia/Anadyr, Australia/Melbourne, Asia/Irkutsk, America/Shiprock, America/Winnipeg, Europe/Vatican, Asia/Amman, Etc/UTC, SystemV/AST4ADT, Asia/Tokyo, America/Toronto, Asia/Singapore, Australia/Lindeman, America/Los_Angeles, SystemV/EST5EDT, Pacific/Majuro, America/Argentina/Buenos_Aires, Europe/Nicosia, Pacific/Guadalcanal, Europe/Athens, US/Pacific, Europe/Monaco]
zonedDateTime: 2021-10-05T20:42:09.993+08:00[Asia/Shanghai]
offsetDateTime: 2021-10-05T20:42:09.993+09:00