我们最近开始在生产环境中遇到一个奇怪的错误(测试环境正常)。
java.lang.IllegalArgumentException:非法模式字符'y'
这是由以下代码
引起的SimpleDateFormat dateFormat = (SimpleDateFormat)DateFormat.getDateInstance();
dateFormat.applyLocalizedPattern("yyyy-MM-dd");
例如,当使用'Y'而不是'y'表示年份时,通常会抛出此错误。如上所示,这不是这种情况。我不是100%确定服务器上设置的语言环境。 Linux env LANG设置为“de_DE.UTF_8”,因此可能会使用它。
输入SimpleDateFormat.java的源代码我找到了方法translatePattern(String pattern, String from, String to)
。这会抛出pattern
中的任何字符不存在时提到的异常。在其他计算机上本地调试时,值看起来像这样
pattern =“yyyy-MM-dd”
from =“GyMdkHmsSEDFwWahKzZ”
从服务器上的例外情况可以看出from
中不存在第一个'y'。 from
是从formatData.getLocalPatternChars()
获取的,DateFormatSymbols
是从服务器上的语言环境初始化的{{1}}。
是否有可用的格式没有'y'?这个错误已经开始,没有任何代码更改,据我所知,没有更改服务器配置。
答案 0 :(得分:11)
来自SimpleDateFormat javadoc:
SimpleDateFormat还支持本地化的日期和时间模式 字符串。在这些字符串中,上述图案字母可以是 替换为其他依赖于语言环境的模式字母。
在您的情况下,本地是DE,因此本地化模式将是jjjj-MM-tt
。 J
代表Jahr,T
代表Tage。
如果您不想处理本地化模式,只需使用SimpleDateFormat.applyPattern("yyyy-MM-dd")。
答案 1 :(得分:7)
理想情况下,您应该强制执行模式的区域设置,否则您的模式需要针对不同的区域设置进行更改,因为yyyy适用于en_US,jjjj适用于de_DE等。而是仅将yyyy和locale指定为en_US,而不管机器的区域设置。
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
System.out.println(format.format(new java.util.Date()));
正如javadoc所说:
使用给定的模式和默认值构造SimpleDateFormat 给定语言环境的日期格式符号。注意:这个构造函数可能 不支持所有语言环境。要获得完整的覆盖率,请使用工厂方法 DateFormat类。
参数:
pattern:描述日期和时间格式的模式
区域设置:应使用其日期格式符号的区域设置
这样您就不必担心为运行时区域设置选择哪个本地字符串并强制执行一次特定区域设置。