在Java中,Locale
定义了与人们希望如何看待事物相关的事物(如货币格式、月份名称和一周开始的时间(。
当解析一个月的名称(使用DateTimeFormatter
(时,它开始变得棘手。
如果使用Locale.US
或Locale.ENGLISH
,则September的缩写为Sep
。
如果您使用Locale.UK
,那么September在Java 11中也有缩写Sep
。。。但当您尝试Java17时,它有Sept
(因为我问它是否正确的Unicode CLDR端的更改(。
结果是,在尝试使用Java17进行构建时,我的测试开始失败。
我当前的代码使用Locale.UK
而不是Locale.ENGLISH
的原因是,在Java中,Locale.ENGLISH
实际上不仅是英语,而且是非ISO美国人定义一周的方式(他们使用周日作为一周的第一天(。我想要ISO的方式。
简单地说:
WeekFields.ISO
=WeekFields.of(Locale.UK)
=WeekFields[MONDAY,4]
WeekFields.of(Locale.ENGLISH)
=WeekFields.of(Locale.US)
=WeekFields[SUNDAY,1]
所以从Java17开始,我还没能找到一个正确工作的内置Locale。
在我看来,我必须选择Locale.ENGLISH
并更改WeekFields
,或者选择Locale.UK
并更改九月的简称以满足我的需要。
我的问题是如何做到这一点(在Java 17中(?
或者有更好的方法来解决这个问题吗?
更新1:
- 我已经收到Unicode人员的反馈,他们表示en_GB改为使用Sept而不是Sep是一个错误,因为这是它在英国应该缩写的方式
所以我似乎不仅需要一个接受";9月;而是一个将接受";9月";以及";9月;英语。
更新2:
- 我调整了我的代码,在出现解析异常的情况下,它将尝试将假设的输入("Sep"(更改为当前选择的位置喜欢的内容。这并不是涵盖所有的案例,而是针对我的具体情况涵盖了足够多的案例。对于那些感兴趣的人:我的承诺
我找到了一种使用SPI处理此问题的方法。
我在这里记录了一种可能对其他人有效的可能性(它不适用于我的上下文(。
作为一个实验,我创建了一个类:
package nl.basjes.parse.httpdlog.dissectors.locale;
import java.util.Locale;
import java.util.spi.CalendarDataProvider;
import static java.util.Calendar.MONDAY;
public class CalendarDataProviderISO8601 extends CalendarDataProvider {
public static final Locale ENGLISH_ISO = new Locale("en", "", "ISO");
@Override
public int getFirstDayOfWeek(Locale locale) {
return MONDAY;
}
@Override
public int getMinimalDaysInFirstWeek(Locale locale) {
return 4;
}
@Override
public Locale[] getAvailableLocales() {
return new Locale[]{ENGLISH_ISO};
}
}
和带有的文件CCD_ 21
nl.basjes.parse.httpdlog.dissectors.locale.CalendarDataProviderISO8601
因为这只是"无区域"的变体;英语";它将从";英语";并把上面的类放在上面。
虽然这是有效的,我不能使用它。
问题是尽管http://openjdk.java.net/jeps/252描述了CCD_ 22,当前的现实是由于CCD_。
因此,要使用此构造,类必须在启动时位于类路径中,并且必须将命令行选项-Djava.locale.providers=CLDR,COMPAT,SPI
传递给JVM。
鉴于我的图书馆(https://github.com/nielsbasjes/logparser/(也用于这样的情况(如ApacheFlink/Beam/Drill/Pig(,即类以更动态的方式(序列化并传输到已经运行的JVM(传输到无法使用此构造的多台机器。
我目前还不知道在Java中有什么dynamic
方法可以做这样的事情。