日期处理第四篇(终)- Java日期时间处理大总结

文章目录

    • 日期时间概念
      • 通用标准
      • 日期字段解析
      • 国际化的日期格式
    • 日期的实战
      • 第一个问题:日期常用时间操作
      • 第二个问题:时区的问题
        • 时区概念
        • 时区的处理
          • ZoneID的使用
        • ZoneOffset的使用
        • 让人恼火的夏令时
      • 第三个问题:MySQL存储时间用什么类型?
        • MySQL中的日期类型
          • DATETIME
          • TIMESTAMEP
          • 数值型时间戳(INT)
        • 结论
      • 第四个问题:项目国际化,日期时间处理方案。
    • 总结

前面三篇分享了在Java中处理日期、时间相关的一些工具类。俗话说得好磨刀不误砍柴工,今天我们来系统的去看一下在程序中的日期是什么样的?我们把他的原理搞清楚,把概念弄明白,希望以后再遇到日期相关的问题,处理起来事半功倍。本篇会先阐述一下时间相关的概念,然后再分享日期的一些实战,比如日期格式化、日期计算、数据库存储日期用什么类型最好等。话不多说,开始吧。

在这里插入图片描述

日期时间概念

通用标准

ISO 8601确定四位数年份、两位数日月两位数24小时制时分秒yyyy-MM-dd HH:mm:ss)的表达方式作为国际标准。这一标准方便计算机进行自然排序,且可减少歧义,有利于跨国资讯交换。说个题外话,你知道千禧年问题吗?

日期字段解析

我们经常使用的就是这种格式yyyy-MM-dd HH:mm:ss,还有很多其他格式,我们了解了下面每个字符的含义后,就可以按照自己想要的格式进行输出了。
y: 年,一般使用yyyy表示4位年份如2024,yy表示2位年份如24
M:月,一般使用MM表示月份比如01、12,MMM会根据语言环境显示不用的月份,如中国:一月、十二月;美国:Oct
d: 月份中天数,一般使用dd表示月份,如:20
D:年份中的天数,表示的是一年的第几天,用D表示,如:323
E:星期几。用E表示,比如中国显示星期六,英语环境下会显示 Sat
H:一天中的小时数(0-23),24小时制,一般用HH表示小时数,如:18
h:一天中的小时数(1-12),12小时制,使用hh表示的10点也可能是晚上22点
m:分钟,用mm表示,如:53
s:秒(1-999),用ss表示,如:35
S:毫秒,一般使用SSS表示,如:879
-: 连接符,没有特殊意义,可以是任意字符,汉字也可以
z:时区,通用时区,如:Pacific Standard Time; PST; GMT-08:00
Z:时区,RFC 822时区,如:-0800,+0800
X:时区,ISO 8601时区,如:-08; -0800; -08:00;+08:00
a:表示am/pm,
G:年代,AD(公元)、BC(公元前)

2024-01-21T00:38:55.981+08:00
这个时间的格式用字母来表达式就是:yyyy-MM-ddTHH:mm:ss.SSSX
T是什么含义呢,类似分隔符可以用任何字符代替,但是国际标准用T来表面后半部分是时间,前半部分是日期。X是时区。

我们再来看一些日期格式,下面这些其实并不常用,可以作为参考:
在这里插入图片描述

国际化的日期格式

可以简单看下国际化的日期格式都是什么样的:
https://docs.oracle.com/cd/E19683-01/816-3981/overview-46/index.html
在这里插入图片描述
以上可以看到只要掌握了日期每个字段的概念和代表符号,就可以自定义你想要的任何格式了。最常见的还是yyyy-MM-dd HH:mm:ss,主要字母的大小写。

日期的实战

知道了日期的概念之后,我们进入实战部分,这里会介绍最常见的一些场景和问题。首先之前介绍了三篇的Java日期处理的工具类:

  1. 日期处理第一篇:优雅好用的Java日期工具类Joda-Time: Java8之前的业务场景推荐使用Joda-Time
  2. 日期处理第二篇:Java8新时间和日期API,看完你就全明白了:Java8以后的版本包括Java8,优先使用内置的sdk,弃用java.date下的工具类,优先使用java.time下的工具类。
  3. 日期处理第三篇:Hutool的日期时间工具-DateUtil使用:使用起来很方便,也兼容了Java8新的日期的API,但是非必要不建议引入额外的jar包了,推荐使用内置的就可以。

