Java基础(十七):日期时间API

news2025/2/27 23:06:46

Java基础系列文章

Java基础(一):语言概述

Java基础(二):原码、反码、补码及进制之间的运算

Java基础(三):数据类型与进制

Java基础(四):逻辑运算符和位运算符

Java基础(五):流程控制语句

Java基础(六):数组

Java基础(七):面向对象编程

Java基础(八):封装、继承、多态性

Java基础(九):Object 类的使用

Java基础(十):关键字static、代码块、关键字final

Java基础(十一):抽象类、接口、内部类

Java基础(十二):枚举类

Java基础(十三):注解(Annotation)

Java基础(十四):包装类

Java基础(十五):异常处理

Java基础(十六):String的常用API

Java基础(十七):日期时间API


目录

  • 一、JDK8之前:日期时间API
    • 1、java.lang.System类的方法
    • 2、两个Date类
    • 3、java.text.SimpleDateFormat
    • 4、java.util.Calendar(日历)
  • 二、JDK8:新的日期时间API
    • 1、为什么会有新的时间API
    • 2、本地日期时间:LocalDate、LocalTime、LocalDateTime
    • 3、瞬时:Instant
    • 4、日期时间格式化:DateTimeFormatter
  • 三、与传统日期处理的转换


一、JDK8之前:日期时间API

1、java.lang.System类的方法

  • System类提供的public static long currentTimeMillis()
    • 获取当前时间对应的毫秒数,long类型,时间戳
    • 当前时间与1970年1月1日0时0分0秒之间的毫秒数
    • 此方法适于计算时间差

举例:

@Test
public void test1(){
    long time = System.currentTimeMillis();
    System.out.println(time);//1559806982971
    //当前系统时间距离1970-1-1 0:0:0 0毫秒的时间差,毫秒为单位
}

2、两个Date类

java.util.Date

  • 表示特定的瞬间,精确到毫秒
  • 构造器:
    • Date():使用无参构造器创建的对象可以获取本地当前时间
    • Date(long 毫秒数):把该毫秒值换算成日期时间对象
  • 常用方法:
    • getTime(): 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数
    • toString(): 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy
      • 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat),zzz是时间标准
    • 其它很多方法都过时了

举例:

@Test
public void test2(){
    Date date1 = new Date(); //创建一个基于当前系统时间的Date的实例
    System.out.println(date1.toString());//Mon Dec 05 11:56:26 CST 2022

    long milliTimes = date1.getTime();
    System.out.println("对应的毫秒数为:" + milliTimes); //1670212256045

    Date date2 = new Date(1370202256045L); //创建一个基于指定时间戳的Date的实例
    System.out.println(date2.toString());
}

java.sql.Date

  • java.util.Date是java.sql.Date的父类
  • java.sql.Date: 对应着数据库中的date类型
  • 没有空参构造方法,只有年月日,没有时分秒
@Test
public void test2(){
    java.sql.Date date1 = new java.sql.Date(1370202256045L);

    System.out.println(date1.toString());//2013-06-03

    System.out.println(date1.getTime());//1370202256045
}

3、java.text.SimpleDateFormat

  • java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化和解析日期的具体类
  • 可以进行格式化:日期 --> 文本
  • 可以进行解析:文本 --> 日期
  • 构造器:
    • SimpleDateFormat() :默认的模式和语言环境创建对象
    • public SimpleDateFormat(String pattern):该构造方法可以用参数pattern指定的格式创建一个对象
  • 格式化:
    • public String format(Date date):方法格式化时间对象date
  • 解析:
    • public Date parse(String source):从给定字符串的开始解析文本,以生成一个日期

在这里插入图片描述

举例:

@Test
public void test3() throws ParseException {
    SimpleDateFormat sdf = new SimpleDateFormat();
    //格式化:日期--->字符串
    Date date1 = new Date();
    String strDate = sdf.format(date1);
    System.out.println(strDate);//22-12-5 下午2:21

    //解析:字符串 ---> 日期
    Date date2 = sdf.parse("22-12-5 下午3:21");
    System.out.println(date2);
}
@Test
public void test4() throws ParseException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒  E Z");
    // 格式化:日期--->字符串
    Date date1 = new Date();
    String strDate = sdf.format(date1);
    System.out.println(strDate);// 2023年04月17日 17时13分32秒 036毫秒  星期一 +0800

    // 解析:字符串 ---> 日期
    Date date2 = sdf.parse("2023年04月17日 17时12分55秒 983毫秒  星期一 +0800");
    System.out.println(date2);// Mon Apr 17 17:12:55 CST 2023

    // 解析失败。因为参数的字符串不满足SimpleDateFormat可以识别的格式。
    // Date date3 = sdf.parse("22-12-5 下午2:21");
    // System.out.println(date2);
}

