与Bash相比,Java中的区域设置区分不一致

时间:2018-05-22 14:19:04

标签: java bash date locale simpledateformat

当我尝试使用波兰语格式化日期时,我得到了一致的格式:

new SimpleDateFormat("EEEE", Locale.forLanguageTag("pl-PL")).format(new Date())

结果

wtorek

bash中的结果相同:

LC_ALL=pl_PL
$ date +"%A %b %d"
wtorek maj 22

请注意w中的小写wtorek

当我使用捷克语时,结果是不存在的:

new SimpleDateFormat("EEEE", Locale.forLanguageTag("cs-CZ").format(new Date())

结果

Pondělí

在bash中运行时:

$ LC_ALL=cs_CZ 
$ date +"%A %b %d"
pondělí kvě 21

注意Java结果中的大写P。这是怎么发生的?这是否意味着SimpleDateFormat不使用系统上安装的标准语言环境?

2 个答案:

答案 0 :(得分:3)

Java从最多四个来源获取其语言环境数据(包括不同语言环境中一周的日期名称)。是的,主机操作系统就是其中之一,但不是默认设置。引用the LocaleServiceProvider documentation

  

Java Runtime Environment提供以下四种语言环境提供程序:

     
      
  • “CLDR”:基于Unicode Consortium的CLDR项目的提供商。
  •   
  • “COMPAT”:表示与JDK8之前的JDK版本兼容的区域设置敏感服务(与JDK8相同)   “JRE”)。
  •   
  • “SPI”:表示实现此LocaleServiceProvider类的子类的区域设置敏感服务。
  •   
  • “HOST”:反映用户在底层操作系统中的自定义设置的提供程序。此提供商可能不是   可用,具体取决于Java运行时环境   实施
  •   
  • “JRE”:代表“COMPAT”的同义词。此名称已弃用,将在JDK的未来版本中删除。
  •   

Java 8 JRE是默认设置。我使用的是java.time因为没有人应该对过时的SimpleDateFormat采取问题:

    DateTimeFormatter dayOfWeekFormatter 
            = DateTimeFormatter.ofPattern("EEEE", Locale.forLanguageTag("cs-CZ"));
    LocalDate date = LocalDate.now(ZoneId.of("Europe/Prague"));
    System.out.println(date.format(dayOfWeekFormatter));

在我的Oracle jdk1.8.0_131上运行的输出与您的结果一致(大写S):

  

Středa

我们可以控制通过系统属性使用的语言环境数据。例如,要优先选择CLDR,请使用VM命令行选项-Djava.locale.providers=CLDR,COMPAT运行程序,或在程序开头插入以下行:

    System.setProperty("java.locale.providers", "CLDR,COMPAT");
  

středa

现在我们得到小写s

我的macOS Sierra 10.12.6上的shell只提供Wednesday,所以显然我的操作系统没有捷克语语言环境数据(这听起来很奇怪;可能问题出在其他地方),因此不适合我。您可以尝试将HOST放在上面的区域设置提供程序字符串前面,看看您的内容是否与您的bash一致。

在Java 9及更高版本中,CLDR是默认设置。因此,在jdk9.0.4上运行相同的代码段而不设置任何系统属性也会以小写形式显示星期几:

  

středa

答案 1 :(得分:2)

  

是否意味着SimpleDateFormat不使用系统上安装的标准语言环境

是,未使用系统区域设置,可用的区域设置依赖于JVM / JRE供应商。例如,在JRE目录中检查lib\ext\localedata.jar。提取后,您可以找到反编译为:{/ p>的文件:sun\text\resources\cs\FormatData_cs_CZ.class

public class FormatData_cs extends ParallelListResourceBundle
{
    @Override
    protected final Object[][] getContents() {
        return new Object[][] { { "MonthNames", 
        { "ledna", "\u00fanora", "b\u0159ezna", "dubna", "kv\u011btna", "\u010dervna", "\u010dervence", "srpna", "z\u00e1\u0159\u00ed", "\u0159\u00edjna", "listopadu", "prosince", "" } }, 
        { "standalone.MonthNames", { "leden", "\u00fanor", "b\u0159ezen", "duben", "kv\u011bten", "\u010derven", "\u010dervenec", "srpen", "z\u00e1\u0159\u00ed", "\u0159\u00edjen", "listopad", "prosinec", "" } }, 
        { "MonthAbbreviations", { "Led", "\u00dano", "B\u0159e", "Dub", "Kv\u011b", "\u010cer", "\u010cvc", "Srp", "Z\u00e1\u0159", "\u0158\u00edj", "Lis", "Pro", "" } }, 
        { "standalone.MonthAbbreviations", { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "" } }, 
        { "MonthNarrows", { "l", "\u00fa", "b", "d", "k", "\u010d", "\u010d", "s", "z", "\u0159", "l", "p", "" } },
        { "standalone.MonthNarrows", { "l", "\u00fa", "b", "d", "k", "\u010d", "\u010d", "s", "z", "\u0159", "l", "p", "" } }, 
        { "DayNames", { "Ned\u011ble", "Pond\u011bl\u00ed", "\u00dater\u00fd", "St\u0159eda", "\u010ctvrtek", "P\u00e1tek", "Sobota" } }, 
        { "standalone.DayNames", { "ned\u011ble", "pond\u011bl\u00ed", "\u00fater\u00fd", "st\u0159eda", "\u010dtvrtek", "p\u00e1tek", "sobota" } }, 
        { "DayAbbreviations", { "Ne", "Po", "\u00dat", "St", "\u010ct", "P\u00e1", "So" } }, 
        { "standalone.DayAbbreviations", { "ne", "po", "\u00fat", "st", "\u010dt", "p\u00e1", "so" } }, 
        { "DayNarrows", { "N", "P", "\u00da", "S", "\u010c", "P", "S" } }, 
        { "standalone.DayNarrows", { "N", "P", "\u00da", "S", "\u010c", "P", "S" } },
        { "AmPmMarkers", { "dop.", "odp." } }, 
        { "Eras", { "p\u0159.Kr.", "po Kr." } }, 
        { "short.Eras", { "p\u0159. n. l.", "n. l." } }, 
        { "narrow.Eras", { "p\u0159.n.l.", "n. l." } }, 
        { "NumberElements", { ",", " ", ";", "%", "0", "#", "-", "E", "\u2030", "\u221e", "\ufffd" } }, 
        { "TimePatterns", { "H:mm:ss z", "H:mm:ss z", "H:mm:ss", "H:mm" } }, 
        { "DatePatterns", { "EEEE, d. MMMM yyyy", "d. MMMM yyyy", "d.M.yyyy", "d.M.yy" } }, 
        { "DateTimePatterns", { "{1} {0}" } }, 
        { "DateTimePatternChars", "GuMtkHmsSEDFwWahKzZ" } };
    }
}

并在“DayNames”中包含“Pond \ u011bl \ u00ed”。