应该没有太多项目了还在java8之前的版本,所以本篇会全部采用Java8新的日期API来进行编码做示例。

第一个问题:日期常用时间操作

这个问题应该是我们业务中最常遇见到的了,将日期输出、展示、存储、时间戳转成日期格式等场景,我们下面一一说明。

  1. 获取当前系统时间
// 2024-01-21T12:20:05.394
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
// 2024-01-21T12:20:05.395  推荐使用带有时区的方式获取时间
LocalDateTime localDateTime2 = LocalDateTime.now(ZoneId.systemDefault());
System.out.println(localDateTime2);
// 2024-01-21T04:20:05.395
LocalDateTime localDateTime3 = LocalDateTime.now(ZoneId.of("UTC+0"));
System.out.println(localDateTime3);

虽然我们日常使用第一种LocalDateTime.now()的场景更多,但是这里还是要强调推荐使用LocalDateTime.now(ZoneId.systemDefault());这种带有时区的方式获取时间,这样目的更明确。

  1. 获取当前系统时间戳
		//1705811713124
        long now = System.currentTimeMillis();
        System.out.println(now);
        
        // 1705811713124
        Instant instant = Instant.now();
        System.out.println(instant.toEpochMilli());
  1. 日期时间和字符串之间的转换
		// 时间戳转成字符串
        Instant instant = Instant.now();
        // 2024-01-21T12:35:13.124
        LocalDateTime fromMillsDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        System.out.println(fromMillsDateTime);
		
		// 字符串转成时间戳
		Instant instantFromDateTime = fromMillsDateTime.toInstant(ZoneOffset.UTC);
		// 1705840746886
        System.out.println(instantFromDateTime.toEpochMilli());
  1. 日期格式化-DateTimeFormatter
    记住不要再使用SimpleDateFormat了,SimpleDateFormat是线程不安全的,也说也被淘汰的类了,推荐使用DateTimeFormatter,DateTimeFormatter也是一个不可变的类,所以是线程安全的,比SimpleDateFormat靠谱多了吧。另外它还内置了非常多的格式化模版实例供以使用,形如:
    在这里插入图片描述
String strDate6 = "2017-01-05";
String strDate7 = "2017-01-05 12:30:05";

LocalDate date = LocalDate.parse(strDate6, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDateTime dateTime1 = LocalDateTime.parse(strDate7, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));


LocalDateTime dateTime = LocalDateTime.now();
String strDate1 = dateTime.format(DateTimeFormatter.BASIC_ISO_DATE);    // 20170105
String strDate2 = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE);    // 2017-01-05
String strDate3 = dateTime.format(DateTimeFormatter.ISO_LOCAL_TIME);    // 14:20:16.998
String strDate4 = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));   // 2017-01-05
String strDate5 = dateTime.format(DateTimeFormatter.ofPattern("今天是:YYYY年 MMMM DD日 E", Locale.CHINESE)); // 今天是:2017年 一月 05日 星期四

若想自定义模式pattern,和Date一样它也可以自己指定任意的pattern 日期/时间模式。由于本文在Date部分详细介绍了日期/时间模式,各个字母代表什么意思以及如何使用,这里就不再赘述了哈。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("第Q季度 yyyy-MM-dd HH:mm:ss", Locale.US);

    // 格式化输出
    System.out.println(formatter.format(LocalDateTime.now()));

    // 解析
    String dateTimeStrParam = "第1季度 2021-01-17 22:51:32";
    LocalDateTime localDateTime = LocalDateTime.parse(dateTimeStrParam, formatter);
    // Q/q:季度,如3; 03; Q3; 3rd quarter。
    System.out.println("解析后的结果:" + localDateTime);