4、java.util.Calendar(日历)

在这里插入图片描述

  • Date类的API大部分被废弃了,替换为Calendar

  • Calendar 类是一个抽象类,主用用于完成日期字段之间相互操作的功能

  • 获取Calendar实例的方法

    • 使用Calendar.getInstance()方法
      在这里插入图片描述
    • 调用它的子类GregorianCalendar(公历)的构造器
      -
  • 一个Calendar的实例是系统时间的抽象表示,可以修改或获取 YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY 、MINUTE、SECOND等 日历字段对应的时间值

    • public int get(int field):返回给定日历字段的值
    • public void set(int field,int value) :将给定的日历字段设置为指定的值
    • public void add(int field,int amount):根据日历的规则,为给定的日历字段添加或者减去指定的时间量
    • public final Date getTime():将Calendar转成Date对象
    • public final void setTime(Date date):使用指定的Date对象重置Calendar的时间
  • 常用字段

在这里插入图片描述

  • 注意:
    • 获取月份时:一月是0,二月是1,以此类推,12月是11
    • 获取星期时:周日是1,周一是2 , 。。。。周六是7

举例:

@Test
public void test5() {
    Calendar calendar = Calendar.getInstance();

    System.out.println("日历类型:" + calendar.getClass());// class java.util.GregorianCalendar

    // 测试方法
    // get(int field)
    System.out.println("当月第几天:" + calendar.get(Calendar.DAY_OF_MONTH)); 
    System.out.println("当年第几天:" + calendar.get(Calendar.DAY_OF_YEAR));

    // set(int field,xx)
    calendar.set(Calendar.DAY_OF_MONTH, 23);
    System.out.println("设置为当月第23天:" + calendar.get(Calendar.DAY_OF_MONTH));

    // add(int field,xx)
    calendar.add(Calendar.DAY_OF_MONTH, 3);
    calendar.add(Calendar.DAY_OF_MONTH, -5);
    System.out.println("当月天数,先加3天,再减5天" + calendar.get(Calendar.DAY_OF_MONTH));

    // getTime():Calender --> Date
    Date date = calendar.getTime();
    System.out.println("日历类转换为Date" + date);

    // setTime():使用指定Date重置Calendar
    Date date1 = new Date();
    calendar.setTime(date1);
    System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
}

二、JDK8:新的日期时间API

1、为什么会有新的时间API

  • 可变性:像日期和时间这样的类应该是不可变的
  • 偏移性:Date中的年份是从1900开始的,而月份都从0开始
  • 格式化:格式化只对Date有用,Calendar则不行
  • 此外,它们也不是线程安全的;不能处理闰秒等

总结:对日期和时间的操作一直是Java程序员最痛苦的地方之一

第三次引入的API是成功的,并且Java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务

Java 8 以一个新的开始为 Java 创建优秀的 API。新的日期时间API包含:

  • java.time – 包含值对象的基础包
    • 时钟(Clock)
    • 本地日期(LocalDate)
    • 本地时间(LocalTime)
    • 本地日期时间(LocalDateTime)
    • 时区(ZonedDateTime)
    • 持续时间(Duration)
  • java.time.chrono – 提供对不同的日历系统的访问。
  • java.time.format – 格式化和解析时间和日期
  • java.time.temporal – 包括底层框架和扩展特性
  • java.time.zone – 包含时区支持的类

尽管有68个新的公开类型,但是大多数开发者只会用到基础包和format包,大概占总数的三分之一

2、本地日期时间:LocalDate、LocalTime、LocalDateTime

方法描述
now() / now(ZoneId zone)静态方法,根据当前时间创建对象/指定时区的对象
of(xx,xx,xx,xx,xx,xxx)静态方法,根据指定日期/时间创建对象
getDayOfMonth()/getDayOfYear()获得月份天数(1-31) /获得年份天数(1-366)
getDayOfWeek()获得星期几(返回一个 DayOfWeek 枚举值)
getMonth()获得月份, 返回一个 Month 枚举值
getMonthValue() / getYear()获得月份(1-12) /获得年份
getHours()/getMinute()/getSecond()获得当前对象对应的小时、分钟、秒
withDayOfMonth()/withDayOfYear()/withMonth()/withYear()将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象
with(TemporalAdjuster t)将当前日期时间设置为校对器指定的日期时间
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours()向当前对象添加几天、几周、几个月、几年、几小时
minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours()从当前对象减去几月、几周、几天、几年、几小时
plus(TemporalAmount t)/minus(TemporalAmount t)添加或减少一个 Duration 或 Period
isBefore()/isAfter()比较两个 LocalDate
isLeapYear()判断是否是闰年(在LocalDate类中声明)
format(DateTimeFormatter t)格式化本地日期、时间,返回一个字符串
parse(Charsequence text)将指定格式的字符串解析为日期、时间

