SONARQUE应该是Unicode而不是java。时间DateTimeFormatter应用于国际日期和时间
关于SonarQube报告的问题的小问题
在一段非常简单的代码中:
Instant.now().atZone(ZoneId.systemDefault()).toLocalDateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"))
我被一件对我来说很奇怪的事情所困扰: i18nJava:V1009
Unicode ICU and not java.time.DateTimeFormatter should be used for international dates and times
Java's DateTimeFormatter is quite error prone prior to Java version 9. Version 9 and greater with Unicode CLDR data is much improved, but still has errors for key locales. For ideal results, use Unicode ICU DateTimePatternGenerator.
Noncompliant Code Example
Locale userPreferredLocale = Locale.forLanguageTag("zh-Hans");
...
DateTimeFormatter mediumFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(userPreferredLocale);
Compliant Solution
import com.ibm.icu.text.DateTimePatternGenerator;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.ULocale;
...
ULocale userPreferredLocale = ULocale.forLanguageTag("zh-Hans");
...
DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(userPreferredLocale);
//pattern for com.ibm.icu.text.DateFormat.FULL="MMM DD,YYYY,h:mm A"
SimpleDateFormat sdf = new SimpleDateFormat(dtpg.getBestPattern("MMM dd, YYYY, h:mm A"), uloc);
我使用的是Java11,希望避免导入这个IBM包。 我很不确定当前的问题是什么(到目前为止代码工作正常)
但我确实对解决这个问题很感兴趣。请问有没有一个“好办法”来实现它
我将理解以下评论: “禁用SonarQube,禁用此规则,不要过多关注那些假阳性,不要过多地重视分析工具等”
但我对如何解决这个“Unicode ICU而不是java.time.DateTimeFormatter应该用于国际日期和时间”很感兴趣
多谢各位
# 1 楼答案
tl;博士
别担心。只需检查一下^{} 生成的典型日期时间格式文本是否满足用户在您支持的任何地区的期望。如果是这样,就不需要让IBM的ICU图书馆参与进来
让我们来看看java。时间自动本地化表示日期时间值的文本
细节
仅供参考,Sonar消息指的是UnicodeCLDR在基于Java 9及更高版本的OpenJDK的Java实现中成为默认语言环境资源的时间。见JEP 252: Use CLDR Locale Data by Default。Java 10带来了further support
你说:
我相信这不是代码工作的问题
问题是本地化是否适用于区域设置
日期时间值的格式因人类语言、文化和亚文化的不同而有很大差异。我们讨论的是翻译的单词,以及标点符号、缩写、元素顺序、大小写等规则。跟踪所有这些本地化信息需要大量数据。最重要的是,他们改变了。文化在变化,学者的理解也在变化
OpenJDK for Java 8及更早版本中默认使用的此类语言环境数据的实现相对有限且肤浅,没有覆盖许多子文化
相比之下,Unicode联盟管理的CLDR规模庞大且详细,涵盖了许多亚文化。早期版本的OpenJDK包含CLDR的副本。但只有在Java9中,它才成为默认的语言环境资源,首先在那里进行查找
也许声纳信息是说
java.time.DateTimeFormatter
在特定亚文化的细微差别方面存在一些问题。但我没有听说过。如果您担心的话,可以查看OpenJDK问题跟踪程序➥ 我不会担心的。如果你知道你的应用程序将只用于少数特定的地区,请测试这些地区。从每个地区招募一组用户。查看应用程序的典型输出是否符合他们的期望。如果他们满意,写一些单元测试,今天到此为止
请记住,正如我所说,文化规范会随着时间的推移而改变。Unicode联盟跟踪这些变化,根据需要发布新版本的CLDR。当您更新Java实现时,可能会得到CLDR的更新版本。很可能在某一天,在某个语言环境中,当生成表示日期时间的文本时,您可能会得到不同的输出。如果您可能关心这些变化,请编写我上面提到的单元测试
仅供参考,Sonar消息中提到的库是Taligent和IBM构建的International Components for Unicode (ICU)的Java实现,现在位于Unicode联盟:http://site.icu-project.org/
# 2 楼答案
巴兹尔·波尔克已经写下了明智的答案。我谦恭地补充一点
这是对的,也是错的
DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss")
不会产生一种能让跨多种语言和文化的用户满意的格式。不知道这是否是你的目标李>dtpg.getBestPattern("MMM dd, YYYY, h:mm A")
的消息是错误的,因为代码将因java.lang.IllegalArgumentException: Illegal pattern character 'A'
或其他异常而崩溃李>消息称为不符合的代码会产生:
因此,在我不知道比我在Basil Bourque的回答中读到的更多的情况下,我觉得SonarQube规则是一个过时的规则,对Java 8有效,但对Java 11应该忽略它
我建议
正确的方式在很大程度上取决于你设置日期和时间的格式
如果要向用户显示,有两个选项:
如果要与其他系统交换:
Instant.toString()
或OffsetDateTime.toString)
,因为这些方法产生ISO8601李>如果用于存储:更喜欢存储数据时间对象,而不是字符串。例如,使用数据库引擎的
timestamp with time zone
或datetime
数据类型和/或让Hibernate 5保存Instant
或其他日期时间对象代码分析器
TL;DR:代码分析器当然可以帮助我们发现代码中的错误和其他不足之处。他们当然也有一些误报
我确实信任代码分析器。我对SonarQube没有任何经验。我是一个快乐的SpotBugs用户。当我确信代码符合我的要求时,我还会有选择地告诉SpotBugs忽略我编写的某些方法中的一些规则。我非常确信我也会用SonarQube做同样的事情