SimpleDateFormat具有本地化模式的非法模式字符错误

Bob*_*hur 6 java localization simpledateformat

我正在尝试理解一些SimpleDateFormat代码.特别是我试图在SimpleDateFormat中使用本地化的模式字符串.来自javadoc:

SimpleDateFormat还支持本地化的日期和时间模式字符串.在这些字符串中,上述模式字母可以用其他依赖于语言环境的模式字母替换.

它还指定了一个SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols)构造函数:

使用给定的模式和日期格式符号构造SimpleDateFormat.

但是,尽管getLocalPatternChars()实例呈现了预期的模式字符,但SimpleDateFormat的构造函数拒绝包含这些字符的模式:

public void run() {
    Locale loc = new Locale("de", "de");
    DateFormatSymbols dfs = new DateFormatSymbols(loc);
    String sym = dfs.getLocalPatternChars();
    System.out.println(sym);
    SimpleDateFormat datefmt = new SimpleDateFormat("tt.MM.uuuu", dfs);
}
Run Code Online (Sandbox Code Playgroud)

产生输出:

GuMtkHmsSEDFwWahKzZ
Exception in thread "main" java.lang.IllegalArgumentException: Illegal pattern character 't'
    at java.text.SimpleDateFormat.compile(SimpleDateFormat.java:845)
    ...
Run Code Online (Sandbox Code Playgroud)

如果我用" ... new SimpleDateFormat("tt.MM.uuuu", loc);" 替换最后一行,我得到相同的输出.

另一方面,如果我使用任何Anglicized模式字符串创建SimpleDateFormat实例,然后调用" applyLocalizedPattern("tt.MM.uuuu")",则接受本地化模式.

所以似乎不能在SimpleDateFormat的构造函数中使用本地化的模式字符串,并且需要这两步初始化.这是故意的行为吗?

Men*_*ild 6

不幸的是,关于如何处理本地化模式的文档很糟糕。所以我研究了源代码并进行了自己的调查。结果:

SimpleDateFormat接受模式字符串的构造函数仅指未本地化的模式字符,其定义记录在 class 的 javadoc 头文件中SimpleDateFormat。这些未本地化的模式字符也被定义为常量DateTimeFormatSymbols

/**
 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
 * All locales use the same these unlocalized pattern characters.
 */
static final String  patternChars = "GyMdkHmsSEDFwWahKzZYuXL";
Run Code Online (Sandbox Code Playgroud)

为了使用本地化模式,需要三个步骤(例如“tt.MM.uuuu”,你认为是德语——但不是德语,它应该是“TT.MM.JJJJ”——错误的 JDK 资源示例):

  1. 通过 定义本地化的模式字符DateFormatSymbols.setLocalPatternChars(...)
  2. 在您的SimpleDateFormat-object上使用自定义的日期格式符号。
  3. 通过应用本地化的日期时间模式 SimpleDateFormat.applyLocalizedPattern(...)

然后本地化的模式将被转换为内部和官方模式字符定义。

用法示例(使用正确的德语模式 TT.MM.JJJJ):

SimpleDateFormat sdf = new SimpleDateFormat(); // uses default locale (here for Germany)
System.out.println(sdf.toPattern()); // dd.MM.yy HH:mm
System.out.println(sdf.toLocalizedPattern()); // tt.MM.uu HH:mm

DateFormatSymbols dfs = DateFormatSymbols.getInstance(Locale.GERMANY);
dfs.setLocalPatternChars("GJMTkHmsSEDFwWahKzZYuXL");
sdf.setDateFormatSymbols(dfs);
sdf.applyLocalizedPattern("TT.MM.JJJJ");

System.out.println(sdf.toPattern()); // dd.MM.yyyy
System.out.println(sdf.toLocalizedPattern()); // TT.MM.JJJJ
System.out.println(sdf.format(new Date())); // 20.06.2016
Run Code Online (Sandbox Code Playgroud)

旁注:我已将字符串“GyMdkHmsSEDFwWahKzZYuXL”中适当的模式字符 y 和 d 更改为 J 和 T,以进行本地化定义。

不幸的是,JDK 资源显然不可靠,所以我个人的观点是,整个功能只能以笨拙的方式使用,在实践中并不是很有用。