举例:

@Test
public void test1() {
    //now():获取当前日期和时间对应的实例
    LocalDate localDate = LocalDate.now();
    LocalTime localTime = LocalTime.now();
    LocalDateTime localDateTime = LocalDateTime.now();

    System.out.println(localDate);//2022-12-05
    System.out.println(localTime);//15:43:51.474
    System.out.println(localDateTime); //2022-12-05T15:43:51.475

    //of():获取指定的日期、时间对应的实例
    LocalDate localDate1 = LocalDate.of(2021, 5, 23);
    LocalDateTime localDateTime1 = LocalDateTime.of(2022, 12, 5, 11, 23, 45);
    System.out.println(localDate1);//2021-05-23
    System.out.println(localDateTime1);//2022-12-05T11:23:45

    //getXXX()
    LocalDateTime localDateTime2 = LocalDateTime.now();
    System.out.println(localDateTime2.getDayOfMonth());// 当月的第几天

    //体现不可变性
    //withXxx()
    LocalDateTime localDateTime3 = localDateTime2.withDayOfMonth(10);
    System.out.println(localDateTime2);//2022-12-05T15:48:48.399// 当前时间
    System.out.println(localDateTime3);//2022-12-15T15:48:48.399// 当前月,日期修改为10

    //plusXxx()
    LocalDateTime localDateTime4 = localDateTime2.plusDays(5);
    System.out.println(localDateTime2);//2022-12-05T15:50:21.864// 当前日期
    System.out.println(localDateTime4);//2022-12-10T15:50:21.864// 当前日期加5天
}

3、瞬时:Instant

  • Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳
  • 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
  • java.time.Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区
    • 概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数
方法描述
now()静态方法,返回默认UTC时区的Instant类的对象
ofEpochMilli(long epochMilli)静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类的对象
atOffset(ZoneOffset offset)结合即时的偏移来创建一个 OffsetDateTime
toEpochMilli()返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳
  • 中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间与UTC的时差均为+8,也就是UTC+8
  • instant.atOffset(ZoneOffset.ofHours(8))

在这里插入图片描述

  • 整个地球分为二十四时区,每个时区都有自己的本地时间
  • 北京时区是东八区,领先UTC八个小时

举例:

@Test
public void test2() {
    //now():
    Instant instant = Instant.now();
    System.out.println(instant);//2023-04-17T13:44:14.137382Z
    //了解:
    OffsetDateTime instant1 = instant.atOffset(ZoneOffset.ofHours(8));
    System.out.println(instant1);//2023-04-17T21:44:14.137382+08:00

    Instant instant2 = Instant.ofEpochMilli(24123123312L);
    System.out.println(instant2);//1970-10-07T04:52:03.312Z

    long milliTime = instant.toEpochMilli();
    System.out.println(milliTime);//1681739054137

    System.out.println(new Date().getTime());//1681739054142
}

4、日期时间格式化:DateTimeFormatter

  • (了解)预定义的标准格式。如:ISO_LOCAL_DATE_TIME、ISO_LOCAL_DATE、ISO_LOCAL_TIME
  • (了解)本地化相关的格式。如:ofLocalizedDate(FormatStyle.LONG)
  • 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
ofPattern(String pattern)静态方法,返回一个指定字符串格式的DateTimeFormatter
format(TemporalAccessor t)格式化一个日期、时间,返回字符串
parse(CharSequence text)将指定格式的字符序列解析为一个日期、时间

举例:

public class TestDatetimeFormatter {
    @Test
    public void test1(){
        // 方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        // 格式化:日期-->字符串
        LocalDateTime localDateTime = LocalDateTime.now();
        String str1 = formatter.format(localDateTime);
        System.out.println(localDateTime);
        System.out.println(str1);//2022-12-04T21:02:14.808

        // 解析:字符串 -->日期
        TemporalAccessor parse = formatter.parse("2022-12-04T21:02:14.808");
        LocalDateTime dateTime = LocalDateTime.from(parse);
        System.out.println(dateTime);
    }

