java.lang.IllegalArgumentException: SimpleDateFormat中的日期格式字符'Y'非法

57

以下代码:

Calendar now = Calendar.getInstance();
month = now.get(Calendar.MONTH) + 1;
year = now.get(Calendar.YEAR);
System.out.println("Month " + month + " year " + year);
SimpleDateFormat dt1 = new SimpleDateFormat("MMMM YYYY");
e.setMonthnYear(dt1.format(now.getTime()));

部署到服务器后出现以下异常:

java.lang.IllegalArgumentException: Illegal pattern character 'Y'
    java.text.SimpleDateFormat.compile(SimpleDateFormat.java:768)
    java.text.SimpleDateFormat.initialize(SimpleDateFormat.java:575)
    java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:500)
    java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:475)
    iland.employee.EmployeeAction.fetchAllAtted(EmployeeAction.java:169)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:597)

在我的本地主机上,我正在使用JDK v1.8,上述代码运行得非常完美,但是在服务器上不起作用。

我该如何解决这个问题?


2
您需要在服务器上检查Java版本。如果不是Java 8或低于Java 7,则Y将无法在那里工作。 - Mandar Pandit
2
我将YYYY替换为小写的yyyy后,它开始正常工作了。正如在答案中提到的那样,问题可能与Java版本有关。 - vishwa.deepak
6个回答

76

尝试

SimpleDateFormat dt1 = new SimpleDateFormat("MMMM yyyy");

1
由于OP正在使用Java 1.8,因此大写的Y对于周年是有效的。请参考Java 8 SimpleDateFormat - Mandar Pandit
@Evgeniy Dorofeev 只有一个小疑问,javadoc 上说-如果指定了周年 'Y' ,但日历不支持任何周年,则使用日历年 ('y')。所以根据这个,Y 不应该抛出 IllegalArgumentException,对吗? - SparkOn
@M.Sharma 这取决于Java版本,但即使是Java 8并且Y没有抛出异常,它仍具有不同的含义,并且会被错误地解释。 - Evgeniy Dorofeev

38

在本地,您可能正在使用Java 8,因此请检查服务器上的Java版本。如果它小于Java JDK 7,则大写字母Y将无法正常工作。

请参考Java 6 Oracle文档中的SimpleDateFormat

您必须使用小写字母y而不是大写字母Y来书写年份。

例如,对于2位数的年份:

 SimpleDateFormat dt1 = new SimpleDateFormat("yy");

对于4位数的年份:

 SimpleDateFormat dt1 = new SimpleDateFormat("yyyy");

如果您正在使用Java 7或以上版本: 您可以使用大写的Y来代表周年份

请参考Java 7 Oracle文档中的SimpleDateFormat


有人能够为非英语母语者解释一下“周年”的概念是什么吗? - Johnny Five
也许这个链接可以帮助了解Java中的周年份是如何工作的。 https://dev59.com/KFsW5IYBdhLWcg3wsY9P - Mandar Pandit
这是什么语言?@MandarPandit。这是因为在一个Android项目中,只有使用pt-BR语言的设备才会崩溃。 - Armando Marques da S Sobrinho

15

Android

文档与实现有所不同。在 API 等级 23 及以下版本中,支持的字符在 SimpleDateFormat 中定义为一个字符串常量。从源代码中可以看到:

static final String PATTERN_CHARS = "GyMdkHmsSEDFwWahKzZLc";

'Y'(周年)未被包含在内,因此模式验证引发异常:

java.lang.IllegalArgumentException: Unknown pattern character 'Y'

当不需要周年行为时,一个快速的解决方法是使用“y”,例如:yyyy-MM-dd

自API级别24开始支持将“Y”作为模式字符。

更新

文档现在列出了模式字符支持的API级别。


7
根据Java文档
If week year 'Y' is specified and the calendar doesn't support any week years,
the calendar year ('y') is used instead. The support of week years can be tested
with a call to getCalendar().isWeekDateSupported().

所以唯一的问题是你的Java版本可能小于1.7,因为JRE1.7添加了“Y”模式用于周年,而在JRE1.6中没有这种模式。
或者简单点,使用 y 替代 Y 更加保险。
还有一个要点,总是尽量使用locale更为保险。
SimpleDateFormat dt1 = new SimpleDateFormat("MMMM yyyy",java.util.Locale.ENGLISH);

2
我从Java文档中获取了这个表格。
Letter  Date or Time Component  Presentation    Examples
G   Era designator  Text    AD
y   Year    Year    1996; 96
M   Month in year   Month   July; Jul; 07
w   Week in year    Number  27
W   Week in month   Number  2
D   Day in year Number  189
d   Day in month    Number  10
F   Day of week in month    Number  2
E   Day in week Text    Tuesday; Tue

在你的情况下,只需将"Y"替换为"y",你可以在这里查看文档


我猜是因为那些投反对票的人认为它与问题无关。我同意这个观点。 - Stephen C

0

来自java.text.SimpleDateFormat

Letter  Date or Time Component  Presentation    Examples 
y       Year                    Year            1996; 96
Y       Week year               Year            2009; 09

您在调用SimpleDateFormat()时,请求的是周年而不是年份


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接