还有很多其他操作参考: 日期处理第二篇:Java8新时间和日期API,看完你就全明白了

第二个问题:时区的问题

令人最头痛的应该就是这个时区的问题了,平时虽然我们用不到,但还是会经常遇到时区的问题的,最近也在做国际化相关的项目,所以开始深入的了解一下时区的问题。
查资料的时候发现这篇文章研究的很清楚,可以参考:https://www.cnblogs.com/yourbatman/p/14307194.html
如果展开来讲,又能写一篇博客深入浅出时区了,这里我们还是尽量简单讲基础概念和实战运用,想深入了解的可以参考上面的文章。

时区概念

我们经常遇到一些名词:时间戳、UTC、GMT、夏令时等,我们来看一看这几个名词分别是什么意思。

  • 时间戳(Timestamp):是指从一个特定的时间起点开始,到另一个时间点的间隔数值。通常来说,这个起点是UNIX时间的开始,即1970年1月1日00:00:00 UTC(协调世界时),到目标日期的秒数(或者毫秒数)。时间戳是一个非常精确的时间表示方法,广泛应用于程序开发和数据库中。

  • UTC(Coordinated Universal Time,协调世界时):是世界标准时间,替代了过去的格林尼治标准时间(GMT)。UTC比GMT更加精确,在偏差控制上采用了原子时钟,因此UTC现在被作为全球统一的时间标准。

  • GMT(Greenwich Mean Time,格林尼治平时):指位于英国伦敦郊区的格林尼治天文台的标准时间,过去常用作国际时间标准。由于GMT不是非常精确(它不涉及原子时钟),现在一般使用更精确的UTC来替代它。

  • 夏令时(Daylight Saving Time,DST):是一种在夏季把标准时间调快1小时的制度,目的是让人们更好地利用日照,晚上减少电灯的使用,以节约能源。不是所有的国家和地区都采用夏令时。在进入冬季时,会把时间调回正常的标准时间。

其实夏令时的英语很有意思,节省日光时间,所以这就很容易记住和明白他的含义了。这里记住UTC就可以了,因为我们使用最多的还是UTC。还有UTC、GMT这些不是时区,是一个标准的统称,UTC+8 这才是一个时区,表示标准时间增加8个小时,就是北京时间了。

时区的处理

Java中引入了ZoneId和ZoneOffset,这两个概念如下:
ZoneId:代表了一个时区的标识符,例如“Europe/Paris”。它是用来识别特定的时区规则的,并且可以用于转换时间点到本地时间。ZoneId可以通过静态方法of来获取,也可以通过时区规则的转换来获得。ZoneId与时区规则相关,这意味着它也包含了关于夏令时(如果该时区有)的信息。如:将一个Instant时间戳转换为本地日期/时间LocalDateTime。

ZoneOffset:是ZoneId的一个具体实现,它表示与UTC/格林尼治时间偏移了多少小时、分钟。ZoneOffset不包含夏令时的信息,它纯粹代表了一个固定的时差,例如“+08:00”代表东八区。ZoneOffset通常用在不需要关心夏令时变化的情况下,如记录日志、事件时间戳等。

ZoneID的使用

时区ZoneId是包含有规则的,实际上描述偏移量何时以及如何变化的实际规则由java.time.zone.ZoneRules定义。ZoneId则只是一个用于获取底层规则的ID。之所以采用这种方法,是因为规则是由政府定义的,并且经常变化,而ID是稳定的。对于API调用者来说只需要使用这个ID(也就是ZoneId)即可,而需无关心更为底层的时区规则ZoneRules,和“政府”同步规则的事是它领域内的事就交给它喽。如:夏令时这条规则是由各国政府制定的,而且不同国家不同年一般都不一样,这个事就交由JDK底层的ZoneRules机制自行sync,使用者无需关心。
ZoneId在系统内是唯一的,它共包含三种类型的ID:

最简单的ID类型:ZoneOffset,它由’Z’和以’+‘或’-‘开头的id组成。如:Z、+18:00、-18:00
另一种类型的ID是带有某种前缀形式的偏移样式ID,例如’GMT+2’或’UTC+01:00’。可识别的(合法的)前缀是’UTC’, ‘GMT’和’UT’
第三种类型是基于区域的ID(推荐使用)。基于区域的ID必须包含两个或多个字符,且不能以’UTC’、‘GMT’、‘UT’ '+‘或’-'开头。基于区域的id由配置定义好的,如Europe/Paris

在Java中使用ZoneId来处理时区。

        // 中国时间:2024-01-21T13:12:57.577
        LocalDateTime chinaTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
        LocalDateTime chinaTime2 = LocalDateTime.now(ZoneId.of("UTC+8"));
        System.out.println(chinaTime);
        System.out.println(chinaTime2);

        // 纽约时间:2024-01-21T00:12:57.580
        LocalDateTime usaTime2 = LocalDateTime.now(ZoneId.of("America/New_York"));
        System.out.println(usaTime2);

这些代号不太好记,可以实时查看sdk,也可以根据时区偏移量来计算。
在这里插入图片描述

ZoneOffset的使用

距离格林威治/UTC的时区偏移量,例如+02:00。值得注意的是它继承自ZoneId,所以也可当作一个ZoneId来使用的,当然并不建议你这么去做,请独立使用。

时区偏移量是时区与格林威治/UTC之间的时间差。这通常是固定的小时数和分钟数。世界不同的地区有不同的时区偏移量。在ZoneId类中捕获关于偏移量如何随一年的地点和时间而变化的规则(主要是夏令时规则),所以继承自ZoneId。

偏移量是能精确到秒的,只不过一般来说精确到分钟已经到顶了。

		// 2024-01-21T13:20:14.987
        LocalDateTime zoneOffsetTime = LocalDateTime.now(ZoneId.ofOffset("UTC", ZoneOffset.ofHours(8)));
        System.out.println(zoneOffsetTime);
让人恼火的夏令时

因为有夏令时规则的存在,让操作日期/时间的复杂度大大增加。但还好JDK尽量的屏蔽了这些规则对使用者的影响。因此:**推荐使用时区(ZoneId)**转换日期/时间,一般情况下不建议使用偏移量ZoneOffset去搞,这样就不会有夏令时的烦恼啦。

第三个问题:MySQL存储时间用什么类型?

在数据库中也有很多存储时间格式,有的使用INT,有的使用DATETIME或者使用TIMESTAMP,甚至有人会使用字符串的日期时间如”2024-01-21 13:00:00“。那么下面我们来看下使用哪种方式存储比较好。

首先,不推荐使用字符串。这是初学者很容易犯的错误,容易直接将字段设置为 VARCHAR 类型,存储"2021-01-01 00:00:00"这样的字符串。当然这样做的优点是比较简单,上手快。但是极力不推荐这样做,因为这样做有两个比较大的问题:

  • 字符串占用的空间大
  • 这样存储的字段比较效率太低,只能逐个字符比较,无法使用 MySQL 提供的日期API
MySQL中的日期类型

MySQL 数据库中常见的日期类型有 YEAR、DATE、TIME、DATETIME、TIMESTAMEP。因为一般都需要将日期精确到秒,其中比较合适的有DATETIMETIMESTAMEP

DATETIME

DATETIME 在数据库中存储的形式为:YYYY-MM-DD HH:MM:SS,固定占用 8 个字节。
从 MySQL 5.6 版本开始,DATETIME 类型支持毫秒,DATETIME(N) 中的 N 表示毫秒的精度。例如,DATETIME(6) 表示可以存储 6 位的毫秒值。

TIMESTAMEP

TIMESTAMP 实际存储的内容为‘1970-01-01 00:00:00’到现在的毫秒数。在 MySQL 中,由于类型 TIMESTAMP 占用 4 个字节,因此其存储的时间上限只能到‘2038-01-19 03:14:07’。

从 MySQL 5.6 版本开始,类型 TIMESTAMP 也能支持毫秒。与 DATETIME 不同的是,若带有毫秒时,类型 TIMESTAMP 占用 7 个字节,而 DATETIME 无论是否存储毫秒信息,都占用 8 个字节。