    @Test
    public void test2(){
        LocalDateTime localDateTime = LocalDateTime.now();
        // 方式二:
        // 本地化相关的格式。如:ofLocalizedDateTime()
        // FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTime
        DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
        
        // 格式化
        String str2 = formatter1.format(localDateTime);
        System.out.println(str2);// 2022年12月4日 下午09时03分55秒

        // 本地化相关的格式。如:ofLocalizedDate()
        // FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDate
        DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
        // 格式化
        String str3 = formatter2.format(LocalDate.now());
        System.out.println(str3);// 2022年12月4日 星期日
    }

    @Test
    public void test3(){
        //方式三:自定义的方式(关注、重点)
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        //格式化
        String strDateTime = dateTimeFormatter.format(LocalDateTime.now());
        System.out.println(strDateTime); //2022/12/04 21:05:42
        //解析
        TemporalAccessor accessor = dateTimeFormatter.parse("2022/12/04 21:05:42");
        LocalDateTime localDateTime = LocalDateTime.from(accessor);
        System.out.println(localDateTime); //2022-12-04T21:05:42
    }
}

三、与传统日期处理的转换

To 遗留类From 遗留类
java.time.Instant与java.util.DateDate.from(instant)date.toInstant()
java.time.Instant与java.sql.TimestampTimestamp.from(instant)timestamp.toInstant()
java.time.ZonedDateTime与java.util.GregorianCalendarGregorianCalendar.from(zonedDateTime)cal.toZonedDateTime()
java.time.LocalDate与java.sql.TimeDate.valueOf(localDate)date.toLocalDate()
java.time.LocalTime与java.sql.TimeDate.valueOf(localDate)date.toLocalTime()
java.time.LocalDateTime与java.sql.TimestampTimestamp.valueOf(localDateTime)timestamp.toLocalDateTime()
java.time.ZoneId与java.util.TimeZoneTimezone.getTimeZone(id)timeZone.toZoneId()
java.time.format.DateTimeFormatter与java.text.DateFormatformatter.toFormat()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/426751.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatGPT开发公司

OpenAI是chatGPT的开发公司,成立于2015年,总部位于美国旧金山。OpenAI致力于开发和推广人工智能技术,包括自然语言处理、视觉识别、机器学习等领域,旨在推动人工智能技术对全球社会和经济的影响和发展。 除了chatGPT之外&…

日撸 Java 三百行day31

文章目录day31 整数矩阵及其运算面向对象思想java异常处理java中的getter和setter方法代码day31 整数矩阵及其运算 面向对象思想 结合之前day7和day8面向过程开发,只关注了矩阵加法和矩阵乘法的功能。而day31是面向对象开发,一个矩阵类,在这…

Python实现驾考自动答题,隔壁老王每次都100分....

人生苦短,我用python 不知道大家都考完驾照没? 这个驾照不管大家有没有,我相信大家都是这个: 朋友最近在考驾照,快考科一了… 我微微一笑当场给他整个活~ 用Python整了几十行代码,给朋友实现一下自动答…

前端面试题 - 基础(HTML、HTTP、WEB)

文章目录1、前端 SEO 需要注意哪些2、img 标签上的 title 和 alt 区别3、浏览器输入 url 到显示过程4、浏览器渲染过程5、常见请求方式6、常见的状态码7、网站性能优化8、语义化理解9、浏览器内核理解10、H5的新特性11、离线存储使用,工作原理12、浏览器是如何管理和…

确保实时操作系统(RTOS)设备中的数据安全

导读1月28日大家庆祝了数据保护日,这是一项旨在促进保护数据隐私和安全的国际活动。为了提高人们对数据保护的意识,讨论实时操作系统中数据安全的问题势在必行。目前非常规操作系统已被广泛使用,所以了解这一系统非常重要,尤其是涉…

做完自动化测试,但别让不会汇报毁了你...

pytest 是一个成熟的全功能Python测试工具,可以帮助您编写更好的程序。它与 python 自带的 unittest 测试框架类似,但 pytest 使用起来更简洁和高效,并且兼容 unittest 框架。pytest 能够支持简单的单元测试和复杂的功能测试,pyte…

Javassist动态生成类使用,以及Arthas 查看动态代理生成类内容

java反射 反射的弊端: 性能开销: 因为反射涉及到动态解析的类型,所以某些Java虚拟机的优化不能被执行(因为它不能真正了解你在做什么)。因此,反射操作的性能比非反射操作的性能要慢,应该避免在对性能敏感的应用程序中频繁调用的代码部分。 …

C++记录总结及面试常见问题

