在Java中定制区域设置
在Java中,Locale
定义与人们希望看到事物的方式相关的内容(如货币格式、月份名称和一周开始的时间)。
分析月份名称(带有DateTimeFormatter
)时,开始变得棘手。
如果使用Locale.US
或Locale.ENGLISH
,则九月的缩写为Sep
。
如果您使用Locale.UK
,那么在Java 11中,九月也有缩写Sep
...但当您尝试Java 17时,它有Sept
(因为Unicode CLDR端的变化I asked if this was correct)。
结果是,我的tests在尝试使用Java 17生成时开始失败。
我当前的代码使用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]
所以从Java 17开始,我还找不到能够正常工作的内置区域设置。
在我看来,我必须采用Locale.ENGLISH
并将WeekFields
更改为Locale.UK
,或者采用Locale.UK
将9月的短名称更改为我需要的月份。
我的问题是如何(在Java 17中)做到这一点?
或者是否有更好的方法来解决此问题?
更新1:
- 我已经从Unicode的人那里得到了反馈,他们表示en_gb使用Sept而不是Sep的更改是一个错误,因为这是它在英国应该被缩写的方式。
因此,我似乎不仅需要一个接受";Sep";的解析器,还需要一个可以接受英语的";Sept";和";Sep";混合使用的解析器。
更新2:
- 我调整了我的代码,在出现解析异常的情况下,它将尝试将假定为输入的内容(";Sep";)更改为当前选定的Locate喜欢的内容。这并不包括所有的情况,它涵盖了我的特定情况的足够的情况。 对于感兴趣的人:my commit。
解决方案
我找到了使用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};
}
}
和带有
的文件./src/main/resources/META-INF/services/java.util.spi.CalendarDataProvider
nl.basjes.parse.httpdlog.dissectors.locale.CalendarDataProviderISO8601
因为这只是无区域英语和英语的变体,所以它将从英语和英语中提取所有内容,并将上面的类放在上面。
虽然此方法有效,但我无法使用它。
问题是,尽管http://openjdk.java.net/jeps/252描述了The default lookup order will be CLDR, COMPAT, SPI,
,但当前的实际情况是,由于deprecating the Extension Mechanism
,SPI已从this change中的此列表中删除。
因此,要使用此构造,类必须在启动时位于类路径中,并且命令行选项-Djava.locale.providers=CLDR,COMPAT,SPI
必须传递给JVM。
鉴于我的库(https://github.com/nielsbasjes/logparser/)也用于以更动态的方式(序列化并传输到已经运行的JVM)将类发送到多台计算机的情况(如Apache Flink/Beam/Drill/Pig),此构造不能使用。
我目前不知道在Java中执行此类操作的dynamic
方法。
相关文章