类型 TIMESTAMP 最大的优点是可以带有时区属性,因为它本质上是从毫秒转化而来。如果你的业务需要对应不同的国家时区,那么类型 TIMESTAMP 是一种不错的选择。比如新闻类的业务,通常用户想知道这篇新闻发布时对应的自己国家时间,那么 TIMESTAMP 是一种选择。Timestamp 类型字段的值会随着服务器时区的变化而变化,自动换算成相应的时间,说简单点就是在不同时区,查询到同一个条记录此字段的值会不一样。

数值型时间戳(INT)

很多时候,我们也会使用 int 或者 bigint 类型的数值也就是时间戳来表示时间。这种存储方式的具有 Timestamp 类型的所具有一些优点,并且使用它的进行日期排序以及对比等操作的效率会更高,跨系统也很方便,毕竟只是存放的数值。缺点也很明显,就是数据的可读性太差了,你无法直观的看到具体时间。

综上,通过对这三个类型的比较,推荐使用TIMESTAMP。我们看看《高性能 MySQL 》中的作者是如何说的:
在这里插入图片描述

结论

当你不知道在数据库中使用哪个时间类型时,就选择TIMESTAMP。

第四个问题:项目国际化,日期时间处理方案。

内容过多,准备专门写一个博客来阐述国际化方案中的时间该怎么处理,从数据库到前端展示等,保持关注。

总结

本文在前三篇的基础上,着重介绍日期时间的原理和概念以及经常用到的一些名词解释。最后把项目中经常遇到的一些问题记录下来,后续如果再遇到其他的问题,也会补充到这里,记得收藏关注。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HCIA——23DNS层次域名空间、域名服务器、域名解析的原理的选择、解答

学习目标: 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议,了解典型网络设备的组成和特点,理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本方法进行…

【笔记】Blender4.0建模入门-3物体的基本操作

Blender入门 ——邵发 3.1 物体的移动 演示: 1、选中一个物体 2、选中移动工具 3、移动 - 沿坐标轴移动 - 在坐标平面内移动 - 自由移动(不好控制) 选中物体:右上的大纲窗口,点击物体名称,物体的轮…

LabVIEW电火花线切割放电点位置

介绍了一个电火花线切割放电点位置分布评价系统,特别是在系统组成、硬件选择和LabVIEW软件应用方面。 本系统由两个主要部分组成:硬件和软件。硬件部分包括电流传感器、高速数据采集卡、开关电源、电阻和导线。软件部分则由LabVIEW编程环境构成&#xf…

2024如何入局云计算?亚麻云助力您成为云专家!一次不过,免费再考

福利派送 2024年伊始,一波又一波的裁员潮又开始啦!还在做传统行业?还在做传统程序员?亦或是对未来依旧迷茫?赶紧趁着行业东风,开始了解入门云计算吧!亚马逊云科技,认证福利免费送&a…

C++——结构体

1,结构体基本概念 结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。像int(整型),浮点型,bool型,字符串型等都是属于系统内置的数据类型。而今天要学习的结构体则是属于我们自定义…

Java前端——HTTP协议中get和post的区别

get 和 post是 HTTP 请求的两种方法 应用场景: 一般 get 请求用于对服务器资源不会产生影响的场景,如请求一个网页的资源 post 请求一般用于对服务器资源会产生影响的情景,如注册用户这一类的操作。 get请求一般用于向服务器请求数据&…

Elastic Stack 8.12:通过对 ES|QL 等的改进增强了向量搜索

作者:来自 Elastic Tyler Perkins, Shani Sagiv, Gilad Gal, Ninoslav Miskovic Elastic Stack 8.12 构建于 Apache Lucene 9.9(有史以来最快的 Lucene 版本)之上,基于我们对标量量化和搜索并发性的贡献,为文本、向量和…

Bert详解

Bert框架 基本架构Embeddingpre-trainingMLM(Mask Language Model)NSP(Next Sentence Prediction) fine-tuning优缺点 基本架构 由Transformer的Encoder层堆叠而来 每个部分组成如下: Embedding Embedding由三种E…