C记录总结及面试常见问题指针和函数内存分区模型访问权限struct & class创建类构造函数静态成员this指针const 修饰成员函数友元friend重载运算符和重载函数继承读文件ifstream/fstreamvector中resize和reserve的区别智能指针左值与右值struct、class区别引用指针和函数 函…

Zabbix6.0升级到Zabbix6.4

1:现在的版本是6.0.3 2:停止Zabbix Server进程。 systemctl stop zabbix-server 若升级Zabbix proxy版本,需也停止Zabbix proxy服务 。 systemctl stop zabbix-proxy 3:我用的是MariaDB数据库名称是zabbix。 4: 查看…

windows11安装pytorch2.0

换了新电脑,好久没用windows了,配置一下环境,顺便记录一下方便帮助AI小白不会浪费时间在装环境上(一星期不夸张hah) 打开命令行,然后输入 nvidia-smi,检查自己的显卡驱动 也可以通过图形界面查…

Python轻量级Web框架Flask(6)——Flask中的单表操作(增删改“查”)

0、前言:Python轻量级Web框架Flask(5)中生成的新模板就是包含数据库操作的Flask模板。 在pycharm中用flask写表结构时需用用到数据类型的定义如下: 下面总结一些常用到的数据类型: 1、Python轻量级Web框架Flask&…

传智健康项目总结

耗时一个半月终于把传智健康项目跟着做完了,下面是对项目的一点心得体会。 项目知识点总结 Maven中parent父工程聚合 聚合模块(父工程)作用:父工程是一个pom工程,通常只是用来帮助其子模块构建的工具,本身并没有实质的内容。具体…

【Pytorch】搭建网络模型的实战

【Pytorch】搭建网络模型的实战CIFAR10 model structure搭建网络使用Sequential进行搭建网络模型使用tensorboard查看网络结构对CIFAR10数据集进行分类,根据图片内容识别这是哪一类 CIFAR10 model structure 输入input:3通道的32 x 32 图片卷积操作的通道数不变 那…

C#,码海拾贝(16)——求“矩阵秩”的全选主元“高斯消去法(Gauss Elimination)”C#源代码,《C#数值计算算法编程》源代码升级改进版

1 矩阵的秩 Rank of Matrix 矩阵的秩是线性代数中的一个概念。在线性代数中,一个矩阵A的列秩是A的线性独立的纵列的极大数,通常表示为r(A),rk(A)或rank A。 在线性代数中,一个矩阵A的列秩是A的线性独立的纵列的极大数目。类似地&…

全面解析反欺诈(羊毛盾)API,助你识别各类欺诈风险

前言 反欺诈(羊毛盾)反机器欺诈 API,是一种基于大数据分析和模型产品的技术,通过输入手机号、手机 IP 地址进行检测,帮助客户识别大量存在恶意的账号。 反欺诈(羊毛盾)API 的作用 反欺诈&…

Spring自定义参数解析器~

1. 什么是参数解析器 RequstBody、RequstParam 这些注解是不是很熟悉? 我们在开发 Controller 接口时经常会用到此类参数注解,那这些注解的作用是什么?我们真的了解吗? 简单来说,这些注解就是帮我们将前端传递的参数…

基于Sikuli GUI图像识别框架的PC客户端自动化测试实践

目录:导读 引言 一、GUI图像识别框架元祖:Sikuli 二、Sikuli运行原理 三、Sikuli安装 四、Sikuli IDE主界面基本使用 五、Sikuli 脚本语法 六、Sikuli 应用示例 七、Sikuli 优势及局限 1.优势 2.局限 Sikuli 使用小结 引言 Sikuli是一种基于…

【Hello Network】网络基础1

作者:小萌新 专栏:网络 作者简介:大二学生 希望能和大家一起进步 本篇博客简介:简单介绍网络的基础概念 网络基础1网络基础网络的起源网络在哪里认识协议网络协议协议分层OSI七层模型TCP/IP协议网络传输流程局域网的两台主机通信两…

跟姥爷深度学习3 神经网络的调试实操

一、前言 前面我们做了一次天气预测的模型,训练的结果都还好,网络好歹是“拟合”了,但预测数据不合预期让我一直耿耿于怀。所以我又花了很长时间来研究为什么,我的理论依据明明没有问题(今日*均温度与*一周*均温度具有…

全球6G技术大会总结报告

全球6G技术大会 论坛B:天地融合智能组网技术 论坛D:2030技术发展趋势 论坛E:6G无线空口传输技术 论坛F:6G通感算架构及关键技术 论坛H:6G网络架构及关键技术 论坛B:天地融合智能组网技术 论坛B中包含…