最小生成树(Java实现)

一、Prim算法 Prim算法基本思想为:从联通网络 N{V,E}中某一顶点 v0 出发,此后就从一个顶点在 S 集中, 另一个顶点不在 S 集中的所有顶点中选择出权值最小的边,把对应顶点加入到 S 集 中, 直到所有的顶点都加入到 S 集中…

D-Tale SSRF漏洞复现(CVE-2024-21642)

0x01 产品简介 D-tale 是一个在 2020 年 2 月推出的库, 是 Pandas 数据结构的可视化工具。它具有许多功能,对于探索性数据分析非常方便、支持交互式绘图、3d 绘图、热图、特征之间的相关性、构建自定义列等等。 0x02 漏洞概述 D-Tale 是 Pandas 数据结构的可视化工具。3.9…

swift基础语法

swift学习笔记 参考教程 https://www.runoob.com/swift/swift-data-types.html swift代码规范 https://juejin.cn/post/7129465308376465422 1 环境搭建 必须要有苹果电脑且安装Xcode 2 基本语法 Swift是类型安全的语言,编译时会进行类型检查 import Cocoa var m…

Git学习笔记(第7章):IDEA实现Git操作(VSCode)

目录 7.1 配置忽略文件 7.2 初始化本地库 7.3 添加暂存区、提交本地库 7.4 修改文件 补充:工具栏简介 7.1 配置忽略文件 问题引入 在版本控制系统中,有些文件或目录是不需要纳入版本管理的,比如编译产生的临时文件、日志文件、缓存文件等…

基于springboot+vue的网上购物商城(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

hugo的常规使用操作

hugo的常规使用操作(不断完善中) 找到theme主题中config.toml 一般都会通过theme中复制到自己项目的config.toml中做修改和补充,来完善不同的业务需求 Hugo静态资源载入逻辑 原理 将图片信息放到static中,但是在文章中写的时…

电脑存储位置不够怎么办

电脑内存不够怎么办!!! 我前段时间经常因为电脑D盘内存不够而苦恼(毕竟电脑内存就那么丁点,C盘作为系统盘不能随便下东西的情况下,就只能选择其他盘进 方法一:检查电脑硬盘的分区情况&#xf…

Unity下实现跨平台的RTMP推流|轻量级RTSP服务|RTMP播放|RTSP播放低延迟解决方案

2018年,我们开始在原生RTSP|RTMP直播播放器的基础上,对接了Unity环境下的低延迟播放,毫秒级延迟,发布后,就得到了业内一致的认可。然后我们覆盖了Windows、Android、iOS、Linux的RTMP推送、轻量级RTSP服务和RTSP|RTMP播…

《WebKit 技术内幕》学习之五(3): HTML解释器和DOM 模型

3 DOM的事件机制 基于 WebKit 的浏览器事件处理过程:首先检测事件发生处的元素有无监听者,如果网页的相关节点注册了事件的监听者则浏览器会将事件派发给 WebKit 内核来处理。另外浏览器可能也需要处理这样的事件(浏览器对于有些事件必须响应…

BGP Local-preferenct 、AS-Path、 Origin 综合选路实验

Local-preference: 本地优先级,公认任意,仅能在 AS 内使用(IBGP内传递),不能在EBGP传递,默认值 100,越大越优。用于离开本 AS ,在 IBGP 的入、出方向都可使用&#xff0c…

双端Diff算法

双端Diff算法 双端Diff算法指的是,在新旧两组子节点的四个端点之间分别进行比较,并试图找到可复用的节点。相比简单Diff算法,双端Diff算法的优势在于,对于同样的更新场景,执行的DOM移动操作次数更少。 简单 Diff 算法…

光学期刊1

光学领域的你,如何评价最近发布的光学期刊分区? 如题,附分区表 20240122 知乎 同样先写结论:时代变了,发国产没错的。参考light当年开局多艰难,被各种diss口碑差,很多投一区守门员